Custom routes in asp.net mvc 5

Here I’ll show you the new way to custom route via attribute in 2 steps (the old way is to register multiple mapRoute)

1. Enable attribute routes

// RouteConfig.cs

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.MapMvcAttributeRoutes(); // 1. after the line above

    routes.MapRoute( /* your route here */ );
}

2. using RouteAttribute

// using dependency
using System.Web.Mvc;

public class HomeController : Controller
{
    [Route("about-us")] // 2. put in the route you want
    public ActionResult About()
    {
        return View();
    }
}

after that, you can go to about view by url /about-us instead of /Home/About.

Routing with parameters

by using the pattern {param-name} in route, you can get the value from url. So in the example above, I want to get the name on url /about-us/quang, then my route would be:

[Route("about-us/{name}")]
public ActionResult About(string name)
{
    return View(model: name); // specify name as a model
    // or return View("About", name);
}

then get the value from Controller in View:

@model string

<h2>Hi @Model.</h2>

routing parameter

Pay attention at route pattern {name} and parameter name string name, they must be the same, otherwise it won’t work.

You can put as many levels of routing you want:

[Route("about-us"/{company}/{unit}/{name})]
public ActionResult About(string company, string unit, string name)
{
    ...
}

multiple routing level

Routing prefix

Imagine you have a ProductController with many actions

public class ProductController : Controller
{
    [Route("product/all")]
    public ActionResult Index() { ... }

    [Route("product/get/{id}")]
    public ActionResult GetProduct() { ... }

    [Route("product/add")]
    public ActionResult AddProduct() {}

    // and many many more
}

with prefix, you can simplify your route like below:

[RoutePrefix("product")] // add this
public class ProductController : Controller
{
    [Route("all")] // no need product/
    public ActionResult Index() { ... }

    [Route("get/{id}")] // no need product/
    public ActionResult GetProduct() { ... }

    [Route("~/add-product")] // override the prefix with ~/ syntax
    public ActionResult AddProduct() {}
}

Custom route for area

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.MapMvcAttributeRoutes();

    // RegisterAllAreas must be called after MapMvcAttributeRoutes to achieve area custom route
    AreaRegistration.RegisterAllAreas();

    routes.MapRoute( /* your route here */ );
}

Of course you need to remove RegisterAllAreas() in your global.asax (if have)

Some common issues on custom route

Q: I don’t know why my routes not working?
A: You might mix the web api routing with mvc routing.

Web Api need System.Web.Http:

using System.Web.Http; // web api dependency

public class MyApiController : ApiController
{
    [System.Web.Http.Route("index")]
    public Action Index() {}
}

while Mvc need System.Web.Mvc:

using System.Web.Mvc; // mvc dependency

public class MyController : Controller
{
    [System.Web.Mvc.Route("index")]
    public ActionResult Index() {}
}


Q: I cannot get the param value on url
A: You might not use the same param name with the route

[Route("about/{name"})]
public ActionResult About(string names) // it should be `name`, not `names`
{ }