After creating a asp.net core web api project, add Microsoft.AspNetCore.Mvc.Versioning from the nuget package
Now, modify your startup class to support versioning.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddApiVersioning();
}
After running the application, you will receive and error stating- An API version is required, but was not specified
Now, amend the AddApiVersioning method
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddApiVersioning(setupAction =>
{
setupAction.AssumeDefaultVersionWhenUnspecified = true;
setupAction.DefaultApiVersion = new ApiVersion(1, 0);
}
}
Default version to be set as 1.0, when the version is not specified.
Query string based versioning
I have created two controller, one as HelloWorldController and other one as HelloWorld2Controller but the route url of both are same.
[Route("api/[controller]")]
[ApiController]
[ApiVersion("1.0")]
[ApiVersion("1.1")]
public class HelloWorldController : ControllerBase
{
// GET: api/values
[HttpGet]
public string Get()
{
return "Hello world";
}
[HttpGet,MapToApiVersion("1.1")]
public string Get11()
{
return "Hello world v1.1";
}
}
I have set the route of HelloWorld2Controller to api/HelloWorld which is same as our HelloWorldController.
[Route("api/HelloWorld")]
[ApiController]
[ApiVersion("2.0")]
public class HelloWorld2Controller : ControllerBase
{
// GET: api/values
[HttpGet]
public string Get()
{
return "Hello World 2";
}
}
ApiVersion is used to represent the metadata that describes the api version associated with the service; whereas, MapToVersion is used to map the method to specific version of the api.
After running the application, call gets default to HelloWorldController’s Get method because we are setting the unspecified version to 1.0.
Now pass the api-version query string to the url, in my case its https://localhost:5001/api/Helloworld?api-version=2. Now it should point to version 2 of the api i.e. HelloWorld2Controller.
Assume, you want to change the name of query string from api-version to version. You can do it by setting ApiVersionReader to QueryStringApiVersionReader in the configure services method.
services.AddApiVersioning(setupAction =>
{
setupAction.AssumeDefaultVersionWhenUnspecified = true;
setupAction.DefaultApiVersion = new ApiVersion(1, 0);
setupAction.ApiVersionReader = new QueryStringApiVersionReader(new[] { "version" });
});
Url Based approach
Honestly, I’m not a big fan of url based approach due to explicitly versioning in the route attribute; moreover, we cannot use it with other versioning approaches.
[Route("api/v{version:apiversion}/HelloWorld")]
[ApiController]
[ApiVersion("2.0")]
public class HelloWorld2Controller : ControllerBase
{
}
[Route("api/v{version:apiversion}/[controller]")]
[ApiController]
[ApiVersion(“1.0")]
[ApiVersion("1.1")]
public class HelloWorldController : ControllerBase
{
}
Now run the application with url https://localhost:5001/api/v1.1/Helloworld
Header based versioning
Another approach of using versioning is by using header based versioning. Most of the developers advocates this approach because unlike the URL path param and query string approach, using request header doesn’t require fiddling around with the URLs on the client side. The downside to using request headers for versioning is that the versioning option is not explicitly visible to the client.
We can configure the header based versioning approach by setting the ApiVersionReader to HeaderApiVersionReader in the startup class.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
//services.AddApiVersioning();
services.AddApiVersioning(setupAction =>
{
setupAction.AssumeDefaultVersionWhenUnspecified = true;
setupAction.DefaultApiVersion = new ApiVersion(2, 0);
setupAction.ReportApiVersions = true;
//setupAction.ApiVersionReader = new HeaderApiVersionReader(new[] { "x-ver" });
});
}
Support multiple versioning
Supporting multiple versioning can provide flexibility and give options to the clients/developers to use versioning based on their choice. Multiple versioning can be used by using combine method of static class ApiVersionReader.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
//services.AddApiVersioning();
services.AddApiVersioning(setupAction =>
{
setupAction.AssumeDefaultVersionWhenUnspecified = true;
setupAction.DefaultApiVersion = new ApiVersion(2, 0);
setupAction.ApiVersionReader = ApiVersionReader.Combine(
new HeaderApiVersionReader(new[] { "x-ver" }),
new QueryStringApiVersionReader(new[] { "version" }));
});
}
Adversing the versioning
We can advertise the versioning of api’s by using ReportApiVersionsin the startup file.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
//services.AddApiVersioning();
services.AddApiVersioning(setupAction =>
{
setupAction.AssumeDefaultVersionWhenUnspecified = true;
setupAction.DefaultApiVersion = new ApiVersion(2, 0);
setupAction.ReportApiVersions = true;
setupAction.ApiVersionReader = ApiVersionReader.Combine(
new HeaderApiVersionReader(new[] { "x-ver" }),
new QueryStringApiVersionReader(new[] { "version" }));
});
}
Advertising the depreciated versions
Similarly like advertising, we can also advertise the depreciated version by setting depreciated property in ApiVersion attribute
[Route("api/[controller]")]
//[Route("api/v{version:apiversion}/[controller]")]
[ApiController]
[ApiVersion("1.0",Deprecated =true)]
[ApiVersion("1.1")]
public class HelloWorldController : ControllerBase
{
// GET: api/values
[HttpGet]
public string Get()
{
return "Hello world";
}
[HttpGet,MapToApiVersion("1.1")]
public string Get11()
{
return "Hello world v1.1";
}
}
I hope you like the article
Pingback: Versioning in asp.net core web api | Anup1252000's Blog