动态修改RouteValueDictionary

Posted

技术标签:

【中文标题】动态修改RouteValueDictionary【英文标题】:Dynamically modify RouteValueDictionary 【发布时间】:2012-11-05 14:08:07 【问题描述】:

作为this question 的后续,我正在尝试实现自定义路由约束,以便为特定路由动态修改RouteValueDictionary

我已经完成了 95%:我可以根据提供的参数模式匹配任何路由,匹配 url 中指定的操作。此过程的最后一步是覆盖 RouteValueDictionary 以将键重命名为控制器操作的适当参数。

这是我的代码的相关sn-p(整个类将近300行,所以我不想全部添加,但如果需要我可以):

public class CustomRouteConstraint : IRouteConstraint

    public bool Match(HttpContextBase httpContext, Route route, string paramName, RouteValueDictionary values, RouteDirection routeDirection)
    
        if (routeDirection.Equals(RouteDirection.UrlGeneration)) 
            return false;
        

        //this will grab all of the "actual" parameters out of the RVD, excluding action and controller 
        Dictionary<string, object> unMappedList = values.Where(x => x.Key.Contains("param")).OrderBy(xi => xi.Key).ToDictionary(
            kvp => kvp.Key, kvp => kvp.Value);

        string controller = values["controller"] as string;
        string action = values["action"] as string;

        //this method tries to find the controller using reflection
        Type cont = TryFindController(controller);

        if (cont != null) 
            MethodInfo actionMethod = cont.GetMethod(action);

            if (actionMethod != null) 
                ParameterInfo[] methodParameters = actionMethod.GetParameters();

                //this method validates that the parameters of the action that was found match the expected parameters passed in the custom constraint; it also performs type conversion
                if (validateParameters(methodParameters, unMappedList)) 
                    for (int i = 0; i < methodParameters.Length; i++) 
                        values.First(x => x.Key == unMappedList.ElementAt(i).Key).Key = methodParameters.ElementAt(i).Name; 
                        //above doesn't work, but even if it did it wouldn't do the right thing

                        return true;
                    
                
            
        

        return false;
    

这是我使用自定义约束的方式:

routes.MapRoute(
    name: "Default2",
    url: "controller/action/param1-param2",
    defaults: new  controller = "Admin", action = "Index" ,
    constraints: new  lang = new CustomRouteConstraint(new RoutePatternCollection( new List<ParamType>  ParamType.INT, ParamType.INT )) 
);

(我传递给构造函数的基本上是说“要查找的参数模式是两个整数”。所以当调用Match方法时,如果url中指定的动作有两个,它将返回true两个整数参数,与实际参数名称无关。)

那么,有没有办法可以覆盖此请求的 RouteValueDictionary?还是有其他我想念的方法可以做到这一点?

【问题讨论】:

不是 ASP.NET MVC 方面的专家,但我想知道路由字典是否是共享资源,是 C# 中的 static 还是 VB.NET 中的 Shared?如果是这样,那么您可能需要在修改它时使用锁定,因为其他请求可能会在您更改它的同时尝试读取它。 【参考方案1】:

如果我理解正确,问题是什么:

那么,有没有办法可以为此覆盖 RouteValueDictionary 要求?还是有其他我想念的方法可以做到这一点?

我采用了您的解决方案并更改了这些行以替换参数名称:

for (int i = 0; i < methodParameters.Length; i++)

    // I. instead of this

    //values.First(x => x.Key == unMappedList.ElementAt(i).Key)
    //    .Key = methodParameters.ElementAt(i).Name; 
    //above doesn't work, but even if it did it wouldn't do the right thing

    // II. do this (not so elegant but working;)
    var key = unMappedList.ElementAt(i).Key;
    var value = values[key];
    values.Remove(key);
    values.Add(methodParameters.ElementAt(i).Name, value);

    // III. THIS is essential! if statement must be moved after the for loop
    //return true;

return true; // here we can return true

注意:我喜欢你的方法。有时扩展/调整路由然后转到代码并“修复不正确的参数名称”更为重要。当然,它们很可能是不正确的。

这就是关注点分离的力量。

URL 地址是一个地方。 控制器、操作和参数名称不同。 以及具有强大自定义功能的路由...

...作为处理该问题的唯一正确位置。这是关注点分离。不调整动作名称以提供 Url...

【讨论】:

啊...我没想到这么简单!我得到的错误说“集合是只读的”所以我假设任何类型的任何修改都不起作用=显然是一个错误的假设。无论如何,它就像一个魅力 - 我会将整个代码发布到我的另一个问题的解决方案中。非常感谢您的帮助!【参考方案2】:

您可以使用正则表达式轻松地将参数限制为正整数:

private const string IdRouteConstraint = @"^\d+$";

routes.MapRoute(
   name: "Default2",
   url: "controller/action/param1-param2",
   defaults: new  controller = "Admin", action = "Index" ,
   constraints: new  param1 = IdRouteConstraint, param2 = IdRouteConstraint);

正如我在回复您的earlier question 时所说,您不必担心控制器操作中的参数名称。给那些过于有意义的名字会让你陷入困境。

【讨论】:

以上是关于动态修改RouteValueDictionary的主要内容,如果未能解决你的问题,请参考以下文章

如何动态的修改全局的sort

JS 动态修改CSS 样式方法/全局

spring+hibernate集成动态修改表结构,网上要对LocalSessionFactory进行小小的修改

Vue动态修改音频url

如何动态修改约束NSLayoutConstraint

xml动态修改 dom4j修改