2010年7月16日 星期五

如何設定HtmlHelper.GenerateRouteLink、routeName、routeValues與HtmlAttribute

HtmlHelper是MVC中新的而且很好用的物件,我們可以用來產生很多延伸的各種Helpers,其中HtmlHelper.GenerateRouteLink()可以用來產生網頁上很單純Link的HTML碼。


<a href="http://myWebSite/Product/Browse" >產品瀏覽</a>


而本文就是利用HtmlHelper.GenerateRouteLink來達到上述產生Link需求,也藉此說明HtmlHelper.GenerateRouteLink()的使用方式。


Gallardo570-4
From:www.lamborghini.com


在MVC的應用中,我們常會用到需要由程式產生一個Link,而這個Link可由MVC中的Route判別該存取哪一個頁面,例如有一個「賀瑞斯汽車資訊網站」,需要在網頁上產生一個Link,可讓網友點選後,即可連結到產品名稱為Lamborghini的汽車規格資訊頁面。


網址列上我們希望如下顯示:


http://localhost/Product/Details/CarName/Lamborghini


我們當然可以直接以HTML寫成下列的Link:


<a href="http://localhost/Product/Details/CarName/Lamborghini" >藍寶堅尼</a>


但想像一下,假設「賀瑞斯汽車資訊網站」需提供好幾百種車款的詳細資訊,若都是在網頁上直接以HTML寫成好幾百條Link程式碼,這看來不是一件有效率的事,而且維護起來是一件災難。比較適當的方式,就是透過程式與資料庫互動,動態且自動產生很多這類的連結資訊。透過程式與資料庫互動的方法其中之一是我們可以用foreach迴圈方式去讀取資料中Model。CarName的方式,也可以組成很多如下Link,如下。


<a href="http://localhost/Product/Details/CarName/Lamborghini" >藍寶堅尼</a>
網址顯示 http://localhost/Product/Details/CarName/Lamborghini


<a href="http://localhost/Product/Details/CarName/Porsche" >保時捷</a>
網址顯示 http://localhost/Product/Details/CarName/Porsche


另外也可以利用本文所提的HtmlHelper.GenerateRouteLink()的方式,達到上述產生Link需求,尤其是要寫MVC中各種Helpers.GenerateRouteLink()這個方法更是重要。


下面簡單說明GenerateRouteLink所需帶入的各參數與涵義,並舉例說明實際用法讓大家瞭解。


GenerateRouteLink方法


GenerateRouteLink(RequestContext requestContext,
    RouteCollection routeCollection,
    string linkText,
    string routeName,
    RouteValueDictionary routeValues,
    IDictionary(String, Object) htmlAttributes)


下面為GenerateRouteLink需帶入的參數說明,這些來自微軟MSDN文件,不過很可惜,沒有實際範例可供參考,這也是本文想要補足之處。


requestContext
    型別:System.Web.Routing..::..RequestContext
    HTTP 要求的內容。


routeCollection
    型別:System.Web.Routing..::..RouteCollection
    URL 路由的集合。


linkText
    型別:System..::..String
    要顯示的連結文字標題。


routeName
    型別:System..::..String
    用來傳回虛擬路徑之路由的名稱。


routeValues
    型別:System.Web.Routing..::..RouteValueDictionary
    包含路徑參數的物件。


htmlAttributes
    型別:System.Collections.Generic..::..IDictionary<(Of <(<'String, Object>)>)>
    物件,包含項目的 HTML 屬性。


傳回值
型別:System..::..String
HTML 項目,連結至指定的 URL 路由。


重點來了,再提一下,我們是要建立一個HtmlHelpers中的GenerateRouteLink()。如何建立一個HtmlHelpers就暫時不在這裡討論了,大家可到微軟:建立Custom HTML Helpers參考一下基本建立方式。建立HtmlHelpers內的GenerateRouteLink()來自動產生如下這樣的Link,這才是本文所要說明的地方。


http://localhost/Product/Details/CarName/Lamborghini



而每一個參數,我們可實際以下列方式帶入:


requestContext參數:就是指HTTP要求的內容,我們可帶入「helper.ViewContext.RequestContext」。
routeCollection參數:就是指Route的集合,我們可帶入「helper.RouteCollection」,因為這部份是提供給Route使用,故直接帶入這些值即可。
linkText參數:就是Link要出現的文字,在我們「賀瑞斯汽車資訊網站」的例子中,我們要顯示「Lamborghini(藍寶堅尼)汽車規格資訊」這個字串。


string myLinkName= "Lamborghini(藍寶堅尼)汽車規格資訊";


routeName參數:就是我們「必須」寫在Global.asax中,讓網站系統的Route「識別的名稱」,說穿了就是一個字串型態的文字,我們設定如下:


string myRouteName = "CarProducts";


有了這個「識別的名稱」,這樣她(Route)才知道要去使用Global.asax內那組「Route的規則」來處理這條Link要指到哪一個Controller與Action,而在Global.asax內,我們也需加上這組「Route的規則」,讓整串Link產生後,網友在網頁上點選才能真正去執行。這組規則如下。


routes.MapRoute(
    "CarProducts"// Route name
    "Product/Details/CarName/{car_name_id}"// URL with parameters
    new { controller = "Product", action = "Details" } // Parameter defaults
);


routeValues參數:routeValues資料型態是一個<Key,Value>的組合,這個也會在Global.asax中被使用到,就是上述Global.asax中參數car_name_id(就是指Key)與屆時需帶入的資料(就是指Value),以我們「賀瑞斯汽車資訊網站」為例,我們可先直接帶入<"CarName","Lamborghini">這樣的組合。


RouteValueDictionary myRouteValues = new RouteValueDictionary();
myRouteValues.Add("car_name_id",("Lamborghini"));


若是CarName後要帶數值型態的編號:38,也可用下列方式:


myRouteValues.Add("car_name_id",(38));


但是一般我們會自資料庫抓了汽車名稱或編號資料,放入陣列中,讓程式自動產生routeValues中所需的value,如下:


myRouteValues.Add("car_name_id",carNameIDAry[i]);


htmlAttributes參數:就是我們舉例的「http://localhost/Product/Details/CarName/Lamborghini」這個Link要配合名為「car-link-style」的這個cssClass,如下寫法:


IDictionary<string, object> myHtmlAtts= new Dictionary<string, object>();
myHtmlAtts.Add("class", "car-link-style");


或是myHtmlAtts後面直接加上style的各種屬性設定如下寫法:


myHtmlAtts.Add("style", "color:Gray;font-family:Georgia;font-size:20px");


上面已經設定完GenerateRouteLink()所需帶入的各種參數,本範例完整方法與參數呼叫如下,她會回應成一個網頁上的Link字串供網友點選,就是一直在提的「http://localhost/Product/Details/CarName/Lamborghini」。


public static string ShowDetailCar(this HtmlHelper helper)
{
        :
        :
    return HtmlHelper.GenerateRouteLink(helper.ViewContext.RequestContext,
        helper.RouteCollection,
        helper.Encode(myLinkName),
        helper.Encode(myRouteName),
        myRouteValues,
        myHtmlAtts);
}


而上面這個Link產生後,它會對應到Product這個Controller的Details這個Action,在這個Action中,我們可簡單寫成直接給予一個Car的資料,當然Car這個類別須在Models中建立。在正式的網站中,通常Car的資料是從資料庫撈出來的,然後轉成List<Car>的資料.這裡只是示範一筆資料來顯示。注意帶入Details這個Action的參數,名稱要和上述routeValues<Key,Value>參數內的Key值相符合(這裡就是都要名稱為car_name_id),也要和Global.asax內那組我們用到的「識別的名稱」內的參數相同名稱。


public class ProductController : Controller
{
    public ActionResult Details(string car_name_id)
    {
        Car carToDetails = new Car
        {
            CarName = "Lamborghini Gallardo",
            Year = "2004",
            Country = "義大利",
            Exhaust = "4961 cc",
            Speed = "309 km/h"
        };
        return View(carToDetails);
    }
}


實際執行後,自動產生的Link如下第一個圖,點選該Link後,就顯示該車的詳細資料,如下圖二。我們可以看一下圖中網址列的Link,就會直接指到我們本範例中所想建立的「http://localhost/Product/Details/CarName/Lamborghini」這樣型態的連結。


Lamborghini


Lamborghini


小結


網址上顯示「http://localhost/Product/Details/CarName/Lamborghini」這樣的名稱,看來比顯示「http://localhost/Product/Details.aspx?CarName=Lamborghini」還要來得直覺與簡便,這部份也可利用在顯示分頁資料的分頁頁碼字串中,如下:


paging


直覺與相互獨立,這就是ASP.NET MVC2的魅力所在!!

沒有留言:

張貼留言