asp.net-mvc-routing - 如何防止 Url.RouteUrl(...) 继承当前请求的路由值

标签 asp.net-mvc-routing

假设您有一个操作方法来在购物车中显示产品

 // ProductsController.cs
 public ActionMethod Index(string gender) {

      // get all products for the gender
 }

在其他地方,在每个页面上显示的 header 中,您使用 Url.RouteUrl 创建指向网站上其他页面的 HREF 链接:

 <a href="<%= Url.RouteUrl("testimonials-route", new { }) %>" All Testimonials </a>

testimonials-route 由下面的第一条路由在global.ascx 中定义。 请注意,上面对 RouteUrl 的调用不提供 gender,但路由定义为默认值“neutral”,因此我们期望 Testimonials.Index("neutral"") 被调用。

 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)。

但这没有意义,不是吗?如果我们不为其提供路由值,那么 testimonials-route 应该默认为 'neutral' 吗?

事实证明,Url.RouteUrl(routeName, routeValues) 辅助扩展程序将首先在其 routeValues 参数中查找 gender 路由值,如果在该字典中找不到它,它将查看我们所在的当前 URL(请记住,Url 是一个 UrlHelper 对象,它具有可用的当前请求的上下文)。

如果我们在男士产品页面上,这可能会给我们一个男士推荐的链接,但如果我们没有在 RouteUrl 中传递值,这可能不是我们想要的效果 code> 调用,并在 global.asax.cs 文件中显式指定“中性”作为默认值。

在我们访问 /products/ 的情况下,我们触发了 'products-route' 路由,并且 Products(null) 方法是叫。当我们使用 testimonials-route 创建 URL 时,对 Url.RouteUrl() 的调用实际上继承了 gender 的这个 null 值。即使我们在 'testimionials-route' 中指定了 gender 的默认值,它仍然使用这个 null 值,这会导致路由失败,并且 RouteUrl返回空值。 [注意:路线失败是因为我们对 (men|women|neutral) 有限制,而 null 不适合]

它实际上变得更可怕 - 因为“ Controller ”和“ Action ”可以以相同的方式继承。即使使用具有默认 Controller 的显式路由名称调用 RouteUrl(...),这也可能导致生成完全错误的 Controller 的 URL。

在这种情况下,一旦你弄清楚了它,你就可以通过多种方式轻松修复它,但在其他情况下它可能会导致一些危险的行为。这可能是设计使然,但这绝对是可怕的。

最佳答案

我的解决方案是这样的:

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”的新 UrlHelper。这意味着没有任何东西可以继承(甚至是空值)。

关于asp.net-mvc-routing - 如何防止 Url.RouteUrl(...) 继承当前请求的路由值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1148443/

相关文章:

c# - 在生成传出 URL 时针对其他 Controller 中的相同操作方法

c# - 从一个 API 调用方法已完成,但在第二个 API 上面临 Not found 错误

asp.net-mvc - asp.net MVC 和 RESTful 路由,rails 风格。是否可以?

asp.net-mvc - ASP.NET MVC 路由在 Controller 之前带有值并且没有尾部斜杠

c# - MVC 2 - URL 缩短/路由(映射路由)

asp.net-mvc - ASP.NET MVC 的 Piranha CMS 路由问题

asp.net-mvc - Asp.Net Mvc 路由约束可以抛出 404 而不是 InvalidOperationException 吗?

asp.net-mvc - 当 ID 包含句点时,ApiController 返回 404

linux - Linux 上的单声道加上 MVC3 : Root directory shows file/folder list on web browser

asp.net-mvc - ASP.NET-MVC。如何从URL获取 Controller 名称?