Search code examples
c#asp.net-coreapi-versioningaspnet-api-versioning

What does UseApiBehavior property do in the ApiVersioning library?


I am trying to enable swagger in my application, but as I am retrofitting it to legacy applications I would like to know exactly what changes I am making.

On the internet it suggests adding the following to make the Swagger endpoints appear

builder.Services.AddApiVersioning(opt =>
{ 
    opt.UseApiBehavior = false;
});

This property makes the endpoints appear, which is great. But I cant find any information on what this property is actually doing.

Is it changing the way my endpoints behave in any way or just exposing them for Swagger to read?

Visual studio comment on the method says:

Gets or sets a value indicating whether to use web API behaviors. True to use web API behaviors; otherwise, false. The default value is true When this property is set to true, API versioning policies only apply to controllers that remain after the IApiControllerFilter has been applied. When this property is set to false API versioning policies are considers for all controllers. This was default behavior behavior in previous versions

But I'm not sure what is meant when it talks about "APIVersioningPolicies only apply"

I cant find any information about the property in the Versioning wiki page https://github.com/dotnet/aspnet-api-versioning/wiki/API-Versioning-Options

I am cautious because I dont want to introduce any breaking changes


Solution

  • In ASP.NET Core, a controller is just a controller. Some people choose to use API Versioning in the same application as their UI application. Although most UI controllers derived from Controller and API controllers typically derived from ControllerBase, that was ever a requirement. UI controllers are not meant to be versioned and often produced a behavior that developers didn't like/want - namely UI controllers shouldn't be versioned. While there were a few possible workarounds, sorting out the ambiguity of controllers was not straight forward.

    ASP.NET Core 2.1 introduced the notion of API Behaviors via IApiBehaviorMetadata which is implemented by ApiControllerAttribute. When you apply [ApiController] to a controller or assembly, you opt into a consistent baseline of standard API-like behaviors. This also provided a way to disambiguate controllers in an organic way. If you apply [ApiController], then you almost certainly intended for that controller to represent an API (I've never seen that not be the case). This led to API Versioning adding IApiControllerFilter to filter out controllers that should be considered an API. The default implementation accepts a sequence of IApiControllerSpecification, one of which matches whether [ApiController] is applied and one that matches OData routing.

    These changes were introduced in API Versioning 3.0 and made it natural to filter out controllers. Unfortunately, existing library consumers may have relied on the previous behavior, which could lead to a breaking change. UseApiBehavior was added as a configurable option with a default value of false (to keep the old behavior) and allow people to transition as not everyone would necessary rush to update all their controllers or assemblies with [ApiController]. Starting in API Versioning 4.0, UseApiBehavior defaulted to true. You must be using an older version of the library because this option property was completely removed in 6.0+. To change the behavior in >= 6.0, you would replace the IApiControllerFilter service via DI. There is a built-in NoApiControllerFilter implementation that would be equivalent to UseApiBehavior = false.

    I have no clue where Swagger/OpenAPI is coming into the picture here; the two are not related. Applying API Behaviors does not affect whether APIs appear in OpenAPI; however, failing to change the filter or to apply [ApiController] would. The API Versioning API Explorer extensions provide everything needed to collate APIs by their versions. If you're able to elaborate on your question and how it's related to OpenAPI (formerly Swagger), I can expand or clarify my answer.