Search code examples
asp.net-coreroutes

How to add global route prefix in asp.net core 3?


Legacy .net core frameworks used UseMvc() for adding global route prefix. How to make it for asp.net core 3 without UseMvc() ?


Solution

  • 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://learn.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".