具有任意数量键值对的ASP.NET路由-是否可能



我想处理这样的URL:

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

现在,我已经建立了一个这样的规则:

/{id}/{*parameters}

parameters对象作为单个string传递给在形成响应中涉及的所有动作。这确实有效,但我有一些问题:

  1. 每个操作都必须为自己解析string。当然,我已经制作了一个扩展方法,将string转换为Dictionary<string, string>,但我更希望调度机制直接为我的方法提供Dictionary<string, string>,或者更好的是,将实际的对作为单独的参数
  2. 操作链接仍将使用传统格式(?Key1=Value1)添加参数。我想我可以用我想要的格式编写专门的助手,但如果有办法让现有的重载遵循上面的路由规则,我更喜欢它

有办法做到以上几点吗

您可以编写一个自定义路由:

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);
    }
}

可以这样注册:

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 }
    );
}

现在你的控制器动作可以采用以下参数:

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

就按照这种模式生成链接而言,它很简单:

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

或者如果您想要<form>:

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

为专用词典编写自己的模型绑定器。如果您有一个,那么就不需要在每个操作方法中解析字符串。

最新更新