【问题标题】:String URL to RouteValueDictionaryRouteValueDictionary 的字符串 URL
【发布时间】:2010-12-01 16:19:49
【问题描述】:

是否有将字符串 URL 转换为 RouteValueDictionary 集合的简单方法?像UrlToRouteValueDictionary(string url)这样的一些方法。

我需要这样的方法,因为我想根据我的路由设置“解析” URL,修改一些路由值并使用 urlHelper.RouteUrl() 根据修改后的 RouteValueDictionary 集合生成字符串 URL。

谢谢。

【问题讨论】:

    标签: asp.net-mvc


    【解决方案1】:

    这是一个不需要模拟的解决方案:

    var request = new HttpRequest(null, "http://localhost:3333/Home/About", "testvalue=1");
    var response = new HttpResponse(new StringWriter());
    var httpContext = new HttpContext(request, response);
    var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
    var values = routeData.Values;
    // The following should be true for initial version of mvc app.
    values["controller"] == "Home"
    values["action"] == "Index"
    

    希望这会有所帮助。

    【讨论】:

    • Piotr,非常感谢您的帮助。这个解决方案看起来很棒
    • 有人已经写过这个:Creating a RouteData instance from a URL
    • @david.s 我对您发布的解决方案有疑问。它无法从查询字符串中分离出路由值。 Piotr 的解决方案效果很好。
    • +10!有没有办法将它放入 request.RequestContext.RouteData 中?我有一个作用于 RequestContext.RouteData 的扩展方法,但它与上面的 routeData 不匹配。
    • @Piotr - 谢谢。此代码有效,并允许我根据引用 URL 进行一些路由 - 任务完成!但是,我只能让代码在应用程序的上下文中运行,但永远不能在我的 Visual Studio 单元测试的上下文中运行。我正在从 RouteConfig 填充 RouteTable,但是,当调用 GetRouteData 方法时,我仍然得到 NullReferenceException。
    【解决方案2】:

    您需要创建一个模拟的 HttpContext,因为路由约束需要它。

    这是我用来对我的路由进行单元测试的示例(它是从Pro ASP.Net MVC framework 复制的):

            RouteCollection routeConfig = new RouteCollection();
            MvcApplication.RegisterRoutes(routeConfig);
            var mockHttpContext = new MockedHttpContext(url);
            RouteData routeData = routeConfig.GetRouteData(mockHttpContext.Object);
            // routeData.Values is an instance of RouteValueDictionary
            //...
    

    【讨论】:

    • 谢谢,这个解决方案看起来很有趣。但遗憾的是,没有不需要模拟的“轻量级”方法,因为我在单元测试中使用 Mocks 而不是在一般代码中。看起来我应该这样做。
    • 我也有类似的顾虑,最后决定在请求之间传递序列化的 RouteCollection。
    【解决方案3】:

    我不会依赖前面示例中的 RouteTable.Routes.GetRouteData,因为在这种情况下,您可能会丢失一些值(例如,如果您的查询字符串参数不完全适合任何已注册的映射路由)。此外,我的版本不需要模拟一堆请求/响应/上下文对象。

    public static RouteValueDictionary UrlToRouteValueDictionary(string url)
    {
        int queryPos = url.IndexOf('?');
    
        if (queryPos != -1)
        {
            string queryString = url.Substring(queryPos + 1);
            var valuesCollection = HttpUtility.ParseQueryString(queryString);
            return new RouteValueDictionary(valuesCollection.AllKeys.ToDictionary(k => k, k => (object)valuesCollection[k]));
        }
    
        return new RouteValueDictionary();
    }
    

    【讨论】:

      【解决方案4】:

      这是一个不需要实例化一堆新类的解决方案。

      var httpContext = context.Get<System.Web.HttpContextWrapper>("System.Web.HttpContextBase");
      var routeData = System.Web.Routing.RouteTable.Routes.GetRouteData(httpContext);
      var values = routeData.Values;
      var controller = values["controller"];
      var action = values["action"];
      

      owin 上下文包含一个包含 HttpContext 的环境。

      【讨论】:

      • 你能再解释一下你的背景吗?如果我们引用 Microsoft.Owin 库,您是说您的 sn-p 有效吗?
      • 我在一个使用 OWIN 的 MVC 项目中运行上面的代码。 MVC 5 使用 OWIN,但早期版本没有。如果您使用的是 MVC 5 或更高版本,则不需要添加任何引用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-31
      • 2015-02-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多