API Versioning in ASP.NET Core 3.1 – Best Practices

by | Updated on May 27, 2020 | Coding, .NET Core, API, ASP.NET Core

In this article, we will talk in detail about various API versioning techniques and How to implement API Versioning in ASP.NET Core 3.1 Applications. We will also go through a few of the industry’s recommended best practices. For the implementation, I will be using Visual Studio 2019 Community and ASP.NET Core 3.1 API Project Template.

What is API Versioning? (and why do you need it?)

Before deploying an API, there is a checklist of a few features that are considered vital. API versioning tops that list. It is highly crucial to anticipate changes that may be required once the API is published and a few clients are already using it. After publishing the API to a production server, we have to be careful with any future change. These changes should not break the existing Client Applications that are already using our API. It is also not a good idea to go on and change the API calls in each and every Client Application. This is how the concept of API versioning came about.

API versioning in ASP.NET Core is a technique by which different clients can get different implementations of the same Controller based on the request or the URL.So essentially, you build an API that has multiple versions that may behave differently. This is a great approach to accommodate the fact that requirements can change at any given time, and we do not have to compromise the integrity and availability of data for our already existing client applications.

Different Ways to Implement API versioning in ASP.NET Core

There are multiple ways to achieve API versioning in ASP.NET Core Applications. The commonly used approaches to version a WebApi are as follows:

  1. Query String based.
  2. URL based.
  3. HTTP Header based.

PS, Note that, apart from these 3 approaches, there are other ways like media type, accept-header, that can be quite complex on the longer run. From the practical point of view, I believe these 3 are the go-to approaches while versioning an API. Correct me if you have a different opinion about this.

Getting Started

For this implementation, let’s create an ASP.NET Core 3.1 API Project. It will be a simple application using the auto-generated WeatherController data.

Installing the Package

Microsoft has it’s own package to facilitate the process of versioning .NET Core APIs. This Package is called Microsoft.AspNetCore.Mvc.Versioning. Let’s install it using the package manager console.

Install-Package Microsoft.AspNetCore.Mvc.Versioning

Configuring the Application to Support Versioning

Navigate to the Startup class of the API Project and modify the Configure Services method to support versioning.

 public void ConfigureServices(IServiceCollection services)
        {
            #region Api Versioning
            // Add API Versioning to the Project
            services.AddApiVersioning(config =>
            {
                // Specify the default API Version as 1.0
                config.DefaultApiVersion = new ApiVersion(1, 0);
                // If the client hasn't specified the API version in the request, use the default API version number 
                config.AssumeDefaultVersionWhenUnspecified = true;
                // Advertise the API versions supported for the particular endpoint
                config.ReportApiVersions = true;
            });
            #endregion
            services.AddControllers();
        }

Folder Structure – Best Practice

Assuming that we can multiple versions of an API controller to serve different clients, I would like to have a cleaner folder-based separation of the actual controller based on the API version. In the demonstration, we have a DataController and 2 versions of the API. Here is the project folder structure for such an API.

api versioning 1

You can notice that I have separate folders based on the version of the API. Now that we have configured our application to support versioning and created the folder structure, let’s go forward to explore the 3 Best Approaches to implement API versioning in ASP.NET Core Application.

URL Based API Versioning.

Personally, this is my favorite approach and I implement this to nearly all of the APIs that I work on. It gives a clean separation between different versions. Versions are explicitly mentioned in the URL of the API endpoints. Here is how it would look like.

https://secureddata.com/api/v1/users
https://secureddata.com/api/v2/users

Implementation of URL Based API Versioning.

Here is the code for v1/DataController

namespace Versioning.WebApi.Controllers.v1
{
    [ApiVersion("1.0")]
    [Route("api/v{version:apiVersion}/[controller]")]
    [ApiController]
    public class DataController : ControllerBase
    {
        [HttpGet]
        public string Get()
        {
            return "data from api v1";
        }
    }
}

And here goes the v2/DataController.

namespace Versioning.WebApi.Controllers.v2
{
    [ApiVersion("2.0")]
    [Route("api/v{version:apiVersion}/[controller]")]
    [ApiController]
    public class DataController : ControllerBase
    {
        [HttpGet]
        public string Get()
        {
            return "data from api v2";
        }
    }
}

The most important lines are #3 and #4.
Line #3 defines the API version of the controller, whereas at #4 we define the path of the versioned controller.To make it more clear, let me run the API and show you some screenshots.

apidatafromv1
apidatafromv2

If you notice the difference in the addresses, we have already implemented the API versioning in ASP.NET Core 3.1 Application. As easy as that. URL based versioning is more conventional. as the clients and fellow developers are able to make out the version by seeing the URL itself. It is easier for developing APIs using this approach. We will move forward to Query Based Versioning on the same application.

Query Based API Versioning.

While the previous approach has the version within the URL, this technique allows you to pass the version of the API as a parameter in the URL, ie a query string. Here is how the URL may look like.
https://secureddata.com/api/users?api-version=1
https://secureddata.com/api/users?api-version=2

Implementation of Query Based API Versioning.

There is not much of a difference from the previous implementation in terms of the code.Just change the Line #4 of each of the controllers to [Route(“api/[controller]”)] instead of [Route(“api/v{version:apiVersion}/[controller]”)]. That’s it. Let’s run the API.

apidatafromv1query
apidatafromv2query

What happens when you pass a api version that does not exist? Like, say 999?

apiversionnotsupported

It throws an UnsupportedAPIVersion Exception saying that there is not Resource that matches API Version 999. Please see that is feature is available for any kind of versioning approach. By seeing the URLs, I guess it is self explanatory. Let’s proceed to our last approach.

HTTP Header Based API Versioning.

This approach is slightly different compared to the previous implementations and to test this, we need Postman or Swagger. I will use Postman in this demonstration to Test the Implementation. In the previous 2 techniques, we had the Version number either within the URL or passed it to the Application via a query string. Here we will pass the API version as HTTP Header in our request. This is exactly why it cannot be demonstrated using just a Browser.

Implementation of HTTP Header Based API Versioning

For this approach, we will have to modify our Startup class to support the Reading of API version from HTTP Header. Line #14 is the only addition needed to your ConfigureServices method.

public void ConfigureServices(IServiceCollection services)
        {
            #region Api Versioning
            // Add API Versioning to the Project
            services.AddApiVersioning(config =>
            {
                // Specify the default API Version as 1.0
                config.DefaultApiVersion = new ApiVersion(1, 0);
                // If the client hasn't specified the API version in the request, use the default API version number 
                config.AssumeDefaultVersionWhenUnspecified = true;
                // Advertise the API versions supported for the particular endpoint
                config.ReportApiVersions = true;
                //HTTP Header based versioning
                config.ApiVersionReader = new HeaderApiVersionReader("x-api-version");
            });
            #endregion
            services.AddControllers();
        }

Run the API and open up Postman. Paste the URL as below and add a Header Key , “x-api-version” with the required API Version. Here are the results.

apidatafromv1http
apidatafromv2http

This usage of versioning can be a bit challenging for Clients and may increase the lines of codes in the Client App.

Supporting Multiple API Versioning Schemes

Do you wonder if you could apply all these approaches to your API and let the client choose what he/she will use? Yes, Totally Possible. You can make your API support all the 3 Vesioning schemes out of the box by making these simple changes.

Firstly, add the route that supports URL based routing. Make sure each of your API Controllers has the following attribute.

[Route(“api/[controller]”)]
[Route(“api/v{version:apiVersion}/[controller]”)]

Next, We will have to combine the HTTP and Query based versioning. For this go back to the ConfigService of the Startup class and modify our last line of code in the ApIVersioning extension.

config.ApiVersionReader = ApiVersionReader.Combine(new HeaderApiVersionReader("x-api-version"), new QueryStringApiVersionReader("api-version"));

Cheers! Now you will be able to use all the 3 API versioning Schemes seamlessly.

Deprecating an API Version

Like, adverting the supported API versions of an endpoint, the versions that are going to be removed in the near future can also be advertised on the HTTP response Header. This can be done by modifying the Route Attribute of the specific version of the API Controller.

// DEPRECATING an API Version
    [ApiVersion("1.0", Deprecated = true)]

Summary

We have covered the Major 3 API versioning techniques to help build a cleaner and much scalable API in ASP.NET Core 3.1. You can find the link to the completed source code which supports all 3 API schemes in the next section. If you learned something new from this article, do not forget to share this blog post within your community to help out others as well. Leave your suggestions/experiences below in the comment section. Thanks!

Source Code

Here is the completed source code which supports all 3 API versioning schemes.
Follow me on Github as well 😉

Frequently Asked Questions

What are the different ways to implement versioning in a ASP.NET Core API?

The Major Schemes for API versioning in ASP.NET Core Applications are URL based, Query based and HTTP Header Request based schemes. Besides this, you have Media type and accept header schemes.

What is API Versioning?

API versioning in ASP.NET Core is a technique by which different clients can get different implementations of the same Controller based on the request or the URL.So essentially, you build an API that has multiple versions that may behave differently.

6 Comments

  1. Hassan Gulzar

    I really like your articles. I recently jumped on the .Net Core 3. How would this versioning work with Swagger? Hooking swagger and trying to run results in an error page where swagger fails to understand the API. I see other people doing some plumbing work to get versioning and swagger work but that is not clean code at all.

    Reply
  2. Cody Mumford

    Can you elaborate on the benefits of doing this versus just implementing a version control system with a build/publish cycle in branching?

    Reply
    • Mukesh Murugan

      Hi, isn’t this much easier and straight forward to implement compared to version controls. I am not very much aware of how you get all these benefits with version controls. This is quite easier to set up and much nicer on the organization part. We use this extensively at work, having the benefit to have multiple implementations for various clients and so on. It’s quite uncommon for me to hear about using gits for API versioning. Do let me know on what you think are the advantages.

      Thanks and regards.

      Reply
  3. Alireza

    Nice post
    Thank you

    Reply
  4. Syyed

    good, great, fantastic.

    Reply

Submit a Comment

Your email address will not be published. Required fields are marked *

Follow codewithmukesh

Support Me!

Buy me a coffeeBuy me a coffee

Pin It on Pinterest