ApiVersion attribute not working in .NET 8 [closed]
Asked Answered
M

1

11

I recently upgraded my webapi to .NET 8. As I test my controller, the ApiVersion attribute is not working in the swagger page.

[ApiVersion("1.0")]
[Route("v{version:apiVersion}/api/[controller]")]
[ApiController]
[Authorize]
public class SubscriptionController(ISubscriptionDataService subscriptionDataService, 
                                    IConfigurationService configurationService) : ControllerBase

In the swagger page, the version is not being filled in by default as it was in .NET 7.

enter image description here

Previously, with the default template weatherforecast controller, the behavior was filled in by default.

The code for that controller was as shown.

[ApiVersion("1.0")]
[Route("v{version:apiVersion}/api/[controller]")]
[ApiController]
[Authorize]
public class WeatherForecastController : ControllerBase

enter image description here

In the Program.cs, the following is added to perform the versioning.

private static void AddApiVersioning(IServiceCollection services)
{
    services.AddApiVersioning(options =>
    {
        options.AssumeDefaultVersionWhenUnspecified = false;
        options.ReportApiVersions = false;
    });

    services.AddVersionedApiExplorer(options =>
    {
        options.GroupNameFormat = "'v'VVV";
        options.SubstituteApiVersionInUrl = true;
    });
}

Edit 1

As a result of the following deprecations below, the way this was done needs to change.

Microsoft.AspNetCore.Mvc.Versioning -> Asp.Versioning.Mvc Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer -> Asp.Versioning.Mvc.ApiExplore

In Program.cs, the following needs to be done:

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.AddApiVersioning(options =>
{
    options.DefaultApiVersion = new ApiVersion(1, 0);
    options.AssumeDefaultVersionWhenUnspecified = false;
    options.ReportApiVersions = false;
}).AddApiExplorer(options =>
{
    options.GroupNameFormat = "'v'VVV";
    options.SubstituteApiVersionInUrl=true;
});


var app = builder.build();

app.UseSwagger();
app.UseSwaggerUI(options =>
{
    var descriptions = app.DescribeApiVersions();
    foreach (var description in descriptions)
    {
        var url = $"/swagger/{description.GroupName}/swagger.json";
        var name = description.GroupName.ToUpperInvariant();
        options.SwaggerEndpoint(url, name);
    }
});

In the controller, the [ApiVersion("1.0")] attribute should be replaced with [Asp.Versioning.ApiVersion("1.0")].

This works in the generated Microsoft webapi template, but still fails (i.e. having to enter the version) if using other swagger attributes and having other middlewares.

Edit 2

After much experimentation, it seems like multiple routes at both the class level and method level no longer work, even in the Microsoft Test Project.

Not Working in Swagger

using Microsoft.AspNetCore.Mvc;

namespace webapitest.Controllers;

[Asp.Versioning.ApiVersion("1.0")]
[Route("v{version:apiVersion}/api/[controller]")]
[ApiController]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    [HttpGet]
    [Route(("/Weather"))]
    public IEnumerable<WeatherForecast> Get()
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
    }
}

Working in Swagger

using Microsoft.AspNetCore.Mvc;

namespace webapitest.Controllers;

[Asp.Versioning.ApiVersion("1.0")]
[ApiController]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    [HttpGet]
    [Route(("v{version:apiVersion}/api/[controller]/Weather"))]
    public IEnumerable<WeatherForecast> Get()
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
    }
}

Would anyone understand why these do not work anymore?

Moyers answered 17/11, 2023 at 14:51 Comment(4)
This is related to the deprecation of Microsoft.AspNetCore.Mvc.Versioning replaced with Asp.Versioning.Mvc and the deprecation of Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer replaced with Asp.Versioning.Mvc.ApiExplorerMoyers
So which one is expected? The second one?Doucet
@GuruStron Please see Edit 1 above. This solves a portion of the issues and was obtained using the Nick Chapsas video "Implementing Modern API Versioning in .NET" at youtube.com/watch?v=8Asq7ymF1R8. The video is out of date though as some of the lines of code do not work in .NET 8.Moyers
Your question as phrased is unclear. Are your edits solutions to the original problem? If so, they need to be posted as an answer, not as edits to the question.Tangible
W
4

For anyone else still facing a similar issue to this .NET 8 Support is available.

Simply Update your Asp.Versioning packages to version 8.0.0

Wolfsbane answered 11/12, 2023 at 12:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.