### Example API Version Formatting Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Version-Format Demonstrates how to format ApiVersion objects using various format specifiers and construct messages. ```csharp var apiVersion = new ApiVersion( 1, 0 ); Console.WriteLine( "Welcome to version " + apiVersion.ToString( "V" ) ); apiVersion = new ApiVersion( 1, 1, "Beta" ); var message = string.Format( "Welcome to version {0:VV}{0:' ('S')'}", apiVersion ); Console.WriteLine( message ); apiVersion = new ApiVersion( 2, 0 ); message = string.Format( "Welcome to version {0:VV}{0:' ('S')'}", apiVersion ); Console.WriteLine( message ); // Output: Welcome to version 1 // Output: Welcome to version 1.1 (Beta) // Output: Welcome to version 2.0 ``` -------------------------------- ### ASP.NET Core Controller Example Source: https://github.com/dotnet/aspnet-api-versioning/wiki/API-Version-Conventions A basic controller definition for ASP.NET Core. ```csharp [ApiController] [Route( "[controller]" )] public class MyController : ControllerBase { [HttpGet] public IActionResult Get() => Ok(); } ``` -------------------------------- ### ASP.NET Core Minimal APIs Versioning Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Versioning-via-the-Query-String This example demonstrates setting up versioned APIs using Minimal APIs in ASP.NET Core, mapping different versions to the same route. ```csharp var builder = WebApplication.CreateBuilder( args ); builder.Services.AddProblemDetails(); builder.Services.AddApiVersioning(); var app = builder.Build(); var hello = app.NewVersionedApi(); var v1 = hello.MapGroup( "/helloworld" ).HasApiVersion( 1.0 ); var v2 = hello.MapGroup( "/helloworld" ).HasApiVersion( 2.0 ); v1.MapGet( "/", () => "Hello world!" ); v2.MapGet( "/", () => "Hello world!" ); app.Run(); ``` -------------------------------- ### Controller Example for Backward Compatibility Source: https://context7.com/dotnet/aspnet-api-versioning/llms.txt Illustrates how to define controllers for default and versioned API endpoints. Unversioned clients will hit the `HelloWorldController`, while versioned clients can explicitly request `v2.0`. ```csharp // Pre-existing controller — no attributes needed; inferred as DefaultApiVersion [RoutePrefix("api/helloworld")] public class HelloWorldController : ApiController { [Route] public string Get() => "Hello world!"; } ``` ```csharp // New v2.0 controller [ApiVersion(2.0)] [RoutePrefix("api/helloworld")] public class HelloWorldV2Controller : ApiController { [Route] public string Get() => "Hello world v2!"; } ``` ```csharp // Unversioned clients continue to work: GET /api/helloworld → HelloWorldController // Versioned clients upgrade explicitly: GET /api/helloworld?api-version=2.0 ``` -------------------------------- ### HTTP request/response for OPTIONS discovery Source: https://context7.com/dotnet/aspnet-api-versioning/llms.txt An example of an HTTP OPTIONS request and its response, showing supported versions, sunset information, and OpenAPI links. ```http // HTTP request / response: // OPTIONS /api/myservice?api-version=1.0 HTTP/2 // Host: localhost // // HTTP/2 200 OK // Allow: GET, OPTIONS // Api-Supported-Versions: 1.0, 2.0, 3.0 // Sunset: Thu, 01 Apr 2025 00:00:00 GMT // Link: ; rel="sunset"; title="API Policy"; type="text/html" // Link: ; rel="openapi"; title="OpenAPI"; type="application/json" ``` -------------------------------- ### ASP.NET Core Controller with Multiple Versions Source: https://github.com/dotnet/aspnet-api-versioning/wiki/API-Version-Conventions Example of an ASP.NET Core controller supporting multiple API versions and routes. ```csharp [ApiController] [Route( "[controller]" )] public class MyController : ControllerBase { [HttpGet] public IActionResult Get() => Ok(); [HttpGet] public IActionResult GetV2() => Ok(); [HttpGet( "{id:int}" )] public IActionResult GetV2( int id ) => Ok(); } ``` -------------------------------- ### HTTP Response Example Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Versioning-by-Header Example HTTP response indicating a successful request with content. ```http HTTP/1.1 200 OK host: localhost content-type: text/plain content-length: 12 Hello world! ``` -------------------------------- ### HTTP Response with API Information Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Versioned-Clients An example HTTP response containing API versioning and sunset policy information. ```http HTTP/2 200 OK Api-Supported-Versions: 2.0 Api-Deprecated-Versions: 1.0 Sunset: Mon, 01 Jan 2024 00:00:00 GMT Link: ; rel="sunset"; type="text/html" Link: ; rel="openapi"; type="application/json"; api-version="1.0" ``` -------------------------------- ### HTTP Request for API Information Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Versioned-Clients An example of an OPTIONS HTTP request sent to retrieve API information. ```http OPTIONS /?api-version=1.0 HTTP/2 Host: my.api.com ``` -------------------------------- ### HTTP Request with Custom Header Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Versioning-by-Header Example HTTP GET request specifying API version 1.0 using the 'x-ms-version' header. ```http GET api/helloworld HTTP/1.1 host: localhost x-ms-version: 1.0 ``` -------------------------------- ### Versioning via URL Path Segment - Minimal APIs Source: https://context7.com/dotnet/aspnet-api-versioning/llms.txt Implement versioning for ASP.NET Core Minimal APIs using URL segment versioning. This example demonstrates grouping routes by version and mapping GET requests. ```csharp // ASP.NET Core Minimal APIs — URL segment with version group var app = builder.Build(); var people = app.NewVersionedApi(); var v1 = people.MapGroup("/people/v{version:apiVersion}").HasApiVersion(1.0); v1.MapGet("/", () => new[] { new Person() }); ``` -------------------------------- ### OpenAPI and Scalar Integration Setup Source: https://context7.com/dotnet/aspnet-api-versioning/llms.txt Configures ASP.NET Core to generate versioned OpenAPI documents and expose them via Scalar UI. Requires `Asp.Versioning.OpenApi` and `Asp.Versioning.Mvc.ApiExplorer`. ```csharp var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddProblemDetails(); builder.Services.AddApiVersioning(options => options.ReportApiVersions = true) .AddMvc() .AddApiExplorer(options => { // format: "v1", "v1.1", "v2-Beta" options.GroupNameFormat = "'v'VVV"; // replace {version:apiVersion} token in route templates options.SubstituteApiVersionInUrl = true; }) .AddOpenApi(options => options.Document.AddScalarTransformers()); var app = builder.Build(); if (app.Environment.IsDevelopment()) { // generates /openapi/v1.json, /openapi/v2.json, etc. app.MapOpenApi().WithDocumentPerVersion(); app.MapScalarApiReference(options => { var descriptions = app.DescribeApiVersions(); for (var i = 0; i < descriptions.Count; i++) { var description = descriptions[i]; var isDefault = i == descriptions.Count - 1; options.AddDocument(description.GroupName, description.GroupName, isDefault: isDefault); } }); } app.MapControllers(); app.Run(); ``` -------------------------------- ### ASP.NET Core Minimal API Versioning Configuration Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Versioning-via-the-URL-Path Sets up API versioning for ASP.NET Core Minimal APIs. This example demonstrates creating versioned API groups and mapping routes. ```csharp var builder = WebApplication.CreateBuilder( args ); builder.Services.AddProblemDetails(); builder.Services.AddApiVersioning(); var app = builder.Build(); var people = app.NewVersionedApi(); var v1 = people.MapGroup( "/people/v{version:apiVersion}" ).HasApiVersion( 1.0 ); v1.MapGet( "/", () => new[] { new Person() } ); app.Run(); ``` -------------------------------- ### HTTP GET Request with Ambiguous API Versions (Multiple Query Parameters) Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Error-Responses Shows an example of ambiguous API versioning where the 'api-version' parameter is provided multiple times in the query string. ```http GET /resource?api-version=1.0&api-version=2.0 HTTP/1.1 host: localhost ``` -------------------------------- ### HTTP Response with Supported API Versions Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Version-Discovery This is an example of an HTTP response that includes the `api-supported-versions` header, indicating the versions of the API that are currently available. ```http HTTP/1.1 200 OK allow: GET, POST, OPTIONS api-supported-versions: 1.0, 2.0, 3.0 ``` -------------------------------- ### Configure ASP.NET Core Minimal API with Versioning Source: https://github.com/dotnet/aspnet-api-versioning/wiki/New-Services-Quick-Start Sets up a minimal API application in ASP.NET Core, adding problem details and API versioning services. Maps a versioned GET endpoint for people. ```csharp var builder = WebApplication.CreateBuilder( args ); builder.Services.AddProblemDetails(); builder.Services.AddApiVersioning(); var app = builder.Build(); var people = app.NewVersionedApi(); people.MapGet( "/people", () => new[] { new Person() } ).HasApiVersion( 1.0 ); app.Run(); ``` -------------------------------- ### ASP.NET Core Application Setup with API Versioning and Swashbuckle Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Swashbuckle-Integration Sets up an ASP.NET Core application with API versioning, MVC, API Explorer, and Swashbuckle, including custom operation filters and Swagger UI configuration. ```csharp var builder = WebApplication.CreateBuilder( args ); builder.Services.AddControllers(); builder.Services.AddApiVersioning().AddMvc().AddApiExplorer(); builder.Services.AddTransient, ConfigureSwaggerOptions>(); builder.Services.AddSwaggerGen( options => options.OperationFilter() ); var app = builder.Build(); app.UseSwagger(); app.UseSwaggerUI( options => { foreach ( var description in app.DescribeApiVersions() ) { options.SwaggerEndpoint( $"/swagger/{description.GroupName}/swagger.json", description.GroupName ); } } ); app.MapControllers(); app.Run(); ``` -------------------------------- ### ASP.NET Core + OData Setup with API Versioning Source: https://context7.com/dotnet/aspnet-api-versioning/llms.txt Configures an ASP.NET Core application to support OData and API versioning. Ensures OData models are built automatically for each version. ```csharp var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers().AddOData(); builder.Services.AddProblemDetails(); builder.Services.AddApiVersioning() .AddOData(options => options.AddRouteComponents("api")); var app = builder.Build(); app.MapControllers(); app.Run(); ``` -------------------------------- ### ASP.NET Web API Controller Example Source: https://github.com/dotnet/aspnet-api-versioning/wiki/API-Version-Conventions A basic controller definition for ASP.NET Web API. ```csharp [RoutePrefix( "my" )] public class MyController : ApiController { [Route] public IHttpActionResult Get() => Ok(); } ``` -------------------------------- ### HTTP GET Request - Default Version Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Versioning-by-Media-Type Example HTTP GET request that will return the result from the current API version (2.0) due to default versioning. ```http GET api/helloworld HTTP/2 Host: localhost ``` -------------------------------- ### Configure API Versioning for ASP.NET Core OData Source: https://github.com/dotnet/aspnet-api-versioning/wiki/API-Documentation Sets up API versioning for OData controllers in ASP.NET Core. Ensure 'Asp.Versioning.OData.ApiExplorer' is installed. This configuration includes OData-specific routing and API explorer setup. ```csharp var builder = WebApplication.CreateBuilder( args ); builder.Services.AddControllers().AddOData(); builder.Services.AddProblemDetails(); builder.Services.AddApiVersioning() .AddOData( options => options.AddRouteComponents() ) .AddODataApiExplorer( // (optional) format the version as "'v'major[.minor][-status]" options => options.GroupNameFormat = "'v'VVV" ) .AddOpenApi( // (optional) apply Scalar-specific transformers options => options.Document.AddScalarTransformers() ); var app = builder.Build(); // configure OpenAPI and Scalar to use a document per version app.MapOpenApi().WithDocumentPerVersion(); app.MapScalarApiReference( options => { var descriptions = app.DescribeApiVersions(); for ( var i = 0; i < descriptions.Count; i++ ) { var description = descriptions[i]; var isDefault = i == descriptions.Count - 1; options.AddDocument( description.GroupName, description.GroupName, isDefault: isDefault ); } } ); app.MapControllers(); app.Run(); ``` -------------------------------- ### ASP.NET Web API Controller with Multiple Versions Source: https://github.com/dotnet/aspnet-api-versioning/wiki/API-Version-Conventions Example of an ASP.NET Web API controller supporting multiple API versions and routes. ```csharp [RoutePrefix( "my" )] public class MyController : ApiController { [Route] public IHttpActionResult Get() => Ok(); [Route] public IHttpActionResult GetV2() => Ok(); [Route( "{id:int}" )] public IHttpActionResult GetV2( int id ) => Ok(); } ``` -------------------------------- ### ASP.NET Core Minimal API Versioning Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Versioning-by-Header Maps a GET endpoint for 'HelloWorld' with version 1.0 using ASP.NET Core's minimal API routing. ```csharp var hello = app.NewVersionedApi(); hello.MapGet( "/helloworld", () => "Hello world!" ).HasApiVersion( 1.0 ); ``` -------------------------------- ### HTTP Request for Version Discovery Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Version-Policies An example HTTP OPTIONS request to discover supported and deprecated API versions, including sunset information. ```http OPTIONS /weather?api-version=1.0 HTTP/2 Host: localhost ``` -------------------------------- ### Configure API Versioning and Scalar for Minimal APIs Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Scalar-Integration Use this configuration for Minimal API projects. Ensure Asp.Versioning.OpenApi and Scalar.AspNetCore NuGet packages are installed. ```csharp builder.Services.AddApiVersioning() .AddApiExplorer() .AddOpenApi( options => options.Document.AddScalarTransformers() ); ``` -------------------------------- ### Configure API Versioning Services in ASP.NET Core Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Migration This example demonstrates the chained extension methods for configuring API Versioning services, including support for Minimal APIs, MVC, API Explorer, OData, and OData API Explorer. ```csharp var builder = WebApplication.CreateBuilder( args ); var services = builder.Services; services.AddApiVersioning() .AddMvc() .AddApiExplorer() .AddOData() .AddODataApiExplorer(); ``` -------------------------------- ### Configure API Versioning for ASP.NET Core Source: https://github.com/dotnet/aspnet-api-versioning/wiki/API-Documentation Sets up API versioning for controller-based or Minimal APIs in ASP.NET Core. Ensure 'Asp.Versioning.Mvc' is installed. For Minimal APIs, 'AddMvc()' is not required. ```csharp var builder = WebApplication.CreateBuilder( args ); // only required if you're using controllers builder.Services.AddControllers(); builder.Services.AddProblemDetails(); builder.Services.AddApiVersioning() .AddMvc() // ← bring in MVC (Core); not required for Minimal APIs .AddApiExplorer( // (optional) format the version as "'v'major[.minor][-status]" options => options.GroupNameFormat = "'v'VVV" ) .AddOpenApi( // (optional) apply Scalar-specific transformers options => options.Document.AddScalarTransformers() ); var app = builder.Build(); // configure OpenAPI and Scalar to use a document per version app.MapOpenApi().WithDocumentPerVersion(); app.MapScalarApiReference( options => { var descriptions = app.DescribeApiVersions(); for ( var i = 0; i < descriptions.Count; i++ ) { var description = descriptions[i]; var isDefault = i == descriptions.Count - 1; options.AddDocument( description.GroupName, description.GroupName, isDefault: isDefault ); } } ); // only required if you're using controllers app.MapControllers(); app.Run(); ``` -------------------------------- ### ASP.NET Core API Versioning with Swashbuckle Setup Source: https://context7.com/dotnet/aspnet-api-versioning/llms.txt This code sets up API versioning, MVC, and Swashbuckle integration in an ASP.NET Core application. It configures the Swagger UI to display endpoints for each API version. ```csharp // Wiring it all together var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddApiVersioning().AddMvc().AddApiExplorer( options => options.GroupNameFormat = "'v'VVV"); builder.Services.AddTransient, ConfigureSwaggerOptions>(); builder.Services.AddSwaggerGen(options => options.OperationFilter()); var app = builder.Build(); app.UseSwagger(); app.UseSwaggerUI(options => { foreach (var description in app.DescribeApiVersions()) { options.SwaggerEndpoint( $"/swagger/{description.GroupName}/swagger.json", description.GroupName); } }); app.MapControllers(); app.Run(); ``` -------------------------------- ### Configure API Versioning and Scalar for OData Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Scalar-Integration Use this configuration for OData projects. Ensure Asp.Versioning.OData.ApiExplorer and Scalar.AspNetCore NuGet packages are installed. ```csharp builder.Services.AddApiVersioning() .AddOData() .AddODataApiExplorer() .AddOpenApi( options => options.Document.AddScalarTransformers() ); ``` -------------------------------- ### Configure OData Batching with API Versioning Source: https://github.com/dotnet/aspnet-api-versioning/wiki/OData-Batching This snippet demonstrates the setup for OData batching in an ASP.NET Core application using API Versioning. It includes adding OData controllers, problem details, API versioning with OData route components, and enabling versioned OData batching. ```csharp var builder = WebApplication.CreateBuilder( args ); builder.Services.AddControllers().AddOData(); builder.Services.AddProblemDetails(); builder.Services.AddApiVersioning() .AddOData( options => options.AddRouteComponents( "api" ) ); var app = builder.Build(); app.UseVersionedODataBatching(); app.UseRouting() app.UseEndpoints( endpoints => endpoints.MapControllers() ); app.Run(); ``` -------------------------------- ### Minimal APIs OpenAPI and Scalar Integration Source: https://context7.com/dotnet/aspnet-api-versioning/llms.txt Configures API versioning, OpenAPI generation, and Scalar UI for Minimal APIs. Omit `.AddMvc()` when using this setup with Minimal APIs. ```csharp services.AddApiVersioning() .AddApiExplorer(options => options.GroupNameFormat = "'v'VVV") .AddOpenApi(options => options.Document.AddScalarTransformers()); ``` -------------------------------- ### Configure API Versioning and Scalar for Controllers Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Scalar-Integration Use this configuration for projects using controllers. Ensure Asp.Versioning.Mvc.ApiExplorer and Scalar.AspNetCore NuGet packages are installed. ```csharp builder.Services.AddApiVersioning() .AddMvc() .AddApiExplorer() .AddOpenApi( options => options.Document.AddScalarTransformers() ); ``` -------------------------------- ### HTTP GET Request with Unspecified API Version Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Error-Responses Demonstrates a client request missing the required API version. This typically results in a 400 Bad Request response. ```http GET /resource?api-version=1.0 HTTP/1.1 host: localhost api-version: 1.0 ``` -------------------------------- ### HTTP GET Request with Ambiguous API Versions (Header vs. Query) Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Error-Responses Illustrates a scenario where API versions are specified ambiguously between the query string and headers, leading to a 400 Bad Request. ```http GET /resource?api-version=1.0 HTTP/1.1 host: localhost api-version: 2.0 ``` -------------------------------- ### HTTP GET Request - Specific Version 1.0 Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Versioning-by-Media-Type Example HTTP GET request specifying API version 1.0 via the Accept header. ```http GET api/helloworld HTTP/2 Host: localhost Accept: text/plain;v=1.0 ``` -------------------------------- ### HTTP GET Request with Ambiguous API Versions (Multiple Headers) Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Error-Responses An example of ambiguous API versioning where the 'api-version' header is specified multiple times with different values. ```http GET /resource HTTP/1.1 host: localhost api-version: 1.0 api-version: 2.0 ``` -------------------------------- ### Construct and Format ApiVersion Objects Source: https://context7.com/dotnet/aspnet-api-versioning/llms.txt Demonstrates creating `ApiVersion` objects using different constructors for numeric, date-only, combined, and status-qualified versions. Shows how to use `IFormattable` with various format specifiers for custom output. ```csharp // Constructors var v1 = new ApiVersion(1, 0); // 1.0 var v1b = new ApiVersion(1, 1, "Beta"); // 1.1-Beta var vd = new ApiVersion(new DateOnly(2024, 5, 1)); // 2024-05-01 var vdc = new ApiVersion(new DateOnly(2024, 5, 1), 2, 0); // 2024-05-01.2.0 ``` ```csharp // Format specifiers var v = new ApiVersion(2, 1, "RC"); Console.WriteLine(v.ToString("VVV")); // 2.1-RC Console.WriteLine(v.ToString("VVVV")); // 2.1-RC (with padded minor → 2.1-RC) Console.WriteLine(v.ToString("V")); // 2 Console.WriteLine(v.ToString("VV")); // 2.1 Console.WriteLine(v.ToString("S")); // RC ``` ```csharp var dated = new ApiVersion(new DateOnly(2017, 5, 1), 1, 0, "RC"); Console.WriteLine(dated.ToString("F")); // 2017-05-01.1-RC Console.WriteLine(dated.ToString("FF")); // 2017-05-01.1.0-RC Console.WriteLine(dated.ToString("G")); // 2017-05-01 Console.WriteLine(dated.ToString("yyyy")); // 2017 Console.WriteLine(dated.ToString("MM")); // 05 ``` -------------------------------- ### HttpClient API Versioning with Multiple Clients and Writers Source: https://context7.com/dotnet/aspnet-api-versioning/llms.txt Demonstrates configuring multiple HttpClient instances with different API versioning strategies (query string and URL segment). ```csharp // Multiple clients with different writers services.AddHttpClient("SomeApi", client => client.BaseAddress = new Uri("https://some.api.com/")) .AddApiVersion(1.0, new QueryStringApiVersionWriter()); services.AddHttpClient("OtherApi", client => client.BaseAddress = new Uri("https://other.api.com/v{ver}/")) .AddApiVersion(2, new UrlSegmentApiVersionWriter("{ver}")); ``` -------------------------------- ### ASP.NET Web API OData Controller - Get All People Source: https://github.com/dotnet/aspnet-api-versioning/wiki/OData-Query-Options Handles GET requests for a collection of Person entities using OData query options. Includes validation settings for allowed query options, order by properties, and limits. ```csharp using Asp.Versioning; using Asp.Versioning.OData; using Microsoft.AspNet.OData; using Microsoft.AspNet.OData.Routing; using Microsoft.Web.Http; using System.Web.Http; using System.Web.Http.Description; using static Microsoft.AspNet.OData.Query.AllowedQueryOptions; using static System.Net.HttpStatusCode; using static System.DateTime; public class PeopleController : ODataController { [HttpGet] [ResponseType( typeof( ODataValue> ) )] public IHttpActionResult Get( ODataQueryOptions options ) { var validationSettings = new ODataValidationSettings() { AllowedQueryOptions = Select | OrderBy | Top | Skip | Count, AllowedOrderByProperties = { "firstName", "lastName" }, AllowedArithmeticOperators = AllowedArithmeticOperators.None, AllowedFunctions = AllowedFunctions.None, AllowedLogicalOperators = AllowedLogicalOperators.None, MaxOrderByNodeCount = 2, MaxTop = 100, }; try { options.Validate( validationSettings ); } catch ( ODataException ) { return BadRequest(); } var people = new[] { new Person() { Id = 1, FirstName = "John", LastName = "Doe", Email = "john.doe@somewhere.com", Phone = "555-987-1234", }, new Person() { Id = 2, FirstName = "Bob", LastName = "Smith", Email = "bob.smith@somewhere.com", Phone = "555-654-4321", }, new Person() { Id = 3, FirstName = "Jane", LastName = "Doe", Email = "jane.doe@somewhere.com", Phone = "555-789-3456", } }; return this.Success( options.ApplyTo( people.AsQueryable() ) ); } [HttpGet] [ResponseType( typeof( Person ) )] public IHttpActionResult Get( int key, ODataQueryOptions options ) { var people = new[] { new Person() { Id = key, FirstName = "John", LastName = "Doe", Email = "john.doe@somewhere.com", Phone = "555-987-1234", } }; var query = options.ApplyTo( people.AsQueryable(); return this.SuccessOrNotFound( query ).SingleOrDefault() ); } } ``` -------------------------------- ### Configure ASP.NET Core MVC with Versioning Source: https://github.com/dotnet/aspnet-api-versioning/wiki/New-Services-Quick-Start Sets up an ASP.NET Core application with MVC, problem details, and API versioning. Enables MVC integration for versioning. ```csharp var builder = WebApplication.CreateBuilder( args ); builder.Services.AddControllers(); builder.Services.AddProblemDetails(); builder.Services.AddApiVersioning().AddMvc(); var app = builder.Build(); app.MapControllers(); app.Run(); ``` -------------------------------- ### Configure ASP.NET Core with OData and Versioning Source: https://github.com/dotnet/aspnet-api-versioning/wiki/New-Services-Quick-Start Configures an ASP.NET Core application with controllers, OData, problem details, and API versioning. Sets up OData model configuration and route components. ```csharp var builder = WebApplication.CreateBuilder( args ); builder.Services.AddControllers().AddOData(); builder.Services.AddProblemDetails(); builder.Services.AddApiVersioning().AddOData( options => { options.ModelBuilder.DefaultModelConfiguration = ( builder, apiVersion, routePrefix ) => { builder.EntitySet( "People" ); }; options.AddRouteComponents(); } ); var app = builder.Build(); app.MapControllers(); app.Run(); ``` -------------------------------- ### Configure API Versioning in ASP.NET Core (Startup.cs) Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Configuring-Your-Application Configure API versioning for ASP.NET Core applications within the `ConfigureServices` method of `Startup.cs`. This adds MVC Core support, which is unnecessary for Minimal APIs. ```csharp public void ConfigureServices( IServiceCollection services ) { services.AddControllers(); services.AddProblemDetails(); services.AddApiVersioning() .AddMvc(); // ← brings in MVC Core; unnecessary for Minimal APIs // remaining setup omitted for brevity } ``` -------------------------------- ### People Controller - Get Person by Key Source: https://github.com/dotnet/aspnet-api-versioning/wiki/OData-Query-Options This endpoint retrieves a single person by their key, supporting OData query options. ```APIDOC ## GET /People({key}) ### Description Retrieves a single person by their unique identifier (key), with support for OData query options. ### Method GET ### Endpoint /People({key}) ### Parameters #### Path Parameters - **key** (integer) - Required - The unique identifier of the person. ### Query Parameters - **$select** (string) - Optional - Specifies the properties to return. - **$filter** (string) - Optional - Filters the results based on a condition. - **$orderby** (string) - Optional - Orders the results by one or more properties. - **$top** (integer) - Optional - Limits the number of results returned. - **$skip** (integer) - Optional - Skips a specified number of results. ### Request Example ```http GET /People(1)?$select=firstName ``` ### Response #### Success Response (200) - **Person** (object) - The Person object matching the key. #### Response Example ```json { "@odata.context": "http://localhost/$metadata#People/$entity", "Id": 1, "FirstName": "John" } ``` ``` -------------------------------- ### People Controller - Get All People Source: https://github.com/dotnet/aspnet-api-versioning/wiki/OData-Query-Options This endpoint retrieves a collection of people, supporting OData query options for filtering, sorting, and pagination. ```APIDOC ## GET /People ### Description Retrieves a collection of people with support for OData query options. ### Method GET ### Endpoint /People ### Query Parameters - **$select** (string) - Optional - Specifies the properties to return. - **$filter** (string) - Optional - Filters the results based on a condition. - **$orderby** (string) - Optional - Orders the results by one or more properties. - **$top** (integer) - Optional - Limits the number of results returned. - **$skip** (integer) - Optional - Skips a specified number of results. - **$count** (boolean) - Optional - Includes the total count of matching results. ### Request Example ```http GET /People?$select=firstName,lastName&$orderby=firstName desc&$top=10 ``` ### Response #### Success Response (200) - **value** (array) - An array of Person objects. #### Response Example ```json { "@odata.context": "http://localhost/$metadata#People", "value": [ { "Id": 1, "FirstName": "John", "LastName": "Doe" } ] } ``` ``` -------------------------------- ### Configure Basic Media Type Versioning Source: https://context7.com/dotnet/aspnet-api-versioning/llms.txt Enables API versioning by reading the version from the 'v' parameter in the 'Accept' or 'Content-Type' media type. Assumes a default version when none is specified and uses the current implementation for selection. ```csharp // Basic media type versioning (parameter name "v") services.AddApiVersioning(options => { options.ApiVersionReader = new MediaTypeApiVersionReader(); // Accept: application/json;v=1.0 options.AssumeDefaultVersionWhenUnspecified = true; options.ApiVersionSelector = new CurrentImplementationApiVersionSelector(options); }); ``` -------------------------------- ### Enabling OPTIONS support for API version discovery Source: https://context7.com/dotnet/aspnet-api-versioning/llms.txt Implement the `OPTIONS` method to allow clients to discover supported API versions and sunset information. This is useful for tooling and client integration. ```csharp // Service with OPTIONS support [ApiVersion(1.0)] [ApiVersion(2.0)] [ApiVersion(3.0)] [ApiController] [Route("api/[controller]")] public class MyServiceController : ControllerBase { [HttpGet] public IActionResult Get() => Ok(); // OPTIONS ~/api/myservice?api-version=[1.0|2.0|3.0] [HttpOptions] public IActionResult Options() { Response.Headers["Allow"] = "GET, OPTIONS"; return Ok(); } } ``` -------------------------------- ### Configure Media Type API Version Reader with Builder (Parameter and Include) Source: https://github.com/dotnet/aspnet-api-versioning/wiki/API-Version-Reader Configures the media type reader to use a specific parameter and include certain media types. ```csharp // Accept: application/json;v=2.0 AddApiVersioning( options => { var builder = new MediaTypeApiVersionReaderBuilder(); options.ApiVersionReader = builder.Parameter( "v" ) .Include( "application/json" ) .Build(); } ); ``` -------------------------------- ### HTTP Response with Version Sunset Policy Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Version-Policies An example HTTP response indicating supported, deprecated, and sunset API versions, along with policy links. ```http HTTP/2 200 OK Allow: GET, POST, OPTIONS Api-Supported-Versions: 1.0, 2.0, 3.0 Api-Deprecated-Versions: 0.9 Sunset: Thu, 01 Apr 2022 00:00:00 GMT Link: ; rel="sunset"; title="API Policy"; type="text/html" Link: ; rel="openapi"; title="OpenAPI"; type="application/json" ``` -------------------------------- ### ASP.NET Core MVC Version-Neutral Health Check Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Version-Neutral Apply the `[ApiVersionNeutral]` attribute to an `ApiController` to opt out of API versioning. This example uses a default route. ```csharp [ApiVersionNeutral] [ApiController] [Route( "api/[controller]/[action]" )] public class HealthController : ControllerBase { [HttpGet] public IActionResult Ping() => Ok(); } ``` -------------------------------- ### ASP.NET Web API Version-Neutral Health Check Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Version-Neutral Use the `[ApiVersionNeutral]` attribute on a controller to make it version-neutral. This example uses a default route prefix. ```csharp [ApiVersionNeutral] [RoutePrefix( "api/health" )] public class HealthController : ApiController { [HttpGet] [Route( "ping" )] public IHttpActionResult Ping() => Ok(); } ``` -------------------------------- ### OData Response for API Version 3.0 Source: https://github.com/dotnet/aspnet-api-versioning/wiki/OData-Model-Configurations Example JSON response for a Person entity in API version 3.0, including both Email and Phone properties. ```json { "id": 1, "firstName": "John", "lastName": "Doe", "email": "john.doe@somewhere.com", "phone": "555-555-5555" } ``` -------------------------------- ### OData Response for API Version 1.0 Source: https://github.com/dotnet/aspnet-api-versioning/wiki/OData-Model-Configurations Example JSON response for a Person entity in API version 1.0, showing only Id, FirstName, and LastName. ```json { "id": 1, "firstName": "John", "lastName": "Doe" } ``` -------------------------------- ### HTTP POST Request - Specific Version 2.0 Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Versioning-by-Media-Type Example HTTP POST request explicitly targeting API version 2.0 using the Content-Type header. ```http POST api/helloworld HTTP/2 Host: localhost Content-Type: text/plain;v=2.0 Content-Length: 12 Hello there! ``` -------------------------------- ### Controllers with Different Names in the Same .NET Namespace Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Controller-Conventions Illustrates how to handle multiple API versions of a controller within the same .NET namespace by using distinct controller names (e.g., HelloWorldController and HelloWorld2Controller). ```csharp namespace My.Services.Controllers { [ApiVersion( 1.0 )] [Route( "[controller]" )] public class HelloWorldController : ControllerBase { [HttpGet] public string Get() => "Hello world v1.0!"; } [ApiVersion( 2.0 )] [Route( "helloworld" )] public class HelloWorld2Controller : ControllerBase { [HttpGet] public string Get() => "Hello world v2.0!"; } } ``` -------------------------------- ### ASP.NET Core Minimal APIs Version-Neutral Health Check Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Version-Neutral Use the `.IsApiVersionNeutral()` extension method on a route to make it version-neutral. This example uses a default route. ```csharp var hello = app.NewVersionedApi(); hello.MapGet( "/api/health/ping", () => Results.Ok() ).IsApiVersionNeutral(); ``` -------------------------------- ### OData Response for API Version 2.0 Source: https://github.com/dotnet/aspnet-api-versioning/wiki/OData-Model-Configurations Example JSON response for a Person entity in API version 2.0, including the Email property introduced in this version. ```json { "id": 1, "firstName": "John", "lastName": "Doe", "email": "john.doe@somewhere.com" } ``` -------------------------------- ### Configure Default API Versioning for ASP.NET Core Minimal APIs Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Existing-Services-Quick-Start Sets up API versioning for Minimal APIs in ASP.NET Core, allowing calls without specifying a version, defaulting to 1.0. Groups routes by API version for clear organization. ```csharp var builder = WebApplication.CreateBuilder( args ); builder.Services.AddProblemDetails(); // allow a client to call you without specifying an api version // since we haven't configured it otherwise, the assumed api version will be 1.0 builder.Services.AddApiVersioning( options => options.AssumeDefaultVersionWhenUnspecified = true ); var app = builder.Build(); var people = app.NewVersionedApi(); var v1 = people.MapGroup( "/people" ).HasApiVersion( 1.0 ); var v2 = people.MapGroup( "/people" ).HasApiVersion( 2.0 ); v1.MapGet( "/", () => new[] { new Person() } ); v2.MapGet( "/", () => new[] { new Person() } ); app.Run(); ``` -------------------------------- ### Configure ASP.NET Web API OData Versioning and OpenAPI Source: https://github.com/dotnet/aspnet-api-versioning/wiki/API-Documentation Integrate API versioning into OData controllers and configure Swagger documentation. This includes setting up the OData model builder and API explorer. ```csharp configuration.AddApiVersioning(); var modelBuilder = new VersionedODataModelBuilder( configuration ) { ModelConfigurations = { new MyModelConfiguration() } }; configuration.MapVersionedODataRoutes( "odata", "api", modelBuilder ); // (optional) format the version as "'v'major[.minor][-status]" var apiExplorer = configuration.AddODataApiExplorer( o => o.GroupNameFormat = "'v'VVV" ); configuration.EnableSwagger( "{apiVersion}/swagger", swagger => { swagger.MultipleApiVersions( ( apiDescription, version ) => apiDescription.GetGroupName() == version, info => { foreach ( var group in apiExplorer.ApiDescriptions ) { info.Version( group.Name, $"Example API {group.ApiVersion}" ); } } ); } ) .EnableSwaggerUi( swagger => swagger.EnableDiscoveryUrlSelector() ); ``` -------------------------------- ### Configure Vendor Media Type Versioning Source: https://context7.com/dotnet/aspnet-api-versioning/llms.txt Sets up API versioning to read the version from a vendor-specific media type template, such as 'application/vnd.my.company.v{version}+json'. ```csharp // Vendor media type template (e.g., application/vnd.company.v1+json) services.AddApiVersioning(options => { var builder = new MediaTypeApiVersionReaderBuilder(); options.ApiVersionReader = builder .Template("application/vnd.my.company.v{version}+json") .Build(); }); ``` -------------------------------- ### ASP.NET Core OData API Versioning Controllers Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Existing-Services-Quick-Start Define API controllers for OData with different versions. This example shows two versions of a People controller for OData. ```csharp [ApiVersion( 1.0 )] // ← this attribute isn't required, but it's easier to understand public class PeopleController : ODataController { // GET ~/people // GET ~/people?api-version=1.0 [EnableQuery] public IActionResult Get() => Ok( new[] { new Person() } ); } [ApiVersion( 2.0 )] [ControllerName( "People" )] public class People2Controller : ODataController { // GET ~/people?api-version=2.0 [EnableQuery] public IActionResult Get() => Ok( new[] { new Person() } ); } ``` -------------------------------- ### ASP.NET Web API Controllers for OData Protocol Transitions Source: https://github.com/dotnet/aspnet-api-versioning/wiki/OData-Protocol-Transitions Demonstrates controller implementations for different API versions, including transitions to and from the OData protocol. Note the use of [ControllerName] and [ODataRoutePrefix] attributes for OData controllers. ```csharp using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.OData.Routing.Controllers; [ApiVersion( 1.0 )] public class OrdersController : ApiController { public IHttpActionResult Get() => Ok(); } [ApiVersion( 2.0 )] [ControllerName( "Orders" )] [ODataRoutePrefix( "Orders" )] public class Orders2Controller : ODataController { [ODataRoute] public IHttpActionResult Get() => Ok(); } [ApiVersion( 3.0 )] [ControllerName( "Orders" )] public class Orders3Controller : ApiController { public IHttpActionResult Get() => Ok(); } ``` -------------------------------- ### Configure Media Type API Version Reader with Builder (Template) Source: https://github.com/dotnet/aspnet-api-versioning/wiki/API-Version-Reader Configures the media type reader to match API versions using a template in the media type. ```csharp // Accept: application/vnd.my.company.v1+json AddApiVersioning( options => { var builder = new MediaTypeApiVersionReaderBuilder(); options.ApiVersionReader = builder.Template( "application/vnd.my.company.v{version}+json" ) .Build(); } ); ``` -------------------------------- ### ASP.NET Core MVC API Versioning Controllers Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Existing-Services-Quick-Start Define API controllers with different versions using the ApiVersion attribute. This example shows two versions of a People controller. ```csharp [ApiVersion( 1.0 )] // ← this attribute isn't required, but it's easier to understand [ApiController] [Route( "[controller]" )] public class PeopleController : ControllerBase { [HttpGet] public IActionResult Get() => Ok( new[] { new Person() } ); } [ApiVersion( 2.0 )] [ApiController] [Route( "People" )] public class People2Controller : ControllerBase { [HttpGet] public IActionResult Get() => Ok( new[] { new Person() } ); } ``` -------------------------------- ### Configure Custom Media Type Versioning with Template Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Versioning-by-Media-Type Use MediaTypeApiVersionReaderBuilder with a template to match custom media types like 'application/vnd.my.company.1+json'. The version is extracted from the template parameter. ```csharp .AddApiVersioning( options => { var builder = new MediaTypeApiVersionReaderBuilder(); options.ApiVersionReader = builder.Template( "application/vnd.my.company.{version}+json" ) .Build(); } ); ``` -------------------------------- ### Versioning via Query String Parameter - Controllers Source: https://context7.com/dotnet/aspnet-api-versioning/llms.txt Implement API versioning using query string parameters. Controllers do not require URL changes, and versioning is handled by the configured ApiVersionReader. ```csharp // Controller (no URL change required) [ApiVersion(1.0)] [ApiController] [Route("api/[controller]")] public class HelloWorldController : ControllerBase { [HttpGet] public string Get() => "Hello world v1!"; } [ApiVersion(2.0)] [ApiController] [Route("api/helloworld")] public class HelloWorld2Controller : ControllerBase { [HttpGet] public string Get() => "Hello world v2!"; } ``` -------------------------------- ### Advertise API Versions with Minimal APIs Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Version-Advertisement Advertise API versions for Minimal APIs using `.AdvertisesApiVersion()` to ensure correct collation with controllers. This requires `ApiVersioningOptions.ReportApiVersions` to be enabled. ```csharp var hello = app.NewVersionedApi(); hello.MapGet( "/api/helloworld", () => "Hello world v2.0!" ) .HasApiVersion( 2.0 ) .AdvertisesApiVersion( 1.0 ); ``` -------------------------------- ### Receive API Version in Minimal APIs Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Accessing-Version-Information Demonstrates how to receive the incoming API version directly as a parameter in a `RequestDelegate` for ASP.NET Core Minimal APIs. Ensure `EnableApiVersionBinding` is called during service configuration. ```csharp var builder = WebApplication.CreateBuilder( args ); builder.Services.AddProblemDetails(); builder.Services.AddApiVersioning().EnableApiVersionBinding(); var app = builder.Build(); var api = app.NewVersionedApi(); api.MapGet( "/", ( ApiVersion version ) => Results.Ok() ) .HasApiVersion( 1.0 ) .HasApiVersion( 2.0 ); app.Run(); ``` -------------------------------- ### Get Requested API Version in ASP.NET Web API Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Accessing-Version-Information Retrieves the client-requested API version using the `GetRequestedApiVersion` extension method on the `HttpRequest` object. This is available in ASP.NET Web API. ```csharp using Microsoft.AspNetCore.Mvc; using Asp.Versioning; [ApiVersion( 1.0 )] [ApiVersion( 2.0 )] public class MyController : ApiController { public IHttpActionResult Get() { var apiVersion = Request.GetRequestedApiVersion(); return Ok(); } // supported in 3.0+ public IHttpActionResult Get( int id, ApiVersion apiVersion ) => Ok(); } ``` -------------------------------- ### ASP.NET Core OData API Versioning Configuration Source: https://github.com/dotnet/aspnet-api-versioning/wiki/Existing-Services-Quick-Start Configure API versioning for OData in the ASP.NET Core application builder. This example sets up OData versioning and assumes version 1.0 when unspecified. ```csharp var builder = WebApplication.CreateBuilder( args ); builder.Services.AddControllers().AddOData(); builder.Services.AddProblemDetails(); // allow a client to call you without specifying an api version // since we haven't configured it otherwise, the assumed api version will be 1.0 builder.Services .AddApiVersioning( options => options.AssumeDefaultVersionWhenUnspecified = true ) .AddOData( options => { options.ModelBuilder.DefaultModelConfiguration = ( builder, apiVersion, routePrefix ) => { builder.EntitySet( "People" ); }; options.AddRouteComponents(); } ); var app = builder.Build(); app.MapController(); app.Run(); ``` -------------------------------- ### OData Controller with Query Options Source: https://github.com/dotnet/aspnet-api-versioning/wiki/OData-Query-Options Demonstrates an ASP.NET Core OData controller that applies OData query options imperatively. It includes validation settings for allowed query options, properties, and limits. ```csharp using Asp.Versioning; using Asp.Versioning.OData; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.OData.Query; using Microsoft.AspNetCore.OData.Results; using Microsoft.AspNetCore.OData.Routing.Controllers; using static Microsoft.AspNetCore.Http.StatusCodes; using static Microsoft.AspNetCore.OData.Query.AllowedQueryOptions; using static System.DateTime; public class PeopleController : ODataController { [Produces( "application/json" )] [ProducesResponseType( typeof( ODataValue> ), Status200OK )] public IActionResult Get( ODataQueryOptions options ) { var validationSettings = new ODataValidationSettings() { AllowedQueryOptions = Select | OrderBy | Top | Skip | Count, AllowedOrderByProperties = { "firstName", "lastName" }, AllowedArithmeticOperators = AllowedArithmeticOperators.None, AllowedFunctions = AllowedFunctions.None, AllowedLogicalOperators = AllowedLogicalOperators.None, MaxOrderByNodeCount = 2, MaxTop = 100, }; try { options.Validate( validationSettings ); } catch ( ODataException ) { return BadRequest(); } var people = new[] { new Person() { Id = 1, FirstName = "John", LastName = "Doe", Email = "john.doe@somewhere.com", Phone = "555-987-1234", }, new Person() { Id = 2, FirstName = "Bob", LastName = "Smith", Email = "bob.smith@somewhere.com", Phone = "555-654-4321", }, new Person() { Id = 3, FirstName = "Jane", LastName = "Doe", Email = "jane.doe@somewhere.com", Phone = "555-789-3456", } }; return Ok( options.ApplyTo( people.AsQueryable() ) ); } [Produces( "application/json" )] [ProducesResponseType( typeof( Person ), Status200OK )] [ProducesResponseType( Status404NotFound )] public IActionResult Get( int key, ODataQueryOptions options ) { var people = new[] { new Person() { Id = key, FirstName = "John", LastName = "Doe", Email = "john.doe@somewhere.com", Phone = "555-987-1234", } }; var person = options.ApplyTo( people.AsQueryable() ).SingleOrDefault(); if ( person == null ) { return NotFound(); } return Ok( person ); } } ```