Routing

Overview

MSDN Tutorial (CORE only): Routing in ASP.NET Core

MSDN Tutorial (MVC): Routing to Controller Actions

Routing

Attribute Routing

When creating an attribute route, you type Route("template") where template is the string that the incoming URL will be compared to. If a match is found for the URL then the ActionResult method will be invoked. In the example below, route attributes are added to the Index() action in the HomeController.cs controller class. Each route template identifies a unique pattern-matching rule.

If a rule does not work with specified action, the action will skip the rule and look for another rule that does work, otherwise it ignores all non-functional rules.

In the example above the route templates represent static routes, but not all routes are static. If you wanted to edit a specific record for instance, then we would want to use an id value in the URL to represent the record we want retrieved. In these cases we use a route parameter. The figure below shows a route template with a route parameter to identify the specific record to be passed into the Edit view. Notice how the ActionResult accepts the parameter.

Screen capture showing how to add a Route attribute.

Putting curly braces around id creates a placeholder for some text that you want to reference by name later. To be precise, you’re capturing a path segment, which is one of part of a URL path separated by slashes (but not including the slashes). To see how that works, let’s define a route like this:

    [Route("{year}/{month}/{day}")]
    public ActionResult Index(string year, string month, string day)
    {
        // Do some work return View();
    }
Route Parameter Value Mapping Examples
URL ROUTE PARAMETER VALUES
/2014/April/10 year = "2014"
month = "April"
day = "10"
/foo/bar/baz year = "foo"
month = "bar"
day = "baz"
/a.b/c-d/e-f year = "a.b"
month = "c-d"
day = "e-f"

In the preceding method, the attribute route will match any URL with three segments because a route parameter, by default, matches any nonempty value. When this route matches a URL with three segments, the text in the first segment of that URL corresponds to the {year} route parameter, the value in the second segment of that URL corresponds to the {month} route parameter, and the value in the third segment corresponds to the {day} parameter.

You can name these parameters almost anything you want (alphanumeric characters are allowed as well as a few other characters). When a request comes in, Routing parses the request URL and places the route parameter values into a dictionary (specifically a RouteValueDictionary accessible via the RequestContext), using the route parameter names as the keys and the corresponding sub-sections of the URL (based on position) as the values.

When an attribute route matches and an action method runs, the route parameters from the route are used by model binding to populate values for any method parameters with the same name. Later, you’ll learn about how route parameters are different from method parameters.

Controller Routes

So far, you’ve seen how to put route attributes directly on your action methods. But often, the methods in your controller class will follow a pattern with similar route templates. Consider the routes for a simple HomeController such as the one in a new MVC application:

    public class HomeController : Controller
    {
        [Route("home/index")] public ActionResult Index()
        {
            return View();
        }

        [Route("home/about")] public ActionResult About()
        {
            return View();
        }

        [Route("home/contact")] public ActionResult Contact()
        {
            return View();
        }
    }

These routes are all the same except for the last segment of the URL. Wouldn’t it be nice to find some way to avoid repeating yourself and just say that each action method maps to a URL under home? Fortunately, you can:

       [Route("home/{action}")]
       public class HomeController : Controller
       {
            public ActionResult Index() 
            {
                return View();
            }
            public ActionResult About() 
            {
                return View();
            }
            public ActionResult Contact() 
            {
                return View();
            }
        }

We’ve removed all the route attributes above each method and replaced them with one attribute on the controller class. When you define a route on the controller class, you can use a special route parameter named action, and it serves as a placeholder for any action name. It has the same effect as your putting separate routes on each action and typing in the action name statically; it’s just a more convenient syntax. You can have multiple route attributes on your controller class just like you do on your action methods.

Using a Route Prefix

Route prefix.

A RoutePrefix can be applied at the controller level to define a value that can be used to prefix all RouteTemplates for that controller. For example we could do this:

            [RoutePrefix("home")]
            [Route("{action}")]
            public class HomeController : Controller
            {
                [Route("")]
                [Route("index")]
                public ActionResult Index()
                {
                    return View();
                }

                public ActionResult About()
                {
                    return View();
                }

                public ActionResult Contact()
                {
                    return View();
                }

Now, all your route attributes can omit home/ because the prefix provides that automatically. The prefix is just a default, and you can escape from it if necessary. For example, you might want your home controller to support the URL / in addition to /home and /home/index. To do that, just begin the route template with ~/, and the route prefix will be ignored. Here’s how it looks when HomeController supports all three URLs for the Index method (/, /home, and /home/index):

Attribute Route Examples

Added to Route.Config.cs