Route Prefix in ASP.NET MVC Attribute Routing

Route Prefix in ASP.NET MVC Attribute Routing

In this article, I am going to discuss How to use the Route Prefix in ASP.NET MVC Attribute Routing with Examples. We are going to work with the same example that we started in the Attribute Routing article of this article series. Please read the Attribute Routing article before proceeding to this article.

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

Let’s understand the need and use of Route Prefix with one example. Let’s modify the StudentController class as shown below.

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]
        [Route("students")]
        public ActionResult GetAllStudents()
        {
            return View(students);
        }

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

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

As you can see in the above code, we are using route attributes at the action level to define routes, and further if you notice, all the routes in the StudentsController start with the same prefix i.e. students. That means “students” is the common prefix for all the routes in Student Controller.

Here, instead of writing the common prefix “students” at each action method, we can specify the common prefix students for the entire Student Controller (for all the action methods of student controller) using the [RoutePrefix] attribute at the controller level as shown below. 

namespace AttributeRoutingDemoInMVC.Controllers
{
    [RoutePrefix("students")]
    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]
        [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)
        {
            Student studentDetails = students.FirstOrDefault(s => s.Id == studentID);
            return View(studentDetails);
        }

        [HttpGet]
        [Route("{studentID}/courses")]
        //This will be translated to /students/2/course
        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();
        }
    }
}

As you can see in the above code, we applied the [RoutePrefix(“students”)] attribute at the Controller level. This Route Prefix attribute eliminates the need to repeat the common prefix “students” on each and every controller action method. However, sometimes we may need to override the route prefix attribute. 

How to Override Route Prefix Attribute in ASP.NET MVC Attribute Routing?

Let us understand this with an example. First, add a class file with the name “Teacher.cs” within the Models Folder. To do so right-click on the Models folder, and then add a new class file with the name “Teacher.cs”, and then copy and paste the following code in it.

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

Now, add the following GetTeachers() action method within the “StudentsController”.

public ActionResult GetTeachers()
{
    List<Teacher> teachers = new List<Teacher>()
            {
                new Teacher() { Id = 1, Name = "James" },
                new Teacher() { Id = 2, Name = "Patrik" },
                new Teacher() { Id = 3, Name = "Smith" }
            };
    return View(teachers);
}

After adding the GetTeachers() action method the “StudentsController” class should look as shown below

namespace AttributeRoutingDemoInMVC.Controllers
{
    [RoutePrefix("students")]
    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]
        [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)
        {
            Student studentDetails = students.FirstOrDefault(s => s.Id == studentID);
            return View(studentDetails);
        }

        [HttpGet]
        [Route("{studentID}/courses")]
        //This will be translated to /students/2/course
        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();
        }

        public ActionResult GetTeachers()
        {
            List<Teacher> teachers = new List<Teacher>()
            {
                new Teacher() { Id = 1, Name = "James" },
                new Teacher() { Id = 2, Name = "Patrik" },
                new Teacher() { Id = 3, Name = "Smith" }
            };
            return View(teachers);
        }
    }
}
GetTeachers.cshtml

Next, add GetTeachers.cshtml view and then copy and paste the below code.

@model IEnumerable<AttributeRoutingDemoInMVC.Models.Teacher>
@{
    ViewBag.Title = "GetTeachers";
}
<h2>GetTeachers</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>

We want the GetTeachers() method to be mapped to URI “/tech/teachers”.

[Route("tech/teachers")]
public ActionResult GetTeachers()
{
    List<Teacher> teachers = new List<Teacher>()
            {
                new Teacher() { Id = 1, Name = "James" },
                new Teacher() { Id = 2, Name = "Patrik" },
                new Teacher() { Id = 3, Name = "Smith" }
            };
    return View(teachers);
}

If we use the [Route] attribute on the GetTeachers() method as shown in the above code and when we navigate to tech/teachers URL, we will get the following error.

Route Prefix in Attribute Routing

But if we navigate to /students/tech/teachers then we will get the output as expected that is the list of teachers. This is because the [RoutePrefix(“students”)] attribute on StudentsController. So there is definitely a need to override the RoutePrefix attribute used on the StudentsController. To override the RoutePrefix attribute, we need to use the ~ (tilde) symbol while defining the route as shown in the below code. Here, we are using [Route(“~/tech/teachers”)] attribute and the tilde (~) symbol in the Route attribute will override or you can ignore the Route Prefix attribute defined at the StudentsController level.

[Route("~/tech/teachers")]
public ActionResult GetTeachers()
{
    List<Teacher> teachers = new List<Teacher>()
            {
                new Teacher() { Id = 1, Name = "James" },
                new Teacher() { Id = 2, Name = "Patrik" },
                new Teacher() { Id = 3, Name = "Smith" }
            };
    return View(teachers);
}

With this change GetTeachers() action method is now mapped to URI “/tech/teachers” as expected.

What is the use of the RoutePrefix Attribute in ASP.NET MVC Attribute Routing?

RoutePrefix attribute is used to specify the common route prefix at the controller level to eliminate the need to repeat that common route prefix on each and every controller action method

How to override the route prefix? 

Use ~ character to override the route prefix

In the next article, I am going to discuss Route Constraint in ASP.NET MVC Attribute Routing with Examples. Here, in this article, I try to explain the Route Prefix in ASP.NET MVC Attribute Routing with examples. I hope this Route Prefix in Attribute Routing article will help you with your needs. I would like to have your feedback. Please post your feedback, question, or comments about this article.

2 thoughts on “Route Prefix in ASP.NET MVC Attribute Routing”

Leave a Reply

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