8 2_Routing
jason.zhu edited this page 2021-06-16 16:40:07 +10:00

Routing in ASP.NET MVC

Routing in ASP.NET MVC Application

Topic covered:

  1. What is Routing in MVC?
  2. What are the different types of Routing supported by ASP.NET MVC?
  3. How does the Routing in ASP.NET Web Form?
  4. What is a Route in MVC Application?
  5. How Does the Routing work in ASP.NET MVC Application?
  6. How to Configure a Route in ASP.NET MVC?
  7. Understanding the URL Pattern in ASP.NET MVC Routing
  8. How to Register Routes in ASP.NET MVC?
  9. Examples to understand Routing

What is Routing in MVC?

Routing module map incoming browser requests to a particular MVC controller action method.

e.g. http://localhost:xxxxx/Home/Index URL will be mapped to follow method

public class HomeController : Controller
{
    public ViewResult Index()
    {
        return View();
    }
}

What are different types of Routing supported by ASP.NET MVC?

2 types:

  • Convention Based Routing (illustrated here)
  • Attribute-Based Routing (supported by MVC5, not illustrated, can refer to Attribute Routing in ASP.NET MVC 5, will be introduced later)

How does the Routing in ASP.NET Web Form?

In ASP.NET Web Form app, each URL need a specific .aspx file (i.e. route through file)

ASP.NET Framework introduce Routing enable rules to match URL pattern to request handler.

What is a Route in ASP.NET MVC App?

  • Route = URL pattern that's mapped to a handler.
  • Handler can be:
    • physical file (e.g. aspx file in WebForms app)
    • class that processes the request (e.g. controller in MVC app)
  • Configured routes of ASP.NET MVC sotred in RouteTable, which used by routing engine to select appropriate handler to handle incoming request.

How does Routing work in ASP.NET MVC App?

Routing in ASP.NET MVC

How to Configure a Route in ASP.NET MVC?

New MVC app has default route (in RouteConfig.cs) as shown below, in which we can configure new route.

namespace FirstMVCDemo
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default", //Route Name
                url: "{controller}/{action}/{id}", //Route Pattern
                defaults: new
                {
                    controller = "Home", //Controller Name
                    action = "Index", //Action method Name
                    id = UrlParameter.Optional //Defaut value for above defined parameter
                }
            );
        }
    }
}

How RouteConfig works:

  1. Routing is configured using MapRoute() extension method of RouteCollection class
  2. Name of default route is "Default"
  3. URL pattern of default route is {controller}/{action}/{id}, which has default values as:
    1. controller: HomeController
    2. action: Index
    3. id is optional

The default value specify which controller, action method or value of id parameter should be used if they do not exist in the incoming request URL.

Understanding the URL Pattern in ASP.NET MVC Routing

  • URL pattern is considered only after the domain name in URL (e.g. www.dotnettutorials.net/{controller}/{action}/{id})
  • If not provided with any value then default values of these parameters will be provided by routing system

How to Register Routes in ASP.NET MVC?

  1. Configure routes in RouteConfig class
  2. Register routes in Application_Start() event in Global.asax file, so RouteTable can be populated

e.g. Global.asax

namespace FirstMVCDemo
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }
    }
}

Custom Routing in ASP.NET MVC App

Creating Custom Routes in ASP.NET MVC App

  • Using MapRoute extension method.
  • Need provide at least route name & URL patter.
  • Default parameter is optional
  • Multiple custom routes can be created with different names
namespace FirstMVCDemo
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Employee",
                url: " Employee/{id}",
                defaults: new 
                { 
                    controller = "Employee", 
                    action = "Index" 
                }
            );
            
            routes.MapRoute(
                name: "Default", //Route Name
                url: "{controller}/{action}/{id}", //Route Pattern
                defaults: new
                {
                    controller = "Home", //Controller Name
                    action = "Index", //Action method Name
                    id = UrlParameter.Optional //Defaut value for above defined parameter
                }
            );
        }
    }
}

Following URLs will be mapped to Employee route:

  • http://localhost:xxxxx/Employee
  • http://localhost:xxxxx/Employee/Index
  • http://localhost:xxxxx/Employee/Index/3

Rules of creating route:

  • Always put more specific route on top

Route Constraints in ASP.NET MVC

What are Route Constraints in ASP.NET MVC App?

Route Constraint in ASP.NET MVC allow us to apply a regular expression to a URL segment to validate.

e.g. Restrict to numeric id only

namespace FirstMVCDemo
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                name: "Default", //Route Name
                url: "{controller}/{action}/{id}", //Route Pattern
                defaults: new
                {
                    controller = "Home", //Controller Name
                    action = "Index", //Action method Name
                    id = UrlParameter.Optional //Defaut value for above defined parameter
                },
                constraints :new { id = @"\d+" } //Restriction for id (numeric only)
            );
        }
    }
}

If given a non-numeric value for the id parameter then

  • the request will be handled by another route
  • if there are no matching routes then "The resource could not be found" error will be thrown.

Creating Route Constraint to a Set of Specific Values in ASP.NET MVC App

        routes.MapRoute(
             "Default", // Route name
             "{controller}/{action}/{id}", // Route Pattern
             new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Default values for parameters
             new { controller = "^H.*", action = "^Details$|^About$" } //Restriction for controller and action
        );

Route engine will consider only URLs which have controller name with H prefix and action name with only Details or About. e.g.:

  • http://dotnettutorials.net/Home/Index
  • http://dotnettutorials.net/Home/Details
  • http://dotnettutorials.net/, because route default values for controller and action are applied first,then check.
  • http://dotnettutorials.net/Home

What is the difference between Routing and URL Rewriting?

  • URL rewriting is focused on mapping on URL (new) to another URL (old)
  • URL rewriting rewrites old URL to a new one while routing never rewrites but just map.

How is the routing table created in ASP.NET MVC?

  1. When MVC app start, Application_Start() method in global.asax is called
  2. Application_Start() calls RegisterRoutes()
  3. RegisterRoutes() creates the routing table for MVC app.

Attribute Routing in ASP.NET MVC

New feature introduced in ASP.NET MVC5.

What is Attribute Routing?

  • Attribute Routing: use [Route] attribute to routes.
  • Pro: provides more control over URIs by defining routes directly on actions and controllers in ASP.NET MVC
  • The other routing mechanism is: Convention-based routing

Why do we need Attribute Routing in ASP.NET MVC Application?

Refer to Why ASttribute Routing?

We can replace

routes.MapRoute(
    name: ProductPage,
    url: {productId}/{productTitle},
    defaults: new { controller = Products, action = Show },
    constraints: new { productId = “\\d+ }
);

with

[Route(“{productId:int}/{productTitle}”)]
public ActionResult Show(int productId) {  }

How to Enabling Attribute Routing in ASP.NET MVC Application?

  • Add a call to routes.MapMvcAttributeRoutes() method within RegisterRoutes() method of RouteConfig.cs file, before other routes.MapRoute() routes

Modify the GetStudentCourses Action Method

Add Attribute Route on top of action method

[Route("students/{studentID}/courses")]
public ActionResult GetStduentCourses(int studnetID)
{
    ...
}

Now http://localhost:xxxx/students/2/courses will be routed to GetStudentCourses method, and 2 will be parsed as value to variable studentID in the function.

What are the advantages of using Attribute Routing in ASP.NET MVC5?

  1. gives deveeloper more control over URIs than convention-based routing. It's hard to create UIR patterns for resources with a lot of hierarchies (e.g. students have courses, Departments have employees)
  2. reduces chances for errors, if a route is edited incorrectly in RouteConfig.cs, it may damage entire app's routing
  3. Can decouple controller and action names for route
  4. Easy to map 2 routes pointing to same action

Can we use both Attribute Routing and Convention-based routing in a single MVC project?

  • controller action method have [Route] attribute use Attribute Routing
  • controller action method without [Route] attribute uses Convention-based routing.

Attribute Routing with Optional Parameter

URI parameter can also be defined in attribute routing by adding question mark ("?") to router parameter within {}. We can also specify default value by parameter = value

e.g. optional URI Parameter {studentName? }

        // Optional URI Parameter
        // URL: /MVCTest/
        // URL: /MVCTest/Pranaya
        [Route("MVCTest/{studentName ?}")]
        public ActionResult MVC(string studentName)
        {
            DoSth(studentName);
            return View();
        }
        // Optional URI Parameter with default value
        // URL: /WEBAPITest/
        // URL: /WEBAPITest/Pranaya
        [Route("WEBAPITest/{studentName = Pranaya}")]
        public ActionResult WEBAPI(string studentName)
        {
            DoSth(studentName);
            return View();
        }

Route Prefix in Attribute Routing

Why do we need Route Prefix in Attribute Routing

In a controller, when attribute route of multiple action methods share same prefix (e.g. students/2/courses, students/course), Route Prefix can be used to eliminate repeated common prefix by:

  1. Add [RoutePrefix("student")] before controller
  2. Modify each attribute routes (i.e. remote prefix)
namespace AttributeRoutingDemoInMVC.Controllers
{
    [RoutePrefix("students")]
    public class StudentsController : Controller
    {
        private static List<Student> students = new List<Student>()
        {
            new Student() {Id = 1, Name = "Pranaya"},
            new Student() {Id = 2, Name = "Priyanka"},
            new Student() {Id = 3, Name = "Anurag"},
            new Student() {Id = 4, Name = "Sambit"}
        };

        [HttpGet]
        [Route]
        // This will be translated to /students
        public ActionResult GetAllStudents()
        {
            return View(students);
        }

        [HttpGet]
        [Route("{studentID}")]
        // This will be translated to /students/2
        public ActionResult GetStudentByID(int studentID)
        {
            ...
        }

        [HttpGet]
        [Route("students/{studentID}/courses")]
        // This will be translated to /students/2/courses
        public ActionResult GetStudentCourses(int studentID)
        {
            ...
        }
    }
}

How to Override Route Prefix in Attribute Routing

We can override route prefix attribute if needed. By using character ~.

namespace AttributeRoutingDemoInMVC.Controllers
{
    [RoutePrefix("students")]
    public class StudentsController : Controller
    {
        ...

        [Route("~/tech/teachers")]
        // This will be translated to /tech/teachers
        public ActionResult GetTeachers()
        {
            ...
        }
        
    }
}

This will overwrite "students" route prefix.

Attribute Route Constraints in ASP.NET MVC

Attribute Route Constraints

  • Attribute route constraints = a set of rules that defined on routing parameters
  • Defined by using : character.
  • Can add additional requirement e.g. min(), max(), range() etc.

e.g. We can create 2 action methods with same name with different route parameter

namespace AttributeRoutingDemoInMVC.Controllers
{
    [RoutePrefix("students")]
    public class StudentsController : Controller
    {
        ...

        [HttpGet]
        [Route("{studentID:int:range(1,3)}")]
        // This will be translated to /students/2
        public ActionResult GetStudentDetails(int studentID)
        {
            Student studentDetails = students.FirstOrDefault(s => s.Id == studentID);
            return View(studentDetails);
        }

        [HttpGet]
        [Route("{studentName:alpha}")]
        // /student/Pranaya
        public ActionResult GetStudentDetails(string studentName)
        {
            Student studentDetails = students.FirstOrDefault(s => s.Name == studentName);
            return View(studentDetails);
        }
        ...
        
    }
}
  • [Route("{studentID:int:range(1,3)}")] enforce route engine to use this action method only if the given studentID is integer and it's within 1,2 or 3
  • [Route("{studentName:alpha}")] enforce route engine to use this action method only if given studentID is alphabatic character strings

Default Route and Route Name in Attribute Routing

Default Route

Controller can has default route by applying route attribute on top of it, default action method is used as parameter (i.e. [Route("action = methodName")])

namespace AttributeRoutingDemoInMVC.Controllers
{
    [RoutePrefix("MyPage")]
    [Route("action = Index")]
    public class HomeController : Controller
    {
        // URL: /MyPage/
        // Default route
        public ActionResult Index()
        {
            ViewBag.Message = "Index Page";
            return View();
        }
        // URL: /MyPage/Contact
        public ActionResult Contact()
        {
            ViewBag.Message = "Contact page";
            return View();
        }
        // URL: /MyPage/About
        public ActionResult About()
        {
            ViewBag.Message = "About";
            return View();
        }
    }
}

Route Names

Route name can be specified in controller so it's easier for URI generation

namespace AttributeRoutingDemoInMVC.Controllers
{
    [Route("menu", Name = "mymenu")]
    public class MenuController : Controller
    {
        public ActionResult MainMenu()
        {
            ViewBag.Message = "Menu Page";
            return View();
        }
    }
}

URL link can be generated using Url.RouteURl; e.g. generatingin URL in View

<a href=”@Url.RouteUrl(“mymenu”)“>Main menu</a>