Attribute routing in MVC 5 and optional defaults

6.4k views Asked by At

Traditional routing defaults meant we were able to access these URLs and always end up on the same action:

/
/Home
/Home/Index

But today we would be writing something in these lines:

[RoutePrefix("Home")]
[Route("{action=Index}")]
public class HomeController
{
    public ActionResult Index() {}

    public ActionResult ...
}

But this routing definition is by no means the same.

/           (fails)
/Home       (works)
/Home/Index (works)

So if we then change upper code to

[RoutePrefix("Home")]
[Route("{action=Index}")]
public class HomeController
{
    [Route("~/")]
    public ActionResult Index() {}

    public ActionResult ...
}

But then we turn the processing upside down:

/           (works)
/Home       (fails)
/Home/Index (fails)

We could make declarative code more verbose and make it work as the old-fashioned routing mechanism by:

[RoutePrefix("Home")]
[Route("{action=Index}")]
public class HomeController
{
    [Route("~/")]
    [Route("~/Home")]
    [Route("~/Home/Index")]
    public ActionResult Index() {}

    public ActionResult ...
}

This works with all three different routes.

Question

This issue is of course bound to the very application default action that defaults controller and action. It's just that I wonder whether this is the only way of doing it? Is there any less verbose code way of getting it to work as expected?

2

There are 2 answers

5
Kiran On BEST ANSWER

Yeah, right..what you have is the way to do here...

I modified the code a bit here:

[RoutePrefix("Home")]
[Route("{action}")]
public class HomeController
{
   [Route("~/")]    // GET /
   [Route]          // GET /Home
   [Route("Index")] // GET /Home/Index
   public ActionResult Index() {}

   public ActionResult ...
}

Some details:
1. Your first case is not exactly the same as conventional routing as in this case you have a literal segment Home which is not similar to the conventional routing optional of {controller}/{action}/{id} and controller = Home, action=Index,id=optional.
2. Your second case is expected as by design if a Route attribute is used on action the attributes on Controller do not take effect.

2
Asad Ali On

right now for SEO you should use canonical url meaning single url something like this

public class HomeController
{
   [Route("~/")]    // GET /
   public ActionResult Index() {}

   public ActionResult ...
}

so home controller is accessible at root only