How to add global route prefix in asp.net core 3?
You could refer to below demo in asp.net core 3.0 to set global route prefix with api version.You could set any prefix as you like by changing services.AddControllersWithViews(o => { o.UseGeneralRoutePrefix("api/v{version:apiVersion}"); });
1.Create a custom MvcOptionsExtensions
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;
}
}
}
}
2.Register in Startup.cs( you need to install package Microsoft.AspNetCore.Mvc.Versioning ,current version for 3.0 is 4.0.0-preview8.19405.7)
public void ConfigureServices(IServiceCollection services) {
//MVC service registration
//https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.0&tabs=visual-studio#mvc-service-registration
services.AddControllersWithViews(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.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints = >{
endpoints.MapControllerRoute(
name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}
3.Controller:
[ApiVersion("1")]
[ApiVersion("2")]
[Route("test")]
[ApiController]
public class TestController : ControllerBase
{
[HttpGet("version"), MapToApiVersion("1")]
public IActionResult GetV1()
{
return new OkObjectResult("Version One");
}
}
4.Result
Calling /api/v1/test/version
results in "Version One".
I solved this in 3.1 with just the below in my startup Configure()
:
app.UsePathBase(new PathString("/api"));
As @alastairtree answered you can use app.UsePathBase
to achieve this.
You need to place this call before registering the middleware that needs to be prefixed.
If you need to register other middleware after that, that should not be prefixed, you can reset the prefix to /
.
Full example:
app.UsePathBase(new PathString("/api"));
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
app.UsePathBase(new PathString("/"));
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});