In this article, we will learn how to add a global route prefix in ASP.NET Core. This enables us to effortlessly incorporate the route prefix into our application’s routing mechanism, offering greater flexibility and control.

To download the source code for this article, you can visit our GitHub repository.

By default, we define routing on a per-action basis. However, in certain scenarios, we may want to incorporate a global route prefix explicitly, applying it to all routes in our application.

To achieve this, we can leverage a middleware approach, which provides a centralized mechanism for adding the prefix.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

Before diving into this topic, we recommend reading the basics of Working with ASP.NET Core Middleware.

Implement Global Route Prefix With Middleware

There are a few steps that we have to follow to achieve this using middleware in ASP.NET Core.

First, we need to create a new GlobalRoutePrefixMiddleware class to handle a global route prefix:

public class GlobalRoutePrefixMiddleware
{
    private readonly RequestDelegate _next;
    private readonly string _routePrefix;

    public GlobalRoutePrefixMiddleware(RequestDelegate next, string routePrefix)
    {
        _next = next;
        _routePrefix = routePrefix;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        context.Request.PathBase = new PathString(_routePrefix);
        await _next(context);
    }
}

The constructor accepts RequestDelegate parameter and a string parameter representing the desired global prefix. The InvokeAsync method serves as the entry point for the middleware’s execution and accepts the HttpContext. This method is responsible for modifying the PathBase property of the incoming request in order to add a global prefix.

Inside the InvokeAsync method, we set the context.Request.PathBase property to a new PathString instance, using the _routePrefix variable as its value. This means that the route prefix specified in _routePrefix will be appended to the base path of the request URL.

After setting the PathBase, the method calls the _next delegate, passing the modified context object as an argument.

Next, in our Program.cs file, let’s include the GlobalRoutePrefixMiddleware:

app.UseMiddleware<GlobalRoutePrefixMiddleware>("/api/v1");

It is crucial to ensure that we place the UseMiddleware early in the pipeline, before any middleware that relies on routing.

Here we’re passing “/api/v1” as the prefix into the constructor so that the prefix will be applied to all routes in our application.

We also have to add one more piece of code to our Program class:

app.UsePathBase(new PathString("/api/v1"));

We use this to extract the specified path base from the request path and enable route mapping.

Testing the Global Route Prefix

To test this, let’s create a simple ProductsController with the GetProducts action:

[ApiController]
[Route("products")]
public class ProductsController : ControllerBase
{
    [HttpGet]
    public ActionResult<List<Product>> GetProducts()
    {
        var products = new List<Product>()
        {
            new Product { Id = 1,Name = "The Secret Recipes of Chef Uyi",Category = "Book",Price = 100},
            new Product { Id = 2,Name = "Lenovo Yoga Laptop",Category = "Tech Gadget",Price = 2000}
        };

        return Ok(products);
    }
}

By applying the middleware approach with a global route prefix, the GetProducts action’s actual URL becomes "/api/v1/products". The “/api/v1” prefix will be automatically added to all routes defined in our application. This also helps with API versioning.

Conclusion

In this article, we learned how adding a global route prefix in ASP.NET Core is achievable using middleware. We adopted an approach that utilizes the GlobalRoutePrefixMiddleware class to add the prefix. This method enables us to achieve a consistent and unified URL structure across our application. By leveraging this technique, we can enhance the organization and readability of our routes, making it easier to manage and maintain our application.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!