Last active
July 25, 2023 21:05
-
-
Save itavero/2b40dfb476bebff756da35b5c7ff7384 to your computer and use it in GitHub Desktop.
Global route prefix in ASP.NET Core 2.0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | |
} | |
} | |
} |
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
Further investigation shows that it was not working in my case because the
ApiVersionAttribute
was set on an abstract base class of the actualController
. Adding the attribute to the actualController
resolved the error, however I do feel that this is a bug in the package.