An ASP.NET route with an arbitrary number of key-value pairs - is this possible?

I would like to handle such URLs:

/Id/Key1/Value1/Key2/Value2/Key3/Value3/ 

Now I have set up a rule similar to this:

 /{id}/{*parameters} 

The parameters object is passed as a single string to all actions that participate in the formation of the response. This really works, but I have a few problems with it:

  • Each action should resolve string for itself. Of course, I made an extension method that turns string into Dictionary<string, string> , but I would prefer the dispatch mechanism to give my methods a Dictionary<string, string> directly or, even better, the actual pairs as separate arguments.
  • Links to actions will still add parameters in the traditional format ( ?Key1=Value1 ). I think I could write specialized helpers with my preferred format, but I would prefer a way to make existing overloads conform to the routing rule.

Is there any way to do this?

+4
source share
2 answers

You can write your own route:

 public class MyRoute : Route { public MyRoute() : base( "{controller}/{action}/id/{*parameters}", new MvcRouteHandler() ) { } public override RouteData GetRouteData(HttpContextBase httpContext) { var rd = base.GetRouteData(httpContext); if (rd == null) { return null; } string parameters = rd.GetRequiredString("parameters"); IDictionary<string, string> parsedParameters = YourExtensionMethodThatYouAlreadyWrote(parameters); rd.Values["parameters"] = parsedParameters; return rd; } public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { object parameters; if (values.TryGetValue("parameters", out parameters)) { var routeParameters = parameters as IDictionary<string, object>; if (routeParameters != null) { string result = string.Join( "/", routeParameters.Select(x => string.Concat(x.Key, "/", x.Value)) ); values["parameters"] = result; } } return base.GetVirtualPath(requestContext, values); } } 

which can be registered as follows:

 public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.Add("my-route", new MyRoute()); routes.MapRoute( "Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } 

and now your actions with the controller can take the following parameters:

 public ActionResult SomeAction(IDictionary<string, string> parameters) { ... } 

As for creating links following this pattern, it is as simple as:

 @Html.RouteLink( "Go", "my-route", new { controller = "Foo", action = "Bar", parameters = new RouteValueDictionary(new { key1 = "value1", key2 = "value2", }) } ) 

or if you want <form> :

 @using (Html.BeginRouteForm("my-route", new { controller = "Foo", action = "Bar", parameters = new RouteValueDictionary(new { key1 = "value1", key2 = "value2" }) })) { ... } 
+4
source

Write your own binder for a specialized dictionary. If you have one, there is no need to parse the string in each action method.

+1
source

Source: https://habr.com/ru/post/1487738/


All Articles