Attribute Routing

What is Attribute Routing

Attribute Routing is a way to define routes directly on controller actions using attributes instead of defining them in the RouteConfig.cs file. It provides more flexibility and makes routes easier to manage, especially in large applications.


What is the Importance of Attribute Routing

To understand why attribute routing is needed in an ASP.NET MVC application, let's go through an example. First, create a new empty ASP.NET MVC project named AttributeRoutingDemoInMVC. Next, right-click on the Models folder, add a new class file named Student.cs, and insert the following code into it.


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

Create Students Controller:

Right-click on the Controllers folder, add a new ASP.NET MVC 5 Empty Controller named StudentsController.cs , and then insert the following code into it.



namespace AttributeRoutingDemoInMVC.Controllers
{
    public class StudentsController : Controller
    {
        static List<student> students = new List<student>()
        {
            new Student() { Id = 1, Name = "Shaista" },
            new Student() { Id = 2, Name = "Noorain" },
            new Student() { Id = 3, Name = "Anam" },
            new Student() { Id = 4, Name = "Arshiya" }
        };
        [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();
              }
           }
       }

Create the corresponding views for the three action methods mentioned above.


GetAllStudents.cshtml

The view below will display all student data. It is a strongly typed view, and its model is IEnumerable<attributeroutingdemoinmvc.models.student>.


@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

The view below will display the details of a specific student. It is a strongly typed view, and its model is AttributeRoutingDemoInMVC.Models.Student.


@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

The view below will display the courses of a specific student. This view is not strongly typed; instead, it uses ViewBag to retrieve the courses.


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

Convention-based routing is used to configure routes using predefined templates. When you create a new ASP.NET MVC 5 application in Visual Studio, a default route is automatically generated in the RouteConfig.cs file. The default route is displayed 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 }
            );
        }
    }
}
                                        

The three methods mentioned above can be accessed using the following URLs:

  • http://localhost:58316/Students/GetAllStudents
  • http://localhost:58316/Students/GetStudentByID?studentID=1
  • http://localhost:58316/Students/GetStudentCourses?studentID=1

Enabling Attribute Routing

Activating Attribute Routing in an ASP.NET MVC 5 application is a simple process. You only need to include the routes.MapMvcAttributeRoutes() method within the RegisterRoutes() method in the RouteConfig.cs file. To do this, navigate to the RouteConfig.cs file inside the App_Start folder and add routes.MapMvcAttributeRoutes(); just before the routes.MapRoute method, as demonstrated below. Attribute routing must be set up before convention-based routing.


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

After implementing the above modifications, your MVC application will now support Attribute Routing. The next step is to apply the [Route] attribute to either the controller or the action method.


Applying the Route Attribute

Update the GetStudentCourses action method as shown below. Here, the [Route("students/{studentID}/courses")] attribute is used to define a custom route for this action method.

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

After making these modifications, you can access the action method using the students/{studentID}/courses URL, where studentID will be dynamically replaced with actual values. Now, navigate to the following URL to see the expected output: http://localhost:58316/students/2/courses (Make sure to update the port number accordingly).