Releases: dotnet/aspnet-api-versioning
10.0.0 Preview 2
This release is a quick iteration which contains minor fixes based on feedback from Preview 1.
Trying out previews is always a big ask. The OpenAPI extensions are net new, so I really am looking for some community support to flush out any edge cases I may have been missed before releasing officially. All other libraries are stable.
Aside from whatever the community may report, there are only two final things I'm considering for the final release:
- gRPC versioning support, which I'm waiting on grpc/grpc-dotnet#2690 and grpc/grpc-dotnet#2693
- Coordination with Microsoft to open up types in Microsoft.AspNetCore.OpenAPI so I don't have to resort to Reflection for integration
If these are not able to be completed within the next few weeks, then I will officially release the stable libraries. The gRPC support will then come in a future, likely minor version, release. The OpenAPI extensions may stay in preview as AOT will likely be broken.
Features
All Platforms
- Support
_prefix character when extracting API versions from a .NET namespace (#1172) - Generate software bill of materials (SBOM) (#1100)
Fixes
ASP.NET Core with OpenAPI
- Build-time OpenAPI documents have empty paths (#1165, #1168)
- Missing XML Comments (#1169)
- Support
<example>tags (#1170)
Breaking Changes
The OpenAPI extensions for API Versioning (e.g. x-api-versioning) will now use a nested links property rather than a simple array. This allows the schema to be open for possible future enhancements.
Preview 1
{
"x-api-versioning":
[
{
"title": "Version Policy",
"type": "text/html",
"rel": "info",
"url": "http://my.api.com/policies/versioning.html"
}
]
}Preview 2+
{
"x-api-versioning":
{
"links":
[
{
"title": "Version Policy",
"type": "text/html",
"rel": "info",
"url": "http://my.api.com/policies/versioning.html"
}
]
}
}Contributors
- Thanks to @sander1095 for reporting and fixing the OpenAPI document generation in Minimal APIs (#1165)
- Thanks to @xavierjohn for adding enhanced support to allow namespaces that start with
_(#1172)
10.0.0 Preview 1
This is a major release that includes new, publicly visible API changes as well as a rollup of bug fixes. This is an initial preview release that is primarily focused on improving OpenAPI integration. Additional features will come in the next preview. The wiki has not be fully updated - yet, but that will also occur in the near future.
These are preview features and changes. Please report issues if you find them. Feel free to start a discussion about the changes in the forthcoming official release.
Features
All Platforms
ASP.NET Core
- Integration with the Microsoft.AspNetCore.OpenApi library
- These features in the new Asp.Versioning.OpenApi library
- OpenAPI documents are now generated per API version
- Sunset and deprecation policies are automatically included with standard (English) text, but can be customized
- Sunset and deprecation policies links are included in OpenAPI documents via the
x-api-versioningextension - The versioned
HttpClientcan now read and report on sunset and deprecation policies - All example projects have been updated to use Scalar
Example
The following provides an example of a bare minimum setup:
var builder = WebApplication.CreateBuilder( args );
var services = builder.Services;
services.AddApiVersioning()
.AddApiExplorer()
.AddOpenApi();
var app = builder.Build();
var hello = app.NewVersionedApi( "HelloWorld" );
var v1 = hello.MapGroup( "/hello-world" ).HasApiVersion( 1.0 );
var v2 = hello.MapGroup( "/hello-world" ).HasApiVersion( 2.0 );
v1.MapGet( "/", ( ApiVersion version ) => $"Hello world from v{version}" );
v2.MapGet( "/", ( ApiVersion version ) => $"Hello world from v{version}" );
if ( app.Environment.IsDevelopment() )
{
app.MapOpenApi().WithDocumentPerVersion();
}
app.Run();The key differences from what you may be currently doing:
- The calls to
services.AddOpenApi( "v1" )and so on are no longer used or needed app.MapOpenApi()has a supplemental.WithDocumentPerVersion()extension that enables multiple OpenAPI documents
In the same way that you can configure sunset policies, you can now specify deprecation policies:
services.AddApiVersioning()
.AddApiExplorer( options =>
{
options.Policies.Deprecate( 0.9 )
.Effective( DateTimeOffset.Now )
.Link( "policy.html" )
.Title( "Deprecation Policy" )
.Type( "text/html" );
})
.AddOpenApi();Fixes
ASP.NET Core
API Explorer
- Include
Descriptionproperty when cloning (#1160)
Breaking Changes
Breaking changes are always something to be taken seriously and should occur as infrequently as possible. When they do occur, they should occur at a clear, major version boundary. Breaking changes in the project will align to the .NET platform Long-Term Support (LTS) strategy. .NET 10 is a LTS version so now is the version to introduce these changes.
.NET 10 and C# 14 introduce extension members, which finally affords defining API Versioning extensions the way they were intended. More specifically, there are a number of extension properties that could not be written as such in the past. Extension properties enable more succinct code and express the intent where an extension method was the only option in the past. These make up the majority of the breaking changes, but unless you are an API Versioning extender or perform deep customization, you'll likely not notice any changes.
All Platforms
The introduction of deprecation polices highlighted the opportunity to genericize policy management and there is no longer a need for the sunset policy specific implementations. The function names and signatures remain the same, but the following types have been replaced:
ISunsetPolicyManager→IPolicyManager<SunsetPolicy>ISunsetPolicyBuilderExtensions→IPolicyBuilderExtensionsISunsetPolicyManagerExtensions→IPolicyManagerExtensions
ASP.NET Web API
The following extension methods are now extension properties.
HttpRequestMessageGetApiVersioningOptions()→ApiVersioningOptions { get; }GetApiVersioningProperties()→ApiVersioningProperties { get; }GetRequestedApiVersion()→RequestedApiVersion { get; }
HttpActionDescriptorGetApiVersionMetadata(),SetApiVersionMetadata()→ApiVersionMetadata { get; set; }
HttpConfigurationGetApiVersioningOptions()→ApiVersioningOptions { get; }
HttpControllerDescriptorGetApiVersionModel(),SetApiVersionModel()→ApiVersionModel { get; set; }
API Explorer
The following extension methods are now extension properties.
ApiDescriptionGetApiVersion()→ApiVersion { get; }IsDeprecated()→IsDeprecated { get; }GetGroupName()→GroupName { get; }GetUniqueID()→UniqueID { get; }
OData
The following extension methods are now extension properties.
IEdmModelGetApiVersion()→ApiVersion { get; }IsAdHoc()→IsAdHoc { get; }
OData API Explorer
The following extension methods are now extension properties.
ApiDescriptionEdmModel()→EdmModel { get; }EntitySet()→EntitySet { get; }EntityType()→EntityType { get; }Operation()→Operation { get; }RoutePrefix()→RoutePrefix { get; }
ASP.NET Core
The following extension methods are now extension properties.
HttpContextApiVersioningFeature()→ApiVersioningFeature { get; }GetRequestedApiVersion()→RequestedApiVersion { get; }
MVC (Core)
The following types and members have been removed:
DefaultApiVersionGroupDescriptionProvider, which was internally identical toGroupedApiVersionDescriptionProvider- Obsolete constructor
public EndpointApiVersionMetadataCollationProvider( EndpointDataSource endpointDataSource ) - Removed
IServiceCollectionExtensions.EnableApiVersionBinding; it's now supported without explicit registration
The following extension methods are now extension properties.
ActionDescriptorGetApiVersionMetadata()→ApiVersionMetadata { get; }
ControllerModelGetApiVersionModel()→ApiVersionModel { get; }
API Explorer
The following extension methods are now extension properties.
ApiDescriptionGetApiVersion(),SetApiVersion()→ApiVersion { get; set; }IsDeprecated()→IsDeprecated { get; }GetSunsetPolicy(),SetSunsetPolicy()→SunsetPolicy { get; set; }
OData
The following extension methods are now extension properties.
IEdmModelGetApiVersion()→ApiVersion { get; }IsAdHoc()→IsAdHoc { get; }
Versioned HTTP Client
The following extension methods are now extension properties.
HttpResponseMessageReadSunsetPolicy()→SunsetPolicy { get; }
Contributors
- Huge thanks to @MGessinger who implemented most of the new
deprecationheader support (#1151)
8.1.0
This is a minor release that includes a new, publicly visible API changes as well as a rollup of bug fixes.
Features
ASP.NET Core
- Added
IEndpointInspector(#1066)- Enables controller action endpoints to not be processed by Minimal API endpoint collators
EndpointApiVersionMetadataCollationProviderhas a new constructor that acceptsIEndpointInspector- The previous constructor is now
Obsoleteand will be removed in a9.0
- The previous constructor is now
- Added
AddErrorObjectsmake integration with the legacy Error Objects format easier (related to #1072)- The underlying
JsonOptionsconfiguration will remain implicit as it is today, but9.0will remove it- It is recommended you use one of the
AddErrorObjectsextension methods versus mappingIProblemDetailsWriterexplicitly
- It is recommended you use one of the
- The associated
JsonSerializerContextis now accessible, if needed AddErrorObjects<TWriter>allows configuring an extended/customizedErrorObjectWritertype
- The underlying
- Added
IApiVersionDescriptionProviderFactory.Create()extension method- Replacing
IApiVersionDescriptionProviderFactoryin DI also now replacesIApiVersionDescriptionProvider IApiVersionDescriptionProvidercan still be individually replaced if you really want to
- Replacing
Fixes
All Platforms
- Correct sunset policy resolution when falling back (#1065)
- Fails to read new versions when available (#1070)
ASP.NET Core
- Using
ApiExplorerSettingsAttributetogether withApiVersionAttributeproduces unexpected number ofApiVersionDescriptions(#1066)
ASP.NET Core with OData
- Support OData Collection Parameters (#999)
Breaking Changes
None
8.0.0
This is the official release for .NET 8. This release primarily includes internal performance improvements based on new .NET 8 features and a limited set of new features.
Features
ASP.NET Core
- AOT Compatibility1:
Asp.Versioning.AbstractionsAsp.Versioning.HttpAsp.Versioning.Http.Client
- Added
IApiVersionSelector.SelectVersionAsync(#1009)- The default interface implementation simply calls
SelectVersion SelectVersionmust still be implemented- The synchronous path must be accounted for
- Some use cases, such as with OData, does have synchronous code paths that cannot be refactored
- The default interface implementation simply calls
1 The .NET Framework and ASP.NET MVC Core do not currently support AOT
Fixes
In addition to the rollup of fixes in 7.1.0, the following outlines the fixes in this release.
ASP.NET Core
ControllerNameAttributeis properly honored (#1042)
Breaking Changes
ASP.NET Core
- The
ErrorObjectWriterconstructor now requires anIOptions<JsonOptions>parameter- If you don't use Error Object responses, this change has no effect
- If you use Error Object responses, but you don't extend or customize the default
ErrorObjectWriter, the changes are transparent
Contributors
- Big thanks to @xavierjohn who:
- Fixed #1042
- Reviewed and researched AOT support
- Reviewed and researched many of the .NET 8 update issues
7.1.0
This release provides some minor updates and patches. This will be the final release before .NET 8, which is just around the corner.
Features
The following outlines all new features since 7.0, but some of them have already been released in a previous patch.
All Platforms
- Enable NuGet Symbol packages
- Validate
ApiVersioningOptions.DefaultApiVersioncannot beApiVersion.Neutral(#1011) - Support Error Object backward compatibility (#1019)
- See the Error Responses - Backward Compatibility topic
- Add
IApiVersionSelectortoApiExplorerOptions(#1025)- Derives from
ApiVersioningOptionsby default - Can be overridden with a different instance just for documentation
- Derives from
- Use
ApiExplorerOptions.ApiVersionSelectorwhile determining if the 1st API version parameter is required (#1025)
ASP.NET Web API with OData
- Use complex types instead of entities for ad hoc models so a key is not required
- Allow
EnableQueryAttributeto override Model Bound Settings (#928)
ASP.NET Core with OData
- Use complex types instead of entities for ad hoc models so a key is not required
- Allow
EnableQueryAttributeto override Model Bound Settings (#928)
Fixes
This is a rollup of all fixes since 7.0, some of which were already released in patch.
ASP.NET Web API
- Fix JSON serialization of
ProblemDetails.Type
ASP.NET Web API with OData
- Fix empty model check, which didn't include complex types
- Fix use of
$topin examples (#944) - Fix models in multiple EDMs with the same API version (#996)
ASP.NET Core
- Fix media type subset matching (#1015)
- Prevent possible infinite recursion reading API versions when misconfigured (#1017)
- Fix propagation of
ApiVersioningOptionstoApiExplorerOptions - Explicit API description should supersede implicit match (#1025)
ASP.NET Core with OData
- Fix empty model check, which didn't include complex types
- Fix use of
$topin examples (#944) - Fix models in multiple EDMs with the same API version (#996)
Breaking Changes
None
6.4.0
This is a backport of the OData API Explorer extensions for ad hoc EDM intended for .NET 6.0 and .NET Core 3.1. Most people should move on to 7.0.
Features
ASP.NET Core with OData
- Added support for ad hoc Model Bound Settings
- Add
ODataApiExplorerOptions.AdHocModelBuilderwhich is used in the same way asODataApiVersioningOptions.ModelBuilder - Examples:
- Add
Non-OData Model Bound Settings
Several OData query settings, such as the allowed properties, can only be configured using Model Bound settings. This information is annotated in the Entity Data Model (EDM). How do you configure this information if you're only using some of OData and don't have an EDM?
The OData API Explorer extensions already support using conventions, but it does not allow you to specify a convention which cannot be mapped to some combination of ODataQueryOptionSettings or ODataValidationSettings. ModelBoundSettings is supported, but mapping custom conventions over it would largely be a duplication of what ODataModelBuilder already does.
The new API Explorer support bridges this gap by creating ad hoc EDM instances on your behalf for the sole purpose of configuring Model Bound settings. This allows you to define configurations you couldn't otherwise without having to use an EDM. You have the choice to use attributes or the ODataModelBuilder fluent API for conventions.
Consider the following:
[Filter( "author", "published" )] // ← model bound settings with attributes
public class Book
{
public string Id { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public int Published { get; set; }
}The result of this configuration will show the $filter query option and indicate only the author and published properties can be used. If you prefer not to use attributes, the convention-based API can be used as well:
AddODataApiExplorer(
options =>
options.AdHocModelBuilder.DefaultConfiguration = (builder, version, prefix) =>
builder.ComplexType<Book>().Filter( "author", "published" ) ) ;The ad hoc EDM is only available during API exploration and is then discarded. It does not opt into any OData features.
Fixes
ASP.NET Core with OData
- Fixed empty EDM detection
Breaking Changes
None
Contributors
- @SamGuoMsft for pushing the backport to .NET 6.0 [LTS] (#928)
7.0.0
The official release for .NET 7.0 is finally here. There have been numerous changes between the previews and fixes that occurred in 6.0 so they will all be collated here for your convenience.
Features
The primary feature and enhancement areas include:
- Support for .NET 7.0
- Enhanced support for Minimal APIs with grouping
- Expanded support for exploring OData query options in non-OData APIs
Minimal APIs
var builder = WebApplication.CreateBuilder( args );
builder.Services.AddApiVersioning();
var app = builder.Build();
var orders = app.NewVersionedApi(); // ← group for an api with an optional name
var v1 = orders.MapGroup( "/api/order" ).HasApiVersion( 1.0 ); // ← all endpoints in this group have 1.0
var v2 = orders.MapGroup( "/api/order" ).HasApiVersion( 2.0 ); // ← all endpoints in this group have 2.0
v1.MapGet( "/{id:int}", ( int id ) => new V1.Order() { Id = id, Customer = "John Doe" } );
v2.MapGet( "/{id:int}", ( int id ) => new V2.Order() { Id = id, Customer = "John Doe", Phone = "555-555-5555" } );
v2.MapDelete( "/{id:int}", ( int id ) => Results.NoContent() );Non-OData Model Bound Settings
Several OData query settings, such as the allowed properties, can only be configured using Model Bound settings. This information is annotated in the Entity Data Model (EDM). How do you configure this information if you're only using some of OData and don't have an EDM?
The OData API Explorer extensions already support using conventions, but it does not allow you to specify a convention which cannot be mapped to some combination of ODataQueryOptionSettings or ODataValidationSettings. ModelBoundSettings is supported, but mapping custom conventions over it would largely be a duplication of what ODataModelBuilder already does.
The new API Explorer support bridges this gap by creating ad hoc EDM instances on your behalf for the sole purpose of configuring Model Bound settings. This allows you to define configurations you couldn't otherwise without having to use an EDM. You have the choice to use attributes or the ODataModelBuilder fluent API for conventions.
Consider the following:
[Filter( "author", "published" )] // ← model bound settings with attributes
public class Book
{
public string Id { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public int Published { get; set; }
}For ASP.NET Core, that's it; there is nothing else you need to do. ASP.NET Web API doesn't support DI out-of-the-box, so you'll need the following basic setup:
configuration.AddODataApiExplorer(
options => options.AdHocModelBuilder
.ModelConfigurations
.Add( new ImplicitModelBoundSettingsConvention() ) );Both platforms support adding, removing, or using conventions. The result of this configuration will show the $filter query option and indicate only the author and published properties can be used. If you prefer not to use attributes, the convention-based API can be used as well:
AddODataApiExplorer(
options =>
options.AdHocModelBuilder.DefaultConfiguration = (builder, version, prefix) =>
builder.ComplexType<Book>().Filter( "author", "published" ) ) ;The ad hoc EDM is only available during API exploration and is then discarded. It does not opt into any OData features.
ASP.NET Web API
ApiVersioningOptions.UnsupportedApiVersionStatusCodeallows specifying a custom HTTP status code- The default value is
400 - This property is ignored when versioning by URL segment and
404will always be used
- The default value is
- A Sunset Policy will always attempt be written when reporting API versions
ASP.NET Web API with OData
- Added support for ad hoc Model Bound Settings
- Add
ODataApiExplorerOptions.AdHocModelBuilderto add or configure conventions - Examples:
- Add
ASP.NET Core
- Migration from
IProblemDetailsFactorytoIProblemDetails - Minimal APIs:
- Add group support
- Support adding metadata to groups (e.g.
RouteGroupBuilder) - Add
ApiVersionSetBuilderFactoryas an injectable delegate - Add
VersionedEndpointRouteBuilderFactoryas an injectable delegate - Examples:
ApiVersioningOptions.UnsupportedApiVersionStatusCodeallows specifying a custom HTTP status code- The default value is
400 - This property is ignored when versioning by URL segment and
404will always be used
- The default value is
- A Sunset Policy will always attempt be written when reporting API versions
- Added the
IApiVersionMetadataCollationProviderservice
ASP.NET Core with OData
- Added support for ad hoc Model Bound Settings
- Add
ODataApiExplorerOptions.AdHocModelBuilderwhich is used in the same way asODataApiVersioningOptions.ModelBuilder - Examples:
- Add
Fixes
All Platforms
- Fix
StackOverflowExceptioninAdvertiseApiVersionsAttribute(#932)
ASP.NET Core
- Use
404over400when versioning only by URL segment (#911) - Do not explore unversioned endpoint more than once (#917)
IApiVersioningBuilder.AddMvcensures dependent services are registeredIApiVersioningBuilder.AddApiExplorerensures dependent services are registered- The
Codeextension inProblemDetailsis correctly written in JSON ascode - API versions are reported when an endpoint is unmatched (#876, #918)
- This is best effort, but restore behavior for unmatched endpoints prior to 6.0
- Honor the name provided in
NewVersionedApiwhen usedWithOpenApi(#920) - Refactor API version metadata collation (#922)
- Fix regression from custom group names (#923)
ASP.NET Core with OData
- Provide workaround for OData/AspNetCoreOData/#753
Breaking Changes
This is a summary of all breaking changes from the first previews to the final release.
ASP.NET Web API
DefaultApiVersionReporterconstructor addedISunsetPolicyManager
ASP.NET Core
- As previously announced, .NET Core 3.1 has been dropped and is end of life
ProblemDetailsimplementationIProblemDetailsFactoryhas been removed and is supplanted by the built-inIProblemDetailsServiceAddProblemDetails()must be called to addProblemDetails, which may result in a behavioral change
- Minimal APIs:
- Since RC 1:
MapApiGroupis nowNewVersionedApi(ASP.NET team recommendation)
- Since 6.0:
IVersionedEndpointConventionBuilderhas been removedVersionedEndpointConventionBuilderhas been removedDefaultApiVersionSetBuilderFactoryhas been replaced by theApiVersionSetBuilderFactorydelegateIVersionedEndpointConventionBuilder.WithApiVersionSetnow has the signatureTBuilder WithApiVersionSet<TBuilder>(TBuilder, ApiVersionSet) where TBuilder : notnull, IEndpointConventionBuilder
- Since RC 1:
- The following constructors were updated with
IEnumerable<IApiVersionMetadataCollationProvider>:ApiVersionMatcherPolicyDefaultApiVersionDescriptionProviderGroupedApiVersionDescriptionProvider
DefaultApiVersionReporterconstructor addedISunsetPolicyManagerApiExplorerOptionsFactory<T>was changed to:- Inherit from
OptionsFactory<T> - Remove
Setupsproperty - Remove
PostConfiguresproperty
- Inherit from
Contributors
Thanks you to all that contributed directly with code, filing issues, and in-depth discussions. In particular, special thanks to:
- @captainsafia, @halter73, @davidfowl for collaborating on Minimal API grouping
- @SamGuoMsft (#928)
- @marmoso (#932, #936)
- @gimlichael (#887)
- @bordecal (#876)
7.0.0 RC 1
The release candidate for .NET 7.0 is finally here. Barring any reported bugs, this should be the release. Big thanks to the early adopters that have tried things out and reported issues.
This release also contains fixes that were forward-integrated from
6.3and6.3.1.
Fixes
ASP.NET Core
- Honor the name provided in
MapApiGroupwhen usedWithOpenApi(#920) - Refactor API version metadata collation (#922)
- Fix regression from custom group names (#923)
AddProblemDetailsin example projects (now required to retain defaultProblemDetailsbehavior; new in .NET 7)
ASP.NET Core with OData
- Provide workaround for OData/ODataAspNetCore#753
Breaking Changes
There weren't any expected breaking changes, but there are some. #922 revealed that API versions were not collated as expected when building the route tree. Collation is split between Minimal APIs and traditional controllers. It is possible to have both. Previously, EndpointDataSource and IActionDescriptorCollectionProvider would have been supplied via DI. Since the ApiVersionMatcherPolicy now only depends on Microsoft.AspNetCore.Routing this was a problem.
6.3.1 subtly introduced IApiVersionMetadataCollationProvider which provides an adapter of sorts over EndpointDataSource and IActionDescriptorCollectionProvider respectively, but allows them to be independently added to DI as you add those features in. This ultimately requires changing the constructor signature of a few types:
ApiVersionMatcherPolicyDefaultApiVersionDescriptionProviderGroupedApiVersionDescriptionProvider
to add or replace their parameters with IEnumerable<IApiVersionMetadataCollationProvider>. In 6.3.1, some DI trickery was done with internal constructors to prevent breaking changes to the existing public surface area (though all the necessary extension pieces are public). Since 7.0 is still in preview, now is the time to apply this change.
Unless you are doing a lot of low-level customization or extensions, you probably won't notice these changes.
6.3.0
This is a minor update, which includes some routing improvements.
Features
All Platforms
ApiVersioningOptions.UnsupportedApiVersionStatusCodehas been added to indicate the status code used when an API version doesn't match- The default value is
400, which has been the de facto from the beginning - Any status code can be used, but
400,404, or501are generally the ones that make sense - Each response will continue to include
ProblemDetails, which is always the same; regardless of status code - When versioning exclusively by URL segment or the incoming request URL is determined to yield an API version route parameter, this option is ignored and the response will always be
404
- The default value is
- A Sunset Policy will always attempt be written when reporting API versions
- Previously, it was only written on success because success is required for API-specific policies
- A version-specific policy can be written even during failure since it is related to the version as a whole, regardless of API
Fixes
ASP.NET Core
IApiVersioningBuilder.AddMvcandIApiVersioningBuilder.AddApiExplorernow ensure dependent services are registeredAddApiExplorer, in particular, snagged a number of people that didn't realize they neededAddMvc
- The
ProblemDetails.Codeextension is now correctly written in JSON ascode - API versions are now reported when an endpoint is unmatched (#876, #918)
- This should restore the behavior for unmatched endpoints that existed prior to
6.0 - This is a best effort
- No erroneous scenarios have been found, but there could be edge cases
- The behavior is relying on the routing system to collate the metadata from endpoints that are already collated by name using their route templates
- Attempts to create contrived configurations that could yield incorrect results were unsuccessful (which is good)
- This should restore the behavior for unmatched endpoints that existed prior to
Breaking Changes
Restoring the unmatched endpoint behavior may break the expectations for those that have adopted 6.0. There's no good answer or time for this change to occur since this is an implementation detail that only manifests in behavior. Despite calling out the changes in the roadmap and release notes, several issues have been filed related to the change in 6.0. At the time, it didn't seem possible to retain that functionality, but it seems that - largely - it can be.
Ultimately, this change only affects APIs that are strictly concerned about whether the response will be 400 or 404 for client errors on unmatched versions. 400 will now revert to be the default case where you might have received 404. If it's important to you to retain the behaviors you've established while adopting 6.x, you can achieve that by setting:
ASP.NET Web API
(ApiVersioningOptions options) => options.UnsupportedApiVersionStatusCode = HttpStatusCode.NotFoundASP.NET Core
(ApiVersioningOptions options) => options.UnsupportedApiVersionStatusCode = 404Special note for .NET Core 3.1 users. There are edge cases where
404is returned instead of400. In reviewing the test cases, this was already a problem. It's unclear why that happens, but it appears to be a change or fix in the routing system in at least .NET 6.0 and above. This will be considered the expected behavior. It may be possible to change the behavior with middleware.
7.0.0 Preview 2
This is the second and likely final preview release for ASP.NET Core with .NET 7.0 support. No additional work is planned, but there are some breaking changes that can be tried, tested, and discussed before promoting to the official release.
Features
ASP.NET Core
- Added
MapApiGroup()as a shortcut forMapGroup( "" ).WithApiVersionSet() - Metadata can now be added to groups (e.g.
RouteGroupBuilder) - Added injectable
VersionedEndpointRouteBuilderFactorydelegate
In Preview 2, metadata can now be applied even more succinctly.
var builder = WebApplication.CreateBuilder( args );
builder.Services.AddApiVersioning();
var app = builder.Build();
var orders = app.MapApiGroup(); // ← api group with optional name
var v1 = orders.MapGroup( "/api/order" ).HasApiVersion( 1.0 ); // ← all endpoints in this group have 1.0
var v2 = orders.MapGroup( "/api/order" ).HasApiVersion( 2.0 ); // ← all endpoints in this group have 2.0
v1.MapGet( "/{id:int}", ( int id ) => new V1.Order() { Id = id, Customer = "John Doe" } );
v2.MapGet( "/{id:int}", ( int id ) => new V2.Order() { Id = id, Customer = "John Doe", Phone = "555-555-5555" } );
v2.MapDelete( "/{id:int}", ( int id ) => Results.NoContent() );All of the previous methods of configuring metadata are still supported. For more examples, refer to the:
Fixes
- Use
404over400when versioning only by URL segment (#911)
Breaking Changes
The following are breaking changes from Preview 1. If you haven't added any customizations, these should all be source code compatible.
- Add group metadata validation to avoid common developer mistakes
- Replace
IApiVersionSetBuilderFactoryinterface with injectableApiVersionSetBuilderFactorydelegate - Refactor
RouteHandlerBuidlerextensions intoIEndpointRouteBuilderExtensions- This allows adding metadata on an endpoint or route group
If you have additional input or feedback, please provide them in the discussion. This will likely be the last time to discuss it before the release becomes official.