6.2.0
This is a minor release which contains mostly fixes and a few new enhancements. The next phase in the roadmap will be supporting .NET 7.0.
.NET Core 3.1 will be End of Life in December of 2022; therefore, support for that target framework will be dropped in the next major release. With the exception of servicing for bug fixes, this will be the last release for .NET Core 3.1.
Features
Abstractions
- Added
ApiVersionMetadata
copy constructor
All Platforms
- Add complex media type API version reader support (#887)
ASP.NET Web API
- Type-forward route parsing from API Explorer to core library
ASP.NET Web API with OData
- Add support for exploring OData metadata routes (#893)
ASP.NET Core
- Support
406
and415
withProblemDetails
(#886) - Handle missing
ApiVersionMetadata
(#891) - Handle multiple
SelectorModel
instances (#896) - Add
IApiVersionDescriptionProviderFactory
(enables DI withinDescribeApiVersions
) - Add support for custom group name formatting
ASP.NET Core with OData
- Add support for exploring OData metadata routes (#893)
New Feature Preview
Enhanced Media Type Reader
The new MediaTypeApiVersionReaderBuilder
has compositional support with the following features:
- Multiple parameters (if they vary by media type)
- Including specific media types
- Excluding specific media types
- Matching a version in a media type by regular expression (it's an escape hatch really)
- Matching a version in a media type by a template
- Disambiguate from multiple choices
Here's a basic example:
var builder = new MediaTypeApiVersionReaderBuilder()
var reader = builder
.Parameter( "v" )
.Include( "application/json" )
.Include( "application/xml" )
.Template( "application/vnd-v{ver}+json" )
.Template( "application/vnd-v{ver}+xml" )
.Build();
This will match:
- A parameter named
v
on any media type filtered to:application/json
application/xml
- A media type matching the template
application/vnd-v{ver}+json
wherever
is the user-defined parameter name - A media type matching the template
application/vnd-v{ver}+xml
wherever
is the user-defined parameter name
Composite Group Names
The API Explorer and OpenAPI (aka Swagger) UI do not support multi-level grouping. Implementing some form of this
has been possible, but complex in the past. API Versioning uses a formatted API version as the group name as a
logical choice, but some people want to combine that with a group name. A new feature will give you the option
to format a group name and API version together.
services.AddApiVersioning()
.AddApiExplorer( options =>
{
options.GroupNameFormat = "'v'VVV";
options.FormatGroupName = (groupName, apiVersion) => $"{groupName}-{apiVersion}";
});
There are multiple ways to define a group name, but a controller might look like:
[ApiVersion( 1.0 )]
[ApiController]
[ApiExplorerSettings( GroupName = "Example" )]
[Route( "[controller]" )]
public class ExampleController : ControllerBase
{
[HttpGet]
public IActionResult Get() => Ok();
}
The formatting rules are as follows:
ApiVersion.ToString( ApiExplorerOptions.GroupNameFormat )
is the default group name- If a group name is defined and
ApiExplorerOptions.FormatGroupName
isnull
, the group name is used - If a group name is defined and
ApiExplorerOptions.FormatGroupName
is notnull
, the callback is invoked with the group name and formatted API version - If a group name is not defined, then the formatted API version is used
In the example above, the final group name will become Example-v1
.
OData Metadata Endpoints
OData has a built-in Service Document and Metadata endpoint. These largely serve the same purpose as OpenAPI (aka Swagger) in
days gone by. You might, however, still want these to show up. The default will continue to keep them hidden, but you can now enable
showing one or both of them via:
services.AddControllers().AddOData();
services.AddApiVersioning()
.AddOData( options => options.AddRouteComponents() )
.AddODataApiExplorer( options.MetadataOptions = ODataMetadataOptions.All );
Breaking Changes
No known breaking changes
Contributors
Thanks you to all that contributed directly with code, filling issues, and in-depth discussions. In particular, special thanks to:
- @mlunelli (#889, #891)
- @gimlichael (#886, #887)
- @Angelinsky7 (#893)
- @orryverducci (#896)
- @brandonsmith86 (#899)