Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSwag .NET Core API Versioning configuration

I'd like to prepare my .NET Core Web API project so that multiple versions of the API can be managed and documented, according to the REST services standards.

I'm using .NET Core 2.1 with NSwag (v11.18.2). I also installed the Microsoft.AspNetCore.Mvc.Versioning NuGet package.

I already searched with Google for some configuration examples, but the only useful link I found is this.

I'm now able to get Swagger pages for both API versions but with some problems:

  1. Please note that none of the last config settings (Title, Description, etc.) takes effect on any of the 2 routes. It only works if I add them on each of the individual configuration. So I'd also like to know if it possible to avoid that, since the general configuration of the API can be version indipendent (title, description and so on...).
  2. Since the issue with NSwag and Microsoft API Versioning package discussed in the above link, was opened 2-3 months (and NSwag versions too) ago, I'd like to know if it is now truly fixed and in this case, which is the right configuration to set.
  3. Although the version is explicit in the configuration of the controllers, it is still required as a mandatory input parameter of the controller methods and of course I don't want that! See image:

Swagger UI tests requiring version as input parameter for methods

So, my actual configuration, by following that example, is looking like this:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddApiVersioning(options =>
        {
            options.AssumeDefaultVersionWhenUnspecified = true;
            options.DefaultApiVersion = new ApiVersion(1, 0);
            options.ReportApiVersions = true;
        });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseSwaggerWithApiExplorer(config =>
    {
        config.GeneratorSettings.OperationProcessors.TryGet<ApiVersionProcessor>().IncludedVersions = new[] { "1.0" };
        config.SwaggerRoute = "v1.0.json";
    });

    app.UseSwaggerWithApiExplorer(config =>
    {
        config.GeneratorSettings.OperationProcessors.TryGet<ApiVersionProcessor>().IncludedVersions = new[] { "2.0" };
        config.SwaggerRoute = "v2.0.json";
    });

    app.UseSwaggerUi3(typeof(Startup).GetTypeInfo().Assembly, config =>
    {
        config.SwaggerRoutes.Add(new SwaggerUi3Route("v1.0", "/v1.0.json"));
        config.SwaggerRoutes.Add(new SwaggerUi3Route("v2.0", "/v2.0.json"));

        config.GeneratorSettings.Title = "My API";
        config.GeneratorSettings.Description = "API functionalities.";
        config.GeneratorSettings.DefaultUrlTemplate = "{v:apiVersion}/{controller}/{action}/{id?}";
        config.GeneratorSettings.DefaultPropertyNameHandling = PropertyNameHandling.CamelCase
    });
}

And these are my actual controllers:

[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]/[action]")]
[SwaggerTag("Test1", Description = "Core operations on machines (v1.0).")]
public class MachinesController : Controller
{
    [HttpGet("{id}")]
    [ProducesResponseType((int)HttpStatusCode.OK)]
    public async Task<ActionResult<Machine>> Get(int id)
    {
        return await ...
    }
}

[ApiController]
[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/[controller]/[action]")]
[SwaggerTag("Test2", Description = "Core operations on machines (v2.0).")]
public class MachinesController : Controller
{
    [HttpGet("{id}")]
    [ProducesResponseType((int)HttpStatusCode.OK)]
    public async Task<ActionResult<Machine>> Get(int id)
    {
        return await ...
    }
}
like image 365
Cheshire Cat Avatar asked Aug 06 '18 14:08

Cheshire Cat


2 Answers

  1. They are ignored in the middleware because they are inferred from the settings or do not apply for api explorer (template). However title and description should work...
  2. Please create an issue with the specific issue and a repro, also check out the existing tests in the repo
  3. Fixed with v11.18.3
like image 145
Rico Suter Avatar answered Sep 17 '22 19:09

Rico Suter


I believe starting in NSwag 12.0.0, there is significantly improved support for the API Explorer. It's important that the complementary API Explorer package for API versioning is also referenced so that the proper information is provided to NSwag.

The Swagger sample application provided by API Versioning uses Swashbuckle, but the setup will be very similar to NSwag. You can use the IApiVersionDescriptionProvider service to enumerate all of the API versions defined in your application. That should significantly simplify your NSwag configuration.

You're versioning by URL segment; therefore, to address Problem 3 you simply need to configure the API Explorer a la:

services.AddVersionedApiExplorer( options => options.SubstituteApiVersionInUrl = true );

This will replace the {version} route parameter in the route template with the corresponding API version value and remove the API version parameter from the API description.

like image 25
Chris Martinez Avatar answered Sep 17 '22 19:09

Chris Martinez