Alex Rivera | Logout

How to prevent Url.RouteUrl(...) from inheriting route values from the current request

Asked 2009-07-18T20:02:52.530
31

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
 }

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>

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)" }
 );

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

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?

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

Edit
Report

1 Answer

26

My solution was this :

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);
        }
    }

I can now do :

Url.RouteUrl('testimonials-route', new { }, false)

and know for sure it will always behave the same way no matter what the context.

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

answered 2009-07-18T20:03:24.120

Your Answer