我有一个在.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个命名值:tenantName
,controller
,action
,fooId
和fooRevision
。我还在调试期间添加了area
以确保,但它仍然返回null。
我验证了路由存在,因为this.Url.RouteCollection["Foo_Bar"]
返回与该路由对应的System.Web.Routing.Route
对象。
我尝试了.NET源步进,我能够在UrlHelper
中进入1级,但是进入GenerateUrl
函数失败了,Visual Studio 2015 U2总是跳过它。
答案 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::Bind
(http://referencesource.microsoft.com/#System.Web/Routing/ParsedRoute.cs)
问题在于这一行:
RouteValueDictionary rd = new RouteValueDictionary( this.Url.RequestContext.RouteData.Values );
这导致rd
复制(继承)当前请求上下文中的值,我认为这是可取的。我认为这是因为路由Foo_Bar
提供了默认的controller
和action
参数值,它总是会使用优先于rd
中的任何值,但我错了
传递到rd
的{{1}}包含UrlHelper.RouteUrl
和controller
的值,但它们是针对当前请求的,因此与默认值不同。
action
的定义是,如果提供的ParsedRoute::Bind
提供的参数值与默认值不同,则会中止(请参阅RouteValueDictionary
中的第133行到第149行。
我认为框架应该在这种情况下抛出异常,而不是返回null - 因为这种行为似乎没有得到很好的记录 - 特别是因为所有的搜索结果都说问题只是路径没有& #39; t存在或传递的参数不足 - 在我的情况下,问题在于传递了太多参数。