Back to: ASP.NET Core Web API Tutorials
How to set up Multiple URLs for a Single Resource in ASP.NET Core Web API
In this article, I will discuss How to set up Multiple URLs for a Single Resource in the ASP.NET Core Web API Application with Examples. Please read our previous article discussing working with Route Data and Query Strings in ASP.NET Core Web API.
Access a Single Resource with Multiple URLs in ASP.NET Core Web API:
In modern Web API (Restful Services) development, flexibility in routing is crucial for fulfilling various client needs and application requirements. ASP.NET Core Web API offers powerful routing capabilities, including the ability to access a single resource through multiple URLs. Let us proceed and understand how to implement this feature (access a single resource through multiple URLs) using a real-time example with in-memory data.
How Do We Access a Single Resource with Multiple URLs?
Attribute Routing allows us to define routes directly on controller actions using attributes. This approach provides greater control over the URL patterns and enables scenarios like accessing a single resource through multiple URLs. Let us understand how to access a single resource with multiple URLs using an example of ASP.NET Core Attribute Routing. We will use In-Memory Data to simulate a data store.
Define the Employee Model
Create a class file named Employee.cs within the Models folder, and then copy and paste the following code:
namespace RoutingInASPNETCoreWebAPI.Models { public class Employee { public int Id { get; set; } public string Name { get; set; } public string Gender { get; set; } public string Department { get; set; } public string City { get; set; } } }
Step 2: Initialize In-Memory Data
For simplicity, we’ll use a static list to store employee data. So, create a class file named EmployeeData.cs within the Models folder and then copy and paste the following code:
using RoutingInASPNETCoreWebAPI.Models; namespace RoutingInASPNETCoreWebAPI.Data { public static class EmployeeData { public static List<Employee> Employees = new List<Employee> { new Employee { Id = 1, Name = "Alice Johnson", Gender = "Female", Department = "HR", City = "New York" }, new Employee { Id = 2, Name = "Bob Smith", Gender = "Male", Department = "IT", City = "Los Angeles" }, new Employee { Id = 3, Name = "Charlie Davis", Gender = "Male", Department = "Finance", City = "Chicago" } // Add more employees as needed }; } }
Implementing Multiple Routes for a Single Resource
We will create an EmployeeController that exposes endpoints to retrieve employee data. We will configure multiple routes to access the same resource. Suppose we have the following resource available in our Employee Controller.
We want to access the above resource with three URLs: api/Employee/All, api/Employee/AllEmployees, and api/Employee/GetAll. How can we do this? If this is your requirement, you need to decorate the GetAllEmployees action method with three different HttpGet Attributes, as shown in the image below.
With this, you can access the GetAllEmployees resource with three different URLs in the ASP.NET Core Web API Application. Let us prove this. First, modify the EmployeeController class as shown in the below code.
using Microsoft.AspNetCore.Mvc; using RoutingInASPNETCoreWebAPI.Models; using RoutingInASPNETCoreWebAPI.Data; namespace EmployeeApi.Controllers { [ApiController] [Route("api/[controller]")] public class EmployeeController : ControllerBase { // Action Method with Multiple Routes [HttpGet("All")] [HttpGet("AllEmployees")] [HttpGet("GetAll")] public ActionResult<IEnumerable<Employee>> GetAllEmployees() { var employees = EmployeeData.Employees; return Ok(employees); } } }
Code Explanation
- [ApiController]: Specifies that the controller responds to web API requests.
- [Route(“api/[controller]”)]: Sets the base route to api/Employee.
- Multiple [HttpGet] Attributes: The GetAllEmployees action is decorated with 3 [HttpGet] attributes, each specifying a different route:
- api/Employee/All
- api/Employee/AllEmployees
- api/Employee/GetAll
This configuration allows clients to access the same resource using any of these URLs. Now, run the application and access the above resource using the different URLs and you should get the same result as shown in the below image.
Using a web browser or Postman, accessing any URLs should display the same list of employees, confirming that the GetAllEmployees method is accessible via multiple routes. As you can observe, each URL is unique. So, as long as the URLs are unique, you can access a particular resource using different URLs.
Handling Route Conflicts in ASP.NET Core Identity
While allowing multiple URLs for a single resource is beneficial, assigning the same route to multiple action methods can lead to conflicts. ASP.NET Core enforces unique routes for each action to prevent ambiguity. Let us prove this with an example. Please modify the Employee Controller as follows. Here, you can see we have two action methods in the EmployeeController with the same route, i.e., api/Employee/All:
using Microsoft.AspNetCore.Mvc; using RoutingInASPNETCoreWebAPI.Data; using RoutingInASPNETCoreWebAPI.Models; namespace EmployeeApi.Controllers { [ApiController] [Route("api/[controller]")] public class EmployeeController : ControllerBase { // First Action Method [HttpGet("All")] public ActionResult<IEnumerable<Employee>> GetAllEmployees() { var employees = EmployeeData.Employees; return Ok(employees); } // Second Action Method with Same Route [HttpGet("All")] public ActionResult<IEnumerable<Employee>> GetEmployees() { var employees = EmployeeData.Employees; return Ok(employees); } } }
Now, within the IDE, you might be getting a warning, as shown in the below image:
With the above changes, attempting to access api/Employee/All endpoint will result in an Internal Server Error with an AmbiguousMatchException, as shown in the image below.
As you can see in the above image, it is throwing an Internal Server Error saying AmbiguousMatchException: The request matched multiple endpoints. This error is because the ASP.NET Core routing system cannot determine which action method to invoke when multiple actions share the same route. This ambiguity leads to a runtime exception.
Note: So, the point that you need to remember is that each resource must have a unique URL, and also, it is possible that a resource can be accessed using multiple URLs as long as all the URLs are unique. However, accessing two or more resources using a single URL in the ASP.NET Core Web API Application is impossible.
Resolving Route Conflicts in ASP.NET Core Web API
To resolve such route conflicts, ensure each action method has a unique route. Now, change the Route Attribute of both the resources shown in the code below to give distinct URLs to each route.
using Microsoft.AspNetCore.Mvc; using RoutingInASPNETCoreWebAPI.Data; using RoutingInASPNETCoreWebAPI.Models; namespace EmployeeApi.Controllers { [ApiController] [Route("api/[controller]")] public class EmployeeController : ControllerBase { // First Action Method with Unique Routes [HttpGet("GetAll")] [HttpGet("AllEmployees")] public ActionResult<IEnumerable<Employee>> GetAllEmployees() { var employees = EmployeeData.Employees; return Ok(employees); } // Second Action Method with a Different Route [HttpGet("All")] public ActionResult<IEnumerable<Employee>> GetEmployees() { var employees = EmployeeData.Employees; return Ok(employees); } } }
With the above changes in place, you can now access the GetAllEmployees resource using two URLs, i.e., api/Employee/GetAll and api/Employee/AllEmployees. On the other hand, you can access the GetEmployees resource using the URL api/Employee/All.
Real-time Example: Endpoint Naming Changes
There may be times when you realize an endpoint name is not informative or needs to be rebranded. However, if you change it immediately, existing clients will break. Keeping both the old and new endpoint names simultaneously allows for a smooth transition.
For example, we previously named our endpoint as /api/old-employees. After some organizational changes, we decided that /api/staff is a clearer name. We want to keep /api/old-employees around until all our clients switch over.
using Microsoft.AspNetCore.Mvc; using RoutingInASPNETCoreWebAPI.Data; using RoutingInASPNETCoreWebAPI.Models; namespace EmployeeApi.Controllers { [ApiController] public class EmployeeController : ControllerBase { // Multiple route attributes to support old and new naming [Route("api/old-employees")] [Route("api/staff")] [HttpGet] public ActionResult<IEnumerable<Employee>> GetAllEmployees() { var employees = EmployeeData.Employees; return Ok(employees); } } }
Here,
- api/old-employees → Old endpoint, still functional for backward compatibility.
- api/staff → New, more descriptive endpoint.
Clients can use either URL without changing the underlying logic. Over time, you can phase out the old endpoint if usage drops to zero.
By using attribute routing in ASP.NET Core Web API, we can configure multiple URLs for a single resource. However, remember that each URL must be unique for each resource to avoid route conflicts and errors.
In the next article, I will discuss Token Replacement in ASP.NET Core Web API Attribute Routing with Examples. In this article, I explain How to set up Multiple URLs for a Single Resource in an ASP.NET Core Web API Application with Examples. I hope you enjoy using multiple URLs for a single resource in the ASP.NET Core Web API article.