2015-02-10 20 views
3

使用帶有路由名稱的@Html.RouteLink只是指示路由引擎使用該名稱的路由。這很容易理解,而且顯然任何寫博客條目或文檔的人都會試圖解釋RouteLink。未提供路由名稱時,使用RouteLink生成URL的方法是什麼?

我明白,這是首選的方法,我也一直使用RouteLink的路由名稱,但我想知道它是如何工作的,當我們不知道時,我無法找到任何真正的好信息。因此,該方法的問題是:

public static MvcHtmlString RouteLink(
    this HtmlHelper htmlHelper, 
    string linkText, 
    RouteValueDictionary routeValues 
) 

,並在MSDN上,it's not explained at all所有有趣的東西是一致的。

Haacked.com has examples of using RouteLink以這種方式:

routes.MapRoute(
    name: "Test", 
    url: "code/p/{action}/{id}", 
    defaults: new { controller = "Section", action = "Index", id = "" } 
); 

routes.MapRoute(
    name: "Default", 
    url: "{controller}/{action}/{id}", 
    defaults: new { controller = "Home", action = "Index", id = "" } 
); 

@Html.RouteLink("Test", new {controller="section", action="Index", id=123}) 

@Html.RouteLink("Default", new {controller="Home", action="Index", id=123}) 

當我閱讀,我認爲這是一個錯字,這兩個實際上綁定到「默認」,但沒有它的實際工作。與文本「測試」的鏈接產生爲https://localhost:44301/code/p/Index/123

這似乎是「錯誤的」,因爲對於我來說,默認值通常在沒有提供時使用,但在這裏它們被用作生成過程中的查找值。這很奇怪和鬆散,我不記得曾經這樣做過,也不能想到爲什麼我會這樣做。

如果我這樣做:

@Html.RouteLink("Test", new {controller="sectionA", action="Index", id=123}) 

它不工作,但如果我這樣做:

@Html.RouteLink("Test", new {controller="section", action="IndexA", id=123}) 

它仍然這樣做似乎只有控制值是顯著,但它是完全只要生成的網址一直未使用。

https://localhost:44301/code/p/Index/123

在Haacked.com,菲爾說:

甚至還有更多的細節我已經掩蓋了具有與 路由的默認值是如何計算到URL代做。這是另一次 的主題,但它解釋了爲什麼不通過 路由到具有不帶參數的URL的控制器操作時遇到此問題。

但似乎他沒有回到那個話題。我查看了源代碼,但是我深入30個調用,並且漫無目的地進入抽象類,並且我現在無法從符號服務器中單步穿過它。

那麼它就像「控制器名稱變成路由名稱,在URL生成過程中沒有實際路由名稱」一樣簡單?如果是這樣,他們爲什麼要這樣做?

回答

0

我在我的問題中概述的場景中尋找並解釋Professional ASP.NET MVC 4 By Jon Galloway, Phil Haack, Brad Wilson, K. Scott Allen,缺省值不存在於url中,成爲必須提供與RouteLink中的默認值匹配的值的鍵控開關爲了這個鏈接的順序是需要考慮的d匹配網址生成。

所以,如果你有這樣一個路徑:

routes.MapRoute(
    name: "Test", 
    url: "code/p/{action}/{id}", 
    defaults: new { controller = "Section", action = "Index", id = "" } 
); 

然後爲了它被認爲是必須在routelink提供一個控制器=「節」值。 {action}並不重要,因爲它是url的一部分,{controller}本身並不重要。它的任何{parameter}的默認值不在url中。

在我RouteLink

@Html.RouteLink("Test", new {fruit="bananas", action="IndexA", id=123}) 

因此,考慮

routes.MapRoute(
    name: "Test", 
    url: "code/p/{action}/{id}", 
    defaults: new { fruit = "bananas", action = "Index", id = "" } 
); 

我們就需要提供一個水果= 「香蕉」 另外請注意,這不是基於順序。所以它不是第一{parameter}沒有出現在URL中成爲關鍵,這一切都{parameter}在URL中不存在成爲關鍵因此,實際上你可以有一個複合鍵按:

routes.MapRoute(
    name: "Test", 
    url: "code/p/{action}/{id}", 
    defaults: new { fruit = "bananas", insect="honeybee", action = "Index", id = "" } 
); 

你會需要一個RouteLink定義爲下面的比賽:

@Html.RouteLink("Test", new {fruit="bananas", insect="honeybee", action="IndexA", id=123}) 

如果谷歌

詳細看看URL生成

您將獲得解釋此問題的網頁的Google圖書鏈接。我將其稱爲「鍵控開關」,因爲按照流程圖,匹配鍵將爲給定路線打開和關閉路線考慮。

我仍然無法想出一個很好的理由,爲什麼我會在命名路線上做到這一點,因此爲什麼它特別支持。

enter image description here

0

看起來像這樣@Html.ActionLink()@Html.RouteLink做同樣的事情,如果路由名稱沒有通過。

看看下面的方法(找到RouteCollectionExtensions.cs)。 name參數是此處的路由名稱。

internal static VirtualPathData GetVirtualPathForArea(this RouteCollection routes, RequestContext requestContext, string name, RouteValueDictionary values, out bool usingAreas) 
{ 
    if (routes == null) 
    throw new ArgumentNullException("routes"); 
    if (!string.IsNullOrEmpty(name)) 
    { 
    usingAreas = false; 
    return routes.GetVirtualPath(requestContext, name, values); 
    } 
    string areaName = (string) null; 
    if (values != null) 
    { 
    object obj; 
    if (values.TryGetValue("area", out obj)) 
     areaName = obj as string; 
    else if (requestContext != null) 
     areaName = AreaHelpers.GetAreaName(requestContext.RouteData); 
    } 
    RouteValueDictionary values1 = values; 
    RouteCollection routeCollection = RouteCollectionExtensions.FilterRouteCollectionByArea(routes, areaName, out usingAreas); 
    if (usingAreas) 
    { 
    values1 = new RouteValueDictionary((IDictionary<string, object>) values); 
    values1.Remove("area"); 
    } 
    return routeCollection.GetVirtualPath(requestContext, values1); 
} 

您可以看到,如果路由名稱爲null或不是,它會採取不同的操作。

要回答你的問題,@Html.ActionLink()@Html.RouteLink()的行爲將是相同的(它們將根據配置選擇相同的路由),如果路由名稱沒有通過。

更新

我因爲在下面的方法調用,您可以查看正在沿着兩個動作的名稱和控制器的名稱通過了空我不知道控制器名稱如何成爲路線名稱:

public static string GenerateRouteLink(RequestContext requestContext, RouteCollection routeCollection, string linkText, string routeName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes) 
{ 
    return HtmlHelper.GenerateLinkInternal(requestContext, routeCollection, linkText, routeName, (string) null, (string) null, protocol, hostName, fragment, routeValues, htmlAttributes, false); 
} 
+0

感謝您的回答。我已經深深地挖了一下,再深一點。我可能應該在帖子的標題中使用「規則」這個詞,而不是「方法」。我認爲所有這些發揮的實際方法是System.Web.Routing.Route.Match。 – rism 2015-02-10 22:01:35