Attribute Routing in ASP.NET MVC

Attribute Routing in ASP.NET MVC Application

In this article, I am going to discuss Attribute Routing in ASP.NET MVC Application with some examples. This is one of the new features introduced in ASP.NET MVC5. Please read our previous article where we discussed the Route Constraints in Conventional based Routing. As part of this article, we are going to discuss the following pointers in detail.

  1. What is Attribute Routing?
  2. Why do we need Attribute Routing in ASP.NET MVC Application?
  3. How to Enabling Attribute Routing in ASP.NET MVC Application?
  4. Examples of using Attribute Routing.
  5. What are the advantages of using Attribute Routing in ASP.NET MVC5?
  6. Can we use both Attribute Routing and Convention-based routing in a single MVC project?
What is Attribute Routing?

Using the [Route] attribute to define routes is called Attribute Routing. It provides you more control over the URIs by defining routes directly on actions and controllers in your ASP.NET MVC application.

Attribute Routing in ASP.NET MVC

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

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

Let us understand the need for attribute routing in MVC with an example.

Create a new Empty ASP.NET MVC application with the name AttributeRoutingDemoInMVC. Then Right-click on the “Models” folder and add a class file with the name Student.cs and then copy and paste the following code in it.

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

Right-click on the Controllers folder and then add a new ASP.NET MVC Empty controller with the name StudentsController.cs and then copy and paste the following code in it.

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();
        }
    }
}

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 ASP.NET MVC, we had convention-based routing that defines routes using the route templates. When we create a new ASP.NET MVC Application using Visual Studio, then by default a route (i.e. default route) is created in the 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 the following URL

  1. http://localhost:58316/Students/GetAllStudents
  2. http://localhost:58316/Students/GetStudentByID?studentID=1
  3. http://localhost:58316/Students/GetStudentCourses?studentID=1

In some scenarios, the convention-based routing is very difficult to support certain URL patterns. But those URL patterns can be easily achieved by using the Attribute Routing in ASP.NET MVC.

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 create using the convention-based routing in MVC. But by using Attribute Routing in ASP.NET MVC Application, this type of URL pattern can be achieved very easily.

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

The first thing that you need to do is Enabling Attribute Routing in RouteConfig.cs class.

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

Enabling the Attribute Routing in ASP.NET MVC Application is very simple. You just need to add a call to routes.MapMvcAttributeRoutes() method within RegisterRoutes() method of RouteConfig.cs file.

So, open RouteConfig.cs file which is stored within the App_Start folder and then just adds routes.MapMvcAttributeRoutes(); method just above the 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 }
            );
        }
    }
}

With the above changes, now your application is going to support Attribute Routing. The next step is to decorate the action method with the Route attribute.

Modify the GetStudentCourses Action Method 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 following URL and you should get the output as expected.

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

What are the advantages of using Attribute Routing in ASP.NET MVC5?
  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.

In the next article, I am going to discuss Attribute Routing with Optional Parameter in ASP.NET MVC Application. Here in this article, I try to explain the basis of Attribute Routing in ASP.NET MVC application. I hope you enjoy 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 *