Attribute Routing in ASP.NET MVC

Attribute Routing in MVC

Routing is a pattern matching mechanism used by ASP.NET MVC Framework to matches a URL pattern to an action method. ASP.NET MVC5 supports a new type of routing called as attribute routing. As the name implies, attribute routing means attributes are used to define routes. It provides you more control over the URIs by defining routes directly on actions and controllers in your ASP.NET MVC application.

The earlier style of routing, called as convention-based routing, is still fully supported by ASP.NET MVC5. In fact, you can combine both these routing approaches in the same project.

In this article, I will cover the basics of Attribute Routing in ASP.NET MVC5.

Why Attribute Routing?

Let us understand attribute routing with an example

Step 1: Create a new ASP.NET MVC application. Name it AttributeRoutingDemoInMVC

Step 2: Right-click on the “Models” folder and add a class file. Name it Student.cs. Copy and paste the following code.

namespace AttributeRoutingDemoInMVC.Models
{
    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}

Step 3: Let’s add Students Controller. Right-click on the Controllers folder and add a new MVC Empty controller. Name it StudentsController.cs. Copy and paste the following code.

namespace AttributeRoutingDemoInMVC.Controllers
{
    public class StudentsController : Controller
    {
        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]
        public ActionResult GetAllStudents()
        {
            return View(students);
        }

        [HttpGet]
        public ActionResult GetStudentByID(int studentID)
        {
            Student studentDetails = students.FirstOrDefault(s => s.Id == studentID);
            return View(studentDetails);
        }

        [HttpGet]
        public ActionResult GetStudentCourses(int studentID)
        {
            List<string> CourseList = new List<string>();

            if (studentID == 1)
                CourseList = new List<string>() { "ASP.NET", "C#.NET", "SQL Server" };
            else if (studentID == 2)
                CourseList = new List<string>() { "ASP.NET MVC", "C#.NET", "ADO.NET" };
            else if (studentID == 3)
                CourseList = new List<string>() { "ASP.NET WEB API", "C#.NET", "Entity Framework" };
            else
                CourseList = new List<string>() { "Bootstrap", "jQuery", "AngularJs" };

            ViewBag.CourseList = CourseList;

            return View();
        }
    }
}

Step4: Add the respective views for the above three action methods.

GetAllStudents.cshtml

@model IEnumerable<AttributeRoutingDemoInMVC.Models.Student>
@{
    ViewBag.Title = "GetAllStudents";
}
<h2>GetAllStudents</h2>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Id)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Name)
        </th>

    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Id)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
        </tr>
    }

</table>

GetStudentByID.cshtml

@model AttributeRoutingDemoInMVC.Models.Student
@{
    ViewBag.Title = "GetStudentByID";
}
<h2>GetStudentByID</h2>
<div>
    <h4>Student</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.Name)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Name)
        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Id)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Id)
        </dd>
    </dl>
</div>

GetStudentCourses.cshtml

@{
    ViewBag.Title = "GetStudentCourses";
}
<h2>GetStudentCourses</h2>
@foreach (var item in ViewBag.CourseList)
{
    <li>@item</li>
}

In MVC, we had convention-based routing that defines routes using route templates. When we create a new MVC project using Visual Studio, a default route is created in RouteConfig.cs file. The default route is shown below

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

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

Now we can access the above three methods using below URL

http://localhost:58316/Students/GetAllStudents

http://localhost:58316/Students/GetStudentByID?studentID=1

http://localhost:58316/Students/GetStudentCourses?studentID=1

In some scenario, the convention-based routing is very complex to support some URL patterns. But those URL patterns can be easily achieved by using Attribute Routing.

For example, resources often contain child resources like Clients have ordered; movies have actors, and books have authors and so on. It’s natural to create URIs that reflects these relations like as: /clients/1/orders

In our example, If we want the URL Pattern “/students/1/courses” should be mapped to GetStudentCourses(int studentID). Then this type of URL is very difficult to match using the convention-based routing. Yes, it can be achieved by convention-based routing but it will take our extra effort and time for this. But by using attribute routing this type of URL pattern can be achieved very easily.

Let’s see how to use attribute routing in MVC.

The first thing that we are going to do is Enabling Attribute Routing in RouteConfig.cs class.

Enabling Attribute Routing

Enabling attribute routing in ASP.NET MVC5 application is simple, just we need to add a call to routes.MapMvcAttributeRoutes() method within RegisterRoutes() method of RouteConfig.cs file.

For doing that first open RouteConfig.cs file which is located in App_Start folder and then just adds routes.MapMvcAttributeRoutes(); method just above routes.MapRoute as the show is below.

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

            //Enabling attribute routing 
            routes.MapMvcAttributeRoutes();

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

That’s it. We have enabled Attribute Routing for the Entire application.

The next step is to decorate the action method with Route attribute.

Modify the GetStudentCourses as shown below

[HttpGet]
[Route("students/{studentID}/courses")]
public ActionResult GetStudentCourses(int studentID)
{
    List<string> CourseList = new List<string>();

    if (studentID == 1)
        CourseList = new List<string>() { "ASP.NET", "C#.NET", "SQL Server" };
    else if (studentID == 2)
        CourseList = new List<string>() { "ASP.NET MVC", "C#.NET", "ADO.NET" };
    else if (studentID == 3)
        CourseList = new List<string>() { "ASP.NET WEB API", "C#.NET", "Entity Framework" };
    else
        CourseList = new List<string>() { "Bootstrap", "jQuery", "AngularJs" };

    ViewBag.CourseList = CourseList;

    return View();
}

Now navigate to the below URL and see the output.

http://localhost:58316/students/2/courses (You need to change the port number)

What is Attribute Routing?

Using the [Route] attribute to define routes is called Attribute Routing

What are the advantages of using Attribute Routing?
  1. It gives us more control over the URIs than convention-based routing. Creating URI patterns like hierarchies of resources (For example, students have courses, Departments have employees) is very difficult with convention-based routing.
  2. Reduces the chances for errors, if a route is modified incorrectly in RouteConfig.cs then it may affect the entire application’s routing.
  3. May decouple controller and action names from route entirely.
  4. Easy to map two routes pointing to the same action.
Can we use both Attribute Routing and Convention-based routing in a single MVC project?

Yes, both the routing mechanisms can be combined in a single MVC project. The controller action methods that have the [Route] attribute uses Attribute Routing, and the others without [Route] attribute uses Convention-based routing.

Note: Attribute routing should configure before the convention-based routing.

When to use Attribute Routing?

The convention-based routing is very complex to support certain URL patterns. But those URL patterns can be easily achieved by using Attribute Routing.

For example, resources often contain child resources like Clients have ordered, movies have actors, and books have authors and so on. It’s natural to create URIs that reflects these relations like as: /clients/1/orders

This type of URI is very difficult to create using convention-based routing. Yes, it can be done using convention-based routing, but it will take extra effort and extra time.

But by using attribute routing this type of URL pattern can be achieved very easily.

If you want to learn more about Attribute Routing then please visit the MSDN Site.

In the next article, I will discuss the following things Attribute Routing with Optional Parameter

SUMMARY
In this article, I try to explain the basis of Attribute Routing in ASP.NET MVC application. I hope this article will help you with your need. I would like to have your feedback. Please post your feedback, question, or comments about this article.

1 thought on “Attribute Routing in ASP.NET MVC”

  1. Nice pоst. I was checking continuously this weblog and
    I am іnspired! Extremely helpful informatiߋn specifically the last section 🙂 I handle
    such information a ⅼot. I used to be ⅼooкing for this certain information for a very long time.
    Thanks and good ⅼucқ.

Leave a Reply

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