9

I need to automatically add api/ prefix to every end point in my asp .net core web API. How to do that?

1
  • 2
    Seems you can use a constant. public static class Consts { public const string DefaultRoute = "api/[controller]"; } and re-use it everywhere. If you need to change the default route everywhere - just change the constant. [Route(Consts.DefaultRoute)] Commented Feb 13, 2023 at 21:53

5 Answers 5

10

You can custom MvcOptionsExtensions to set route prefix globally instead of change the route attribute manually.

1.custom MvcOptionsExtensions:

public static class MvcOptionsExtensions
{
    public static void UseRoutePrefix(this MvcOptions opts, IRouteTemplateProvider routeAttribute)
    {
        opts.Conventions.Add(new RoutePrefixConvention(routeAttribute));
    }

    public static void UseRoutePrefix(this MvcOptions opts, string
    prefix)
    {
        opts.UseRoutePrefix(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(version before .Net6) or in Program.cs(version beyond .Net 6):

services.AddControllers(o =>{
    o.UseRoutePrefix("api");
});

Or:

builder.Services.AddControllers(o =>{
    o.UseRoutePrefix("api");
});
Sign up to request clarification or add additional context in comments.

1 Comment

Where I should add that custom MvcOptionsExtensions?
2

Make your controller constructor with Route Prefix "api/"

For example lets say your controller class name is CustomerController

[Route("api/[controller]")]
public class CustomerController : ControllerBase
{

}

// This will become api/customer
[HttpGet]
public async Task<ActionResult> GetCustomers()
{
   // Code to get Customers
}

// This will become api/customer/{id}
[HttpGet]
[Route("{id}")]
public async Task<ActionResult> GetCustomerById(int id)
{
   // Code to get Customer by Id
}
    

1 Comment

I need to add that to every controllers not only for one controller. So If I have 20 controllers, in this method I have to change every controller manually if I need to change the prefix.
2

Seems you can use a constant.

public static class Consts
{
    public const string DefaultRoute = "api/[controller]";
}

and re-use it everywhere. If you need to change the default route everywhere - just change the constant.

[Route(Consts.DefaultRoute)]
public class TestController : ControllerBase
{
...
}

Comments

1

In ASP.NET Core 6+ I had to use one of the below options:

  • Set a global conventional controller route template:

    app.MapControllerRoute(
          name: "default",
          pattern: "api/{controller}/{action}");
    

    Note: for conventional routing to work, your controllers cannot have the ApiController attribute, which enforces attribute routing (second option below).

  • Use a base controller class with your route pattern, and inherit it in all your controllers:

    [ApiController]
    [Route("api/[controller]")]
    public class BaseApiController : ControllerBase
    { }
    
    //This will have the route "api/WeatherForecast"
    public class WeatherForecastController: BaseApiController
    {
         ....
    }
    

    I found this option to be the most flexible, especially if you're using Swagger, as it doesn't support conventional route templates.

  • Use the PathBase middleware:

    app.UsePathBase("/api");
    app.UseRouting():
    

    This one seems to be suggested in plenty of places, however, it's important to note that this does not actually add a prefix to your routes, rather, it is ignoring(effectively) the specified path base in requests, so that they still end up hitting the controllers that don't have /api in their route; those routes without /api will still exist and be valid, resulting in duplicate endpoints.

    The intended purpose of this middleware is to remove an optional prefix from a request. I find using it to achieve what we want here bastardising it.

Comments

0

we can simply add that in top of the controller like this

[Route("api/[controller]")]
public class TestController : ControllerBase
{
    [HttpGet("version")]
    public IActionResult Get()
    {
        return new OkObjectResult("Version One");
    }
   [HttpGet("Types")]
    public IActionResult GetTypes()
    {
        return new OkObjectResult("Type One");
    }
}

so that you can access like below

....api/Test/version
....api/Test/Types

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.