Global route prefix in ASP.NET Core MVC (revisited)

A couple of months ago I blogged about adding a feature to ASP.NET Core MVC (or ASP.NET 5 at the time) that will allow you to set central route prefix(es) to your attribute routing mechanism.

That solution was written against beta8 version of ASP.NET Core and since now we are at RC2 – it doesn’t (surprise, surprise) work anymore.

Here is the updated version.

Global route prefixing in ASP.NET Core MVC overview

The original solution took advantage of the IApplicationModelConvention extensibility point – which allows you to inject custom conventions for the various configuration pieces of the MVC framework.

This still holds true – the extensibility point is the same in RC2. If you followed for example my work on typed routing for ASP.NET Core MVC (code is here on Github), that functionality uses IApplicationModelConvention to plug in the custom logic into MVC as well.

In the case of globally prefixing all your routes, we are going to use the same mechanism.

To recap: the ApplicationModel exposes a bunch of things about your MVC application – among them, all controllers that have been discovered. Then you can iterate through them, and access all discovered actions, action parameters and all useful framework components like that.

You can then plug your custom convention in against your MVC options object in the Startup class of your MVC application, and the convention will applied by the MVC runtime as your application is started.

So in this case we can leverage this, to inject a global route prefix into every controller.

Solution for ASP.NET Core MVC RC2

Again, the overall solution was already discussed in the original post.

The code, updated to RC2 is as follows:

What changed in RC2 is that the controllers and actions no longer expose a property AttributeRoutes on them. Instead, they have a collection of so called SelectorModels attached to them. This is an extra layer of flexibility, as it allows you to provide different action selection ways that can lead to this controller/action.

Attribute routing, along with action constraints (such as i.e. HTTP method constraint), is then exposed as a property of a selector model.


In order to use this, you need to insert this custom route convention into the MvcOptions at application startup.

So now your Startup may look like this:

In this case, api/v{version} will prefix every single route in your application. So you can now write controllers without any controller-level route attribute – or with a controller-level route attribute, and in both cases your global route prefix will be merged into them.

Below are two examples:

All the code for this post can be found on Github.