Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Global route prefix in ASP.NET Core 2.0
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.Routing;
namespace MyWebApi.Extensions
{
public static class MvcOptionsExtensions
{
public static void UseGeneralRoutePrefix(this MvcOptions opts, IRouteTemplateProvider routeAttribute)
{
opts.Conventions.Add(new RoutePrefixConvention(routeAttribute));
}
public static void UseGeneralRoutePrefix(this MvcOptions opts, string prefix)
{
opts.UseGeneralRoutePrefix(new RouteAttribute(prefix));
}
}
public class RoutePrefixConvention : IApplicationModelConvention
{
private readonly AttributeRouteModel _routePrefix;
public RoutePrefixConvention(IRouteTemplateProvider route)
{
_routePrefix = new AttributeRouteModel(route);
}
public void Apply(ApplicationModel application)
{
foreach (var selector in application.Controllers.SelectMany(c => c.Selectors))
{
if (selector.AttributeRouteModel != null)
{
selector.AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel(_routePrefix, selector.AttributeRouteModel);
}
else
{
selector.AttributeRouteModel = _routePrefix;
}
}
}
}
}
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MyWebApi.Extensions;
namespace MyWebApi
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(o => { o.UseGeneralRoutePrefix("api/v{version:apiVersion}"); });
services.AddApiVersioning(o => o.ReportApiVersions = true);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
}
using Microsoft.AspNetCore.Mvc;
namespace MyWebApi.Controllers
{
[ApiVersion("1")]
[ApiVersion("2")]
[Route("test")]
public class TestController : Controller
{
[HttpGet("version"), MapToApiVersion("1")]
public IActionResult GetV1()
{
return new OkObjectResult("Version One");
}
[HttpGet("version"), MapToApiVersion("2")]
public IActionResult GetV2()
{
return new OkObjectResult("Version Two");
}
}
}
@itavero

This comment has been minimized.

Copy link
Owner Author

itavero commented May 18, 2018

Manually edited the namespaces (so there might be a mistake in those).

  • Calling /api/v1/test/version results in Version One.
  • Calling /api/v2/test/version results in Version Two.
  • Calling /api/v3/test/version results in:
{
error: {
code: "UnsupportedApiVersion",
message: "The HTTP resource that matches the request URI 'http://localhost:5432/api/v3/test/version' does not support the API version '3'.",
innerError: null
}
}
@itavero

This comment has been minimized.

Copy link
Owner Author

itavero commented May 18, 2018

Unfortunately it does not play nice when I have multiple controllers with the "same" route (one for v1 and one for v2). 😞

@itavero

This comment has been minimized.

Copy link
Owner Author

itavero commented May 18, 2018

Further investigation shows that it was not working in my case because the ApiVersionAttribute was set on an abstract base class of the actual Controller. Adding the attribute to the actual Controller resolved the error, however I do feel that this is a bug in the package.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.