假设您有一种在购物车中显示产品的操作方法
// ProductsController.cs
public ActionMethod Index(string gender) {
// get all products for the gender
}
在其他地方,在每个页面上显示的标头中,您使用Url.RouteUrl
创建到网站上其他页面的HREF链接:
<a href="<%= Url.RouteUrl("testimonials-route", new { }) %>" All Testimonials </a>
此testimonials-route
在global.ascx
中通过以下第一条路线定义。
请注意,上面对RouteUrl
的调用不提供gender
,但路由的默认值为“中性”,因此我们希望调用Testimonials.Index(“中性”)。
routes.MapRoute(
"testimonials-route",
"testimonials/{gender}",
new { controller = "Testimonials", action = "Index", gender = "neutral" },
new { gender = "(men|women|neutral)" }
);
routes.MapRoute(
"products-route",
"products/{gender}",
new { controller = "Products", action = "Index", gender = (string)null },
new { gender = "(men|women|neutral)" }
);
如果有人访问了该网页/products/women
,我们就会获得HREF /testimonials/women
如果有人访问了页面/products
,那么我们会得到一个空的HREF(对RouteUrl的调用返回null)。
但这没有意义吗?如果我们没有为它提供路由值,testimonials-route
应该默认为'neutral'
?
事实证明,Url.RouteUrl(routeName, routeValues)
帮助扩展程序将首先在其routeValues
参数中查找gender
路由值,如果它在该字典中找不到它,它将会查看我们当前的URL(请记住,Url是一个UrlHelper对象,它具有当前请求的上下文可用)。
如果我们在男性产品页面上,这可能会给我们提供男性推荐的链接,但如果我们没有通过RouteUrl
调用中的值,这可能不是我们想要的,并在global.asax.cs
文件中明确指定“中性”作为默认值。
如果我们访问了/products/
,则会触发'products-route'
路由并调用Products(null)
方法。当我们使用Url.RouteUrl()
创建网址时,对gender
的调用实际上会继承testimonials-route
的THIS空值。即使我们在gender
'中指定了'testimionials-route
的默认值,它仍然使用此空值,这会导致路由失败并且RouteUrl
返回null。 [注意:路线失败,因为我们有一个约束(男人|女人|中立)而null不适合]
它实际上变得更加可怕 - 因为“控制器”和“动作”可以以相同的方式继承。即使在使用具有默认控制器的显式路由名称调用RouteUrl(...)时,这也可能导致URL生成完全错误的控制器。
在这种情况下,一旦你弄明白了,你可以通过多种方式轻松解决它,但在其他情况下可能会导致一些危险的行为。这可能是设计上的,但它绝对是可怕的。
答案 0 :(得分:26)
我的解决方案是:
HtmlExtension助手方法:
public static string RouteUrl(this UrlHelper urlHelper, string routeName, object routeValues, bool inheritRouteParams)
{
if (inheritRouteParams)
{
// call standard method
return urlHelper.RouteUrl(routeName, routeValues);
}
else
{
// replace urlhelper with a new one that has no inherited route data
urlHelper = new UrlHelper(new RequestContext(urlHelper.RequestContext.HttpContext, new RouteData()));
return urlHelper.RouteUrl(routeName, routeValues);
}
}
我现在可以做到:
Url.RouteUrl('testimonials-route', new { }, false)
并且确定无论上下文如何,它总是会以相同的方式运行。
它的工作方式是取现有的UrlHelper
并创建一个空白的'RouteData'。这意味着没有任何东西可以继承(甚至是空值)。
答案 1 :(得分:2)
也许我在这里遗漏了一些东西,但为什么不这样设置:
在您的全局asax中,创建两个路径:
routes.MapRoute(
"testimonial-mf",
"Testimonials/{gender}",
new { controller = "Testimonials", action = "Index" }
);
routes.MapRoute(
"testimonial-neutral",
"Testimonials/Neutral",
new { controller = "Testimonials", action = "Index", gender="Neutral" }
);
然后,使用Url.Action而不是Url.RouteUrl:
<%= Url.Action("Testimonials", "Index") %>
<%= Url.Action("Testimonials", "Index", new { gender = "Male" }) %>
<%= Url.Action("Testimonials", "Index", new { gender = "Female" }) %>
在我的机器上解析为以下网址:
/Testimonials/Neutral
/Testimonials/Male
/Testimonials/Female
我不确定这是否是一个可接受的解决方案,但它是另一种选择,不是吗?