Allow dashes within urls using asp.net MVC 4

UPDATE: This applies to MVC 5 too

I was kind of surprised recently when I wanted to create an asp.net MVC view with dashes in it and found out that I couldn’t.

To me, reading-a-url-like-this is better than readingaurllikethis so I thought there must be a way to get around this. After all, web apps like WordPress and Umbraco allow this so why can’t I just do it in asp.net MVC?

After doing a bit of research on the subject I found out that I needed to do a couple of things:

  1. Create a new class that extends the MvcRouteHandler class within my Global.asax file, and
  2. Create a route within my Route.Config file.

Extending the MvcRouteHandler

The first thing to note here is that the underscore character _ is perfectly acceptable within controller names and also within action names.  So with that in mind any urls you want to write out with dashes in them should have underscores within them within your controller or actions names like so:

public class Laptops_and_TabletsController : Controller
{
   public ActionResult Budget_Laptops()
   {
      return View();
   }
}

The next step is to extend the MvcRouteHandler class to replace those underscores with dashes so that when the above action is requested it will be written out like /laptops-and-tablets/budget-laptops. So, open up your Global.asax file and add the following code block in:

public class HyphenatedRouteHandler : MvcRouteHandler
{
   protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
   {
      requestContext.RouteData.Values["controller"] =
         requestContext.RouteData.Values["controller"].ToString().Replace("-", "_");
      requestContext.RouteData.Values["action"] =
         requestContext.RouteData.Values["action"].ToString().Replace("-", "_");
      return base.GetHttpHandler(requestContext);
   }
}

Next it’s onto the Route.Config file.

Route.Config

The changes we need to make to this file are minimal as all we’re going to do is replace the default route handler with our new one:

Replace this

routes.MapRoute(
   name: "Default",
   url: "{controller}/{action}/{id}",
   defaults: new { controller = "Home", action = "Index",
      id = UrlParameter.Optional }
   );

With this

routes.Add(
   new Route("{controller}/{action}/{id}",
      new RouteValueDictionary(
         new { controller = "Home", action = "Index", id = "" }),
         new HyphenatedRouteHandler())
         );

And that’s it. You’ll now be able to provide urls that read-like-this over urls that readlikethis.

11 Comments Allow dashes within urls using asp.net MVC 4

  1. Pingback: Journey to ASP .NET MVC 5 (Episode 2) | cuteprogramming

  2. Barak

    This is a cool solution to the problem however it does raise a number of concerns.

    This seems to allow for any page to be hit from any number of URLs.

    E.g.,
    /user/info can be hit from:
    /us-er/inf–o
    /user—-/—–inf—–o
    etc.

    While in and of itself this would rarely manifest as a security risk it will unfortunately decrease your pagerank with many search engines (repeating the same content across a bunch of pages is seen as an attempt to increase the association of certain keywords with your site in general I believe).

    For intranet sites this is rarely a concern but if you want to do something similar in a production consumer site I believe using attribute routing is the superior choice.

    Reply
  3. Hafiz Ameer Hamza

    I did everything as your guideline..but when i run in url its shows me url with “_” it not replace it with “-” while loading.
    i have to to this manually in url… as i replaced in url and check..it works…Why it not replaced it remotely while loading ??

    Reply
  4. Jonathan

    This was very useful for me in diagnosing an interesting 404 error I ran across. It let me know that a least a piece of the MVC pipeline was functioning as expected.

    Great work!

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *