UrlHelper.RouteUrl(routeName,RouteValueDictionary)返回null

时间:2016-05-31 06:54:40

标签: asp.net-mvc routing asp.net-mvc-routing

我有一个在.NET 4.6.1上运行的ASP.NET MVC 5 Web应用程序。

我的应用程序中有一个名为“Foo”的区域,在我的区域注册中,我添加了一条命名路线,如下所示:

RegisterArea(AreaRegistrationContext context) {

    context.MapRoute("Foo_Bar", "{tenantName}/foo/{fooId}/{fooRevision}", new { controller = "Foo", action = "Index" } );

}

从我的Razor视图代码中我想使用此路由生成链接,所以我这样做:

RouteValueDictionary rd = new RouteValueDictionary( this.Url.RequestContext.RouteData.Values );
rd["fooId"      ] = "123";
rd["fooRevision"] = "4";

this.Url.RouteUrl("Foo_Bar", rd );

但是这会返回null。没有例外。没有其他副作用。

调试器显示rd包含5个命名值:tenantNamecontrolleractionfooIdfooRevision。我还在调试期间添加了area以确保,但它仍然返回null。

我验证了路由存在,因为this.Url.RouteCollection["Foo_Bar"]返回与该路由对应的System.Web.Routing.Route对象。

我尝试了.NET源步进,我能够在UrlHelper中进入1级,但是进入GenerateUrl函数失败了,Visual Studio 2015 U2总是跳过它。

2 个答案:

答案 0 :(得分:0)

null值表示请求的值与任何路由都不匹配。由于您还明确指定了路由名称(其作用类似于路由表上的过滤器),因此可以肯定地说路由Foo_Bar与提供的路由值输入不匹配。

您没有为{tenantName}提供默认值(如果没有合理的默认值,则没有问题),因此{tenantName}是必需值。当您为{tenantName}提供值时,会正确生成网址。

RouteValueDictionary rd1 = new RouteValueDictionary();
rd1["fooId"] = "123";
rd1["fooRevision"] = "4";

var url1 = this.Url.RouteUrl("Foo_Bar", rd1);
// url1 value is null

RouteValueDictionary rd2 = new RouteValueDictionary();
rd2["fooId"] = "123";
rd2["fooRevision"] = "4";
rd2["tenantName"] = "SomeTenant";

var url2 = this.Url.RouteUrl("Foo_Bar", rd2);
// url2 value is /SomeTenant/foo/123/4
  

注意:未明确提供的MVC automatically reuses route values from the current request。无需将this.Url.RequestContext.RouteData.Values显式添加到路径集合中。

当然,这意味着您可能不必将tenantName显式添加到路径集合中,具体取决于您运行此代码的上下文是否已经拥有它。

答案 1 :(得分:0)

我不得不逐步进入.NET Framework源代码来解决这个问题 - 首先进入System.Web.Mvc.dll进入UrlHelper.RouteUrl然后调用System.Web.Routing.dll(现在是.NET 4.5中System.Web.dll的存根。)

答案在于ParsedRoute::Bindhttp://referencesource.microsoft.com/#System.Web/Routing/ParsedRoute.cs

问题在于这一行:

RouteValueDictionary rd = new RouteValueDictionary( this.Url.RequestContext.RouteData.Values );

这导致rd复制(继承)当前请求上下文中的值,我认为这是可取的。我认为这是因为路由Foo_Bar提供了默认的controlleraction参数值,它总是会使用优先于rd中的任何值,但我错了

传递到rd的{​​{1}}包含UrlHelper.RouteUrlcontroller的值,但它们是针对当前请求的,因此与默认值不同。

action的定义是,如果提供的ParsedRoute::Bind提供的参数值与默认值不同,则会中止(请参阅RouteValueDictionary中的第133行到第149行。

我认为框架应该在这种情况下抛出异常,而不是返回null - 因为这种行为似乎没有得到很好的记录 - 特别是因为所有的搜索结果都说问题只是路径没有& #39; t存在或传递的参数不足 - 在我的情况下,问题在于传递了太多参数。