How to Apply API Versioning in ASP.NET Core | Syncfusion Blogs
Detailed Blog page Skeleton loader
How to Apply API Versioning in ASP.NET Core

Once an API is deployed and starts to be used, it should be reliable and should not break for any reason. On the other hand, as requirements change, we need to update the API code base. This should be done without breaking the current API, so both the new and old versions of the API will be active. This is where API versioning approaches come into play, to handle different versions of APIs.

Assuming that you are familiar with ASP.NET Core API development, we are going to discuss the different ways to version APIs in ASP.NET Core.

Note: If you are not familiar with building ASP.NET Core APIs, please read this blog:  How to Build CRUD REST APIs with ASP.NET Core 3.1 and Entity Framework Core, Create JWT Tokens, and Secure APIs.

Prerequisites

Including versioning package and service

Microsoft provides an out-of-the-box library for ASP.NET Core API Versioning. We can install the versioning library by either using the NuGet package manager or using the following command in the package manager console:

Install-Package Microsoft.AspNetCore.Mvc.Versioning

Now, let’s add the versioning service in the application. To do this, go to the Startup class and register the versioning service.

Refer to the following code example.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddApiVersioning();
}

After including the service, your API will return the ApiVersionUnspecified error.

ApiVersionUnspecified errorThis happens because we didn’t specify the version, which is mandatory for calling an API. To resolve this, add the default version and configure the versioning service to consider the default version if none is provided.

Refer to the following code example.

services.AddApiVersioning(config => {
      config.DefaultApiVersion = new ApiVersion(1, 0);
      config.AssumeDefaultVersionWhenUnspecified = true;
});

Now the error will be resolved, and the default version will be considered for all API calls without version details.

Another useful configuration in the versioning service is to know the supported versions of an API in response to an API call. Refer to the following code example.

services.AddApiVersioning(config =>
{
    config.DefaultApiVersion = new ApiVersion(1, 0);
    config.AssumeDefaultVersionWhenUnspecified = true;
    config.ReportApiVersions = true;
});

By setting the ReportApiVersions configuration as true, we can see all the supported versions of the API in the response.

API's supported Versions

We have successfully included the versioning service in the application, so now let’s see some approaches to versioning.

Versioning approaches

We need to do the following two steps to implement API versioning:

  1. Map the controller or action with the supported version.
  2. Configure the versioning service to read and identify the version the client calls.

In the sections that follow, I explain the different approaches for both of these steps. Each approach has its pros and cons- you have to choose the one that suits you.

Versioning controller

We can specify which API versions can access a controller action by using the ApiVersion attribute in the controller. Then, only those specified versions will be allowed to access the controller actions. All other versions will return the UnsupportedApiVersion error.

Refer to the following code example.

[ApiVersion("1.0")]
[ApiVersion("2.0")]
[Route("[controller]")] 
[ApiController]
public class WeatherForecastController : ControllerBase
{
     private static readonly string[] Summaries = new[]
     {
         "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering"
      };

     [HttpGet]
     public IEnumerable<WeatherForecast> Get()
     {
         var rng = new Random();
         return Enumerable.Range(1, 5).Select(index => new WeatherForecast
         {
             Date = DateTime.Now.AddDays(index),
             TemperatureC = rng.Next(-20, 55),
             Summary = Summaries[rng.Next(Summaries.Length)]
         })
         .ToArray();
     }
}

Versioning action

We can also specify an action to support only the specified API versions with the MapToApiVersion attribute. Then, only those mapped API versions will have access to the API. Other versions will return the UnsupportedApiVersion error.

Refer to the following code example.

[HttpGet("{weather}")]
[MapToApiVersion("2.0")]
public WeatherForecast Get(string weather)
{
     var rng = new Random();
     return Enumerable.Range(1, 5).Select(index => new WeatherForecast
     {
          Date = DateTime.Now.AddDays(index),
          TemperatureC = rng.Next(-20, 55),
          Summary = Summaries[rng.Next(Summaries.Length)]
     })
      .ToList().Where(weatherList => weatherList.Summary == weather).FirstOrDefault();
}

Using a URI to pass the version details

A URI is an easy way to pass version details to the versioning service. We can use a query string or a URI absolute path to state the version in an API call.

Using the query string

By default, the versioning service reads the query string named api-version. If the query string is present in the URI, then the service will consider the query string value as the API version.

We can override this default behavior and configure a different query string to mention the API version. To do so, we need to configure the versioning service to look for a specific query string value in the URI to get the value of the calling API version.

Refer to the following code example.

services.AddApiVersioning(config =>
{
     config.DefaultApiVersion = new ApiVersion(1, 0);
     config.AssumeDefaultVersionWhenUnspecified = true;
     config.ReportApiVersions = true;
     config.ApiVersionReader = new QueryStringApiVersionReader("version");
});

Demo URI

https://localhost:44335/weatherforecast/cool?version=2.0

Using URI absolute path

By using the UrlSegmentApiVersionReader, we can use part of the URI segment to specify the API version. There are no inputs needed to use the segment reader while configuring the service. It will assume that the version will be present in the URI segment. To make this work, we have to configure the controller and the versioning service. Refer to the following code.

Startup service

services.AddApiVersioning(config =>
{
    config.DefaultApiVersion = new ApiVersion(1, 0);
    config.AssumeDefaultVersionWhenUnspecified = true;
    config.ReportApiVersions = true;
    config.ApiVersionReader = new UrlSegmentApiVersionReader();
});

Controller

[Route("v{version:apiVersion}/[controller]")]
[ApiVersion("1.0")]
[ApiVersion("2.0")]
[ApiController]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    [HttpGet] 
    public IEnumerable<WeatherForecast> Get()
    {
         var rng = new Random();
         return Enumerable.Range(1, 5).Select(index => new WeatherForecast
         {
             Date = DateTime.Now.AddDays(index),
             TemperatureC = rng.Next(-20, 55),
             Summary = Summaries[rng.Next(Summaries.Length)]
         })
         .ToArray();
     }
}

Demo URI

https://localhost:44335/v2/weatherforecast

https://localhost:44335/v1/weatherforecast 

Using headers to pass the version details

By configuring the versioning service, we can use the HTTP request header values to pass the API version. To get the version from the header, we need to configure the versioning service using the HeaderApiVersionReader and mention the header that we are going to use in our application.

Refer to the following code example.

Startup Service

services.AddApiVersioning(config =>
{
     config.DefaultApiVersion = new ApiVersion(1, 0);
     config.AssumeDefaultVersionWhenUnspecified = true;
     config.ReportApiVersions = true;
     config.ApiVersionReader = new HeaderApiVersionReader("x-version");
});

Demo URI and header

Using headers to pass the version details

Other versioning approaches

There are also other versioning approaches available in the ASP.NET Core API versioning library.

You can apply a specific version in the namespace and pass the version details in the content type. Also, you can write your own version reader for the versioning library and use that in the service. Writing your own reader will let you read the version by your app logic, so it will be completely based on your needs.

Conclusion

In this article, we have learned how to apply API versioning in ASP.NET Core and some of the common versioning approaches. I hope you found this article useful. Try out the methods listed in this blog post and leave your feedback in the comments section.

The Syncfusion ASP.NET Core UI controls library, powered by Essential JS 2, is the only suite you will ever need to build an application. It contains over 70 high-performance, lightweight, modular, and responsive UI controls in a single package. Use them to enhance your productivity!

For existing customers, the new version is available for download from the License and Downloads page. If you are not yet a Syncfusion customer, you can try our 30-day free trial to check out our available features. Also, we encourage you to try our samples on GitHub.

You can also contact us through our support forumDirect-Trac, or feedback portal. We are always happy to assist you!

Related blogs

Be the first to get updates

Dhinesh V

Meet the Author

Dhinesh V

Dhinesh Valarman has been a software engineer at Syncfusion Software since 2016. He is passionate about web technologies and is experienced in full-stack web application development.

Comments (3)

Nice Dhinesh,
Is Swagger (swashbuckle) have support of rednering the api as per it?

@ Kamran  

Hi Kamran,

Thanks for your feedback,

Yes, swagger has support for aspnet core API versioning. Please refer to the below documentation to enable and customize swagger to generate doc based on API version.

https://github.com/domaindrivendev/Swashbuckle.AspNetCore#generate-multiple-swagger-documents
https://github.com/domaindrivendev/Swashbuckle.AspNetCore#customize-the-action-selection-process

Thanks,
Dhinesh V.

Consider extending this post by adding Swagger.
API versioning is great, but we need an easy way to show that via UI and Swagger is great for that.

Comments are closed.