2012-11-28 165 views
3

一個組成名爲控制器我需要映射這樣的網址:如何自定義路由動態URL映射到ASP.NET MVC3

/股票/風險 - >StockRiskController.Index()

/股票/風險/ ATTR - >StockRiskController.Attr()

/srock /風險/圖 - >StockRiskController.Chart()

...

/債券/性能 - >BondPerformanceController.Index()

/鍵/性能/ ATTR - >BondPerformanceController.Attr()

/鍵/性能/圖表 - >BondPerformanceController.Chart() ...

第一部分是動態的,但可枚舉的,所述第二部分具有唯一的兩種選擇(風險)。

現在我知道只有兩種方式:

  1. 訂做的ControllerFactory(似乎overkilled或複雜)
  2. 硬編碼的所有組合,因爲它們是枚舉(醜陋的)。

我可以用routes.MapRoute來實現嗎?或者任何其他方便的方式?

+0

據我所知,你的最後一部分是你的行動,所以我認爲你可以使用這樣的東西。 {controller}/*/{action}在地圖路由中。那麼,我知道這是行不通的,但這是一個開始。 –

+0

@OnurTOPAL,你說得對。但是,因爲我們已經有了一個可操作的版本,其中包含像「BondPerformance/Index | Attr | ...」這樣的醜陋網址,我們只是想在不影響任何邏輯的情況下更改網址。所以我認爲我應該對路由做些什麼。 –

+0

我認爲,如果您希望避免爲每個「債券/股票/風險」業績組合編制路線,選項#1是您唯一的選擇。 –

回答

2

有一個很好的解決方案基於IRouteConstraint。首先我們要創建新的路線映射:

routes.MapRoute(
    name: "PrefixedMap", 
    url: "{prefix}/{body}/{action}/{id}", 
    defaults: new { prefix = string.Empty, body = string.Empty 
        , action = "Index", id = string.Empty }, 
    constraints: new { lang = new MyRouteConstraint() } 
); 

下一步是創建我們的約束。之前,我將介紹一些方法如何檢查相關如上所述 - 兩個列表有可能的值,但邏輯可以調整

public class MyRouteConstraint : IRouteConstraint 
{ 
    public readonly IList<string> ControllerPrefixes = new List<string> { "stock", "bond" }; 
    public readonly IList<string> ControllerBodies = new List<string> { "risk", "performance" }; 
    ... 

現在Match方法,因爲我們需要

public bool Match(System.Web.HttpContextBase httpContext 
     , Route route, string parameterName, RouteValueDictionary values 
     , RouteDirection routeDirection) 
{ 
    // for now skip the Url generation 
    if (routeDirection.Equals(RouteDirection.UrlGeneration)) 
    { 
     return false; 
    } 

    // try to find out our parameters 
    string prefix = values["prefix"].ToString(); 
    string body = values["body"].ToString(); 

    var arePartsKnown = 
     ControllerPrefixes.Contains(prefix, StringComparer.InvariantCultureIgnoreCase) && 
     ControllerBodies.Contains(body, StringComparer.InvariantCultureIgnoreCase); 

    // not our case 
    if (!arePartsKnown) 
    { 
     return false; 
    } 

    // change controller value 
    values["controller"] = prefix + body; 
    values.Remove("prefix"); 
    values.Remove("body"); 

    return true; 
} 
將調整路由

你可以玩這個方法更多,但概念現在應該清楚。

注:我喜歡你的方法。有時候,擴展/調整路由,然後轉到代碼和「修復名稱」更重要。類似的解決方案在這裏工作:Dynamically modify RouteValueDictionary

+0

就像一個魅力。我不知道約束可以有機會改變RouteValueDictionary。非常感謝。 –