6

I am trying to add versioning to my web api and after reading asp .net core documentation it seemed that IApplicationBuilder.UsePathBase could serve to this purpose. And, it really does but with a quirk. The api can still be accesed without adding the versioning path.

As an example, I use this to add an v1 path to my api:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHttpContextAccessor httpAccesor)
{
    app.UsePathBase("/api/v1");
    ....
}

Now I am able to access my cars endpoint by using http://www...com/api/v1/cars or by using http://www...com/cars.

The cars controller routing is setup this way:

[Authorize]
[Route("/[controller]")]
[ApiController]
public class DriversController : ControllerBase
{
  ....
}

So, is this how it works? Is there any possibility to just allow paths with the corresponding versioning path?

Notbad
  • 5,936
  • 12
  • 54
  • 100

4 Answers4

3

As per document Here's extracts the specified path from a request. If it is not provided in the request then it will be ignored.

It's useful with micro-service architecture where multiple micro-services are hosted with docker and Load Balancer can route the request base on a request path. so it not required to do any URL mapping or re-write the path.

Hope this would clear your queries.

.Net core 2.2 versioning: we used Microsoft.AspNetCore.Mvc.Versioning NuGet package OR GIT for our project and it's in .net core 2.2. It's required some set in Setup.cs -> ConfigureService method file and then you can use in your controller i.e. [Route("api/v{v:apiVersion}/[controller]")]

Setup.cs -> ConfigureService

services.AddApiVersioning(o =>
            {
                o.ReportApiVersions = true;
                o.AssumeDefaultVersionWhenUnspecified = true;
                o.DefaultApiVersion = new ApiVersion(1, 0);
            });
  • Ok, I see, I overlooked this part. So, Is there any way to add the versioning part of the path (/api/v1) without modifying all the controllers routes. I mean, I need an easy way to be able to change endpoints urls based on a versioning string. If tomorrow I want to change /api/v1 to /api/v2 I don't want to change that in every controller routing attribute :/. – Notbad Jun 30 '20 at 09:13
  • 1
    @Notbad, we used **Microsoft.AspNetCore.Mvc.Versioning** NuGet package for our project and it's in .net core 2.2. It's required some set in Setup.cs -> ConfigureService method file and then you can use in your controller i.e. `[Route("api/v{v:apiVersion}/[controller]")]` *Setup.cs -> ConfigureService*: `services.AddApiVersioning(o => { o.ReportApiVersions = true; o.AssumeDefaultVersionWhenUnspecified = true; o.DefaultApiVersion = new ApiVersion(1, 0); });` – Mukesh Vadodariya Jun 30 '20 at 09:53
1

My problem was the order in which I did the UsePathBase. If I put one line later it doesn't work.

  app.UsePathBase("/MyPath");
  app.UseRouting();
  app.UseEndpoints(endpoints =>
  {
     endpoints.MapControllers();
  });
T Brown
  • 1,385
  • 13
  • 9
1

In order to enforce a global prefix route with a global versioning to your controllers you can check the answer of this stackoverflow question

I copied the answer here:

Startup.cs class:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(o => {
        o.UseGeneralRoutePrefix("api/v{version:apiVersion}");
    });
   // you need to install package Microsoft.AspNetCore.Mvc.Versioning
    services.AddApiVersioning(o = >o.ReportApiVersions = true);
}

Now implement UseGeneralRoutePrefix method as below:

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;
            }
        }
    }
}

Then in your controller add the version that you want using ApiVersion(...), and you should specify [ApiController] else it wont work:

[ApiVersion( "1" )]
[ApiController]
[Route("[controller]")]
public class MyController : Controller {

}
Nassim BG
  • 23
  • 6
0

IN your Startp.cs you have the method "Configure". Add this command there and should work. (Check if you already have this command there and just edit). app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "api/v1/{controller}/{action=Index}/{id?}"); });

And just keep the controller name in controller class.