问题描述
让我们说您有一种操作方法来显示购物车中的产品
Lets say you have an action method to display products in a shopping cart
// ProductsController.cs
public ActionMethod Index(string gender) {
// get all products for the gender
}
在其他位置,在显示在每个页面上的标头中,您正在使用Url.RouteUrl
创建指向网站其他页面的HREF链接:
Elsewhere, in a masthead that is displayed on every page you are using Url.RouteUrl
to create HREF links to other pages on the site :
<a href="<%= Url.RouteUrl("testimonials-route", new { }) %>" All Testimonials </a>
此testimonials-route
在global.ascx
中由下面的第一条路线定义.请注意,上面对RouteUrl
的调用没有提供gender
,但是该路由的默认设置为'neutral',因此我们希望调用Testimonials.Index("neutral").
This testimonials-route
is defined in global.ascx
by the first route below.Notice that the above call to RouteUrl
does not provide a gender
, but the route is defined with a default of 'neutral' so we'd expect Testimonials.Index("neutral") to be called.
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
,我们将获得/testimonials/women
的HREF如果有人访问页面/products
,那么我们会得到一个空的HREF(对RouteUrl的调用返回null).
If someone visits the page /products/women
we get an HREF to /testimonials/women
If someone visits the page /products
then we get an empty HREF (the call to RouteUrl returns null).
但这没有意义吗?如果我们不提供'neutral'
的路由值,应该将其默认为'neutral'
吗?
But that doesn't make sense does it? testimonials-route
is supposed to default to 'neutral'
for us if we don't provide a route value for it?
事实是,Url.RouteUrl(routeName, routeValues)
帮助程序扩展将首先在其routeValues
参数中查找gender
路由值,如果在该词典中找不到该值,它将查找当前URL我们处于启用状态(请记住,Url是一个UrlHelper对象,它具有当前请求的上下文可用).
What turns out is happening is that Url.RouteUrl(routeName, routeValues)
helper extension will first look in its routeValues
parameter for a gender
route value and if it doesn't find it in that dictionary it will look at the current URL that we're on (remember that Url is a UrlHelper object which has the context of the current request available to it).
如果在男士用品页面上,给我们一个指向男士推荐书的链接可能会产生很好的效果,但是如果我们没有在RouteUrl
调用中传递值,这可能不是我们想要的,并且在global.asax.cs
文件中明确指定默认设置为中性".
This has a possibly nice effect of giving us a link to men's testimonials if we're on a mens product page, but that probably isnt what we want if we haven't passed a value in the RouteUrl
call, and explicitly specified 'neutral' as a default in the global.asax.cs
file.
在我们访问了/products/
的情况下,我们触发了'products-route'
路线,并调用了Products(null)
方法.当我们使用testimonials-route
创建URL时,对Url.RouteUrl()
的调用实际上继承了gender
的此null值.即使我们在'testimionials-route
中为gender
指定了默认值,它仍然使用此null值,这会导致路由失败,并且RouteUrl
返回null. [注意:路线失败是因为我们对(men | women | neutral)有约束,而null不适合该条件]
In the case where we visited /products/
we triggered the 'products-route'
route and the Products(null)
method was called. The call to Url.RouteUrl()
actually inherits THIS null value for gender
when we're creating a URL using testimonials-route
. Even though we have specified a default for gender
in 'testimionials-route
' it still uses this null value which causes the route to fail and RouteUrl
returns null. [note: the route fails because we have a constraint on (men|women|neutral) and null doesn't fit that]
实际上,它变得更加可怕-因为控制器"和动作"可以以相同的方式继承.即使使用具有默认控制器的显式路由名称调用RouteUrl(...),这也可能导致将URL生成为完全错误的控制器.
It actually gets more scary - in that 'controller' and 'action' can be inherited in the same way. This can lead to URLs being generated to completely the wrong controller even when calling RouteUrl(...) with an explicit route name that has a default controller.
在这种情况下,一旦您弄清楚了它,就可以很轻松地以多种方式对其进行修复,但是在其他情况下,它可能会导致某些危险的行为.这可能是设计使然,但绝对令人恐惧.
In this case once you've figured it out you can fix it quite easily in numerous ways, but it could in other cases cause some dangerous behavior. This may be by design, but its definitely scary.
推荐答案
我的解决方案是这样的:
My solution was this :
HtmlExtension帮助器方法:
An HtmlExtension helper method :
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)
,并确保无论上下文如何,它都将始终具有相同的行为.
and know for sure it will always behave the same way no matter what the context.
其工作方式是采用现有的UrlHelper
并使用空白"RouteData"创建一个新的UrlHelper
.这意味着没有要继承的内容(即使是空值).
The way it works is to take the existing UrlHelper
and create a new one with blank 'RouteData'. This means there is nothing to inherit from (even a null value).
这篇关于如何防止Url.RouteUrl(...)从当前请求继承路由值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!