0

我知道我可以創建支持該網址的URL映射MVC URL路由密鑰值對參數

用戶/ IDEX/用戶id/1/的categoryId/ABC

ActionResult Index (String userId, String categoryID) 

我想知道的是,是否有可能將此機制推廣並編寫一個可支持作爲鍵/值對傳遞的基於url的參數的映射。

控制器/動作/ * KEY1/VALUE1/KEY2 /值2 .... *

利用單個映射我需要支持例如所有這些URL

用戶/ idex/userId/1/categoryId/abc

ActionResult Index (String userId, String categoryID) 

category/idex/CATID/1/的groupId/2

ActionResult Index (catId String, String groupId) 

類別/ IDEX/CATID/1/的groupId/2

ActionResult Index (catId String, String groupId) 

新聞/細節/ NewSID的/1/groupId/2/option/3

ActionResult Index (newsid String, String groupId, String optionId) 
+0

我認爲一個方式可以是創建RouteDataValueProvider –

回答

0

我做到了!

使用自定義值提供程序!

我改變的值對參數

的格式從KEY1/VALUE1/KEY2/VALUE2

到更清晰鍵1 =值;鍵2 =值

public class KeyValuePairValueProviderFactory : ValueProviderFactory { 
    public override IValueProvider GetValueProvider(ControllerContext controllerContext) { 
     return new KeyValuePairValueProvider(controllerContext.HttpContext.Request.Path); 
    } 
    private class KeyValuePairValueProvider : IValueProvider { 
     private readonly Dictionary<String,String> _valuesDictionary = new Dictionary<String,String>(); 

     public bool ContainsPrefix(string prefix) { 
      return true; 
     } 

     public KeyValuePairValueProvider(String rawUrl) { 
      // The url have to be in this format 
      // controller/key=value 
      // controller/key=value/ 
      // controller/key=value?op=1 
      // controller/key=value/?op=1 
      // controller/action/key=value 
      // controller/action/key=value?op=1 
      // controller/action/key=value/?op=1 
      // controller/action/key=value;key=value 
      // controller/action/key=value;key=value?op=1 
      // controller/action/key=value;key=value/?op=1 
      String parameters = ""; 

      // removing the querystring 
      if(rawUrl.Contains("?")){ 
       // i split on the ? and take the first part 
       rawUrl = rawUrl.Split('?')[0]; 
      } 


      // controller/key=value 
      // controller/action/key=value 
      // controller/action/key=value/ 
      // controller/action/key=value;key=value 


      // check if the url without the querystring contains a = simbol 
      // if yes I proceed into extract parameters 
      if(rawUrl.Contains("=")){ 

       // removing last slash 
       if (rawUrl.LastIndexOf('/')+1 == rawUrl.Length) { 
        rawUrl = rawUrl.Remove(rawUrl.LastIndexOf('/')); 
       } 


       int startIndex = rawUrl.LastIndexOf("/")+1; 
       int endIndex = rawUrl.Length; 
       int lenght = endIndex-startIndex; 
       parameters = rawUrl.Substring(startIndex,lenght); 
       String[] pairs = parameters.Split(';'); 
       foreach (String pair in pairs) { 
        String key = pair.Split('=')[0]; 
        String value = pair.Split('=')[1]; 
        _valuesDictionary.Add(key, value); 
       } 
      } 
     } 

     public ValueProviderResult GetValue(string key) { 
      if (_valuesDictionary.ContainsKey(key)) { 
       return new ValueProviderResult(
        _valuesDictionary[key] 
        , _valuesDictionary[key] 
        , CultureInfo.CurrentUICulture); 
      } else { 
       return null; 
      } 
     } 
    } 
} 

當然,它可以使用正則表達式。

然後,在Global.asax

public static void RegisterRoutes(RouteCollection routes) { 
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 
routes.MapRoute(
    "Default", // Route name 
    "{controller}/{action}/{*catchall}", // URL with parameters 
    new { controller = "Home", action = "Index" } // Parameter defaults 
    ); 
} 

protected void Application_Start() { 
    AreaRegistration.RegisterAllAreas(); 

    RegisterGlobalFilters(GlobalFilters.Filters); 
    RegisterRoutes(RouteTable.Routes); 

    ValueProviderFactories.Factories.Add(new KeyValuePairValueProviderFactory()); 
} 
+0

出於好奇,如何將這項工作與你的控制器組合? ActionResult Index的方法包含哪些參數url Home/Index/Id = 1; Name = Thor以及如果用戶輸入Home/Index/description = working; Name = Thor會發生什麼? –

+0

使用標準路由配置可能會出現一些參數名稱爲「id」的問題,所以我更改{* catchall}中的{id} Home/Index/Id = 1; Name = Thor將映射到(in​​t Id,字符串名稱) Home/Index/description = working;名稱= Thor將映射到(字符串描述,字符串名稱)或(字符串名稱,字符串描述)。參數的順序並不重要 –

+0

我明白,但是你只能在同一個控制器中有一個ActionResult Index(參數),否則會拋出AmbiguousMethodException。所以* Home/Index/Id = 1; Name = Thor *是唯一可行的路線。在那種情況下,我並沒有看到有太多可能定義參數名稱的價值。但是如果你在另一個控制器中有索引(不同的參數),並且你不想使用* News/Detail/1?groupId = 2&optionId = 3 *或者註冊一條支持* News/Detail/1/2/3 *,那麼是的,這可能是一個可能的解決方案。 (重新發明輪子?) –

0

我不認爲你可以這樣做的,但你可以這樣做:

routes.MapRoute(
    "Grouped", // Route name 
    "{controller}/{action}/{id}/{groupid}", // URL with parameters 
    new { controller = "Home", action = "Index", id = UrlParameter.Optional, groupid = UrlParameter.Optional } // Parameter defaults 
); 

但後來你想用這個動作,有方法應該被定義爲

ActionResult ActionName (string id, string groupid) 

給予新聞/細節/ 1/2類別/索引/ 1/2

+0

自定義這不是我所需要 –