动态修改RouteValueDictionary [英] Dynamically modify RouteValueDictionary

查看:87
本文介绍了动态修改RouteValueDictionary的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于这个问题的后续,我想实现一个自定义路由约束,以动态修改 RouteValueDictionary 的具体路线。

As a followup of this question, I'm trying to implement a custom route constraint in order to dynamically modify the RouteValueDictionary for a specific route.

我是那里的方式95%:我可以匹配的基础上匹配的URL指定的动作所提供的参数模式的路线。该方法的最后一步是覆盖RouteValueDictionary到键作为用于控制器的动作相应的参数重命名

I'm 95% of the way there: I can match any route based on the supplied parameter pattern matching the action specified in the url. The very last step of this process is to overwrite the RouteValueDictionary to rename the keys as the appropriate parameters for the controller action.

下面是我的code的相关片段(整个班级几乎是300线,所以我不希望添加所有的,但如果需要的话我):

Here's the relevant snippet of my code (the entire class is almost 300 lines so I don't want to add all of it, but I can if needed):

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

和这里的我怎么使用自定义约束:

And here's how I use the custom constraint:

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

(我正在传递到构造基本上是说参数的模式是寻找两个整数的。所以,当匹配方法被调用时,它会返回true如果URL指定的动作有两个两个整数参数,而不管实际参数名称。)

(What I'm passing into the constructor is basically saying "The parameter pattern to look for is two integers". So when the Match method is called, it will return true if the action specified in the url has two two integer parameters, regardless of the actual parameter names.)

那么,有没有一种方法,我可以覆盖RouteValueDictionary这个要求吗?还是有一些其他的方式,我可以做到这一点,我失踪?

So, is there a way I can overwrite the RouteValueDictionary for this request? Or is there some other way I can do this that I'm missing?

推荐答案

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

If I do understand correctly what is the question:

那么,有没有一种方法,我可以覆盖RouteValueDictionary此
  请求?还是有一些其他的方式,我可以做到这一点,我失踪?

So, is there a way I can overwrite the RouteValueDictionary for this request? Or is there some other way I can do this that I'm missing?

我已经采取了您的解决方案,改变了这些线路更换参数名称:

I've taken your solution and changed these lines to replace parameter names:

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

注意:我很喜欢你的方法。有时它只是更重要的是扩展/调整路由然后转到code和修正不正确的参数名。当然,他们最有可能不是不正确。

NOTE: I like your approach. Sometimes it is simply much more important to extend/adjust routing then go to code and "fix incorrect parameter names". And of course, they are most likely NOT incorrect.

这是值得关注的分离的力量。

And here is the power of Separation of concern.


  • URL地址是同一个地方。

  • 控制器,动作和参数名称等之一。

  • 和路由具有强大的自定义...

...是唯一的正确的地方来处理。这是一个令人关注的分离。不调整动作名称的服务网址...

...as the only correct place where to handle that. This is separation of concern. Not tweaking the action names to serve Url...

这篇关于动态修改RouteValueDictionary的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆