Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@itavero
Last active July 25, 2023 21:05
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save itavero/2b40dfb476bebff756da35b5c7ff7384 to your computer and use it in GitHub Desktop.
Save itavero/2b40dfb476bebff756da35b5c7ff7384 to your computer and use it in GitHub Desktop.
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
Copy link
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.

@guillaume86
Copy link

Thanks, that was great help for me. Using a similar method I wrote an adapter to support [RoutePrefix] and ease a migration from an old WebAPI project to ASP.NET Core.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment