DEV Community 👩‍💻👨‍💻

Cover image for Versioning REST APIs in ASP.NET Core 6.0
Mohammed Ahmed Hussien
Mohammed Ahmed Hussien

Posted on

Versioning REST APIs in ASP.NET Core 6.0

In this post I will show you how to versioning you REST APIs, and I will explain to you when to versioning and what is the best approach to apply and implement this feature to your APIs.

First, let us take an example that can helep us and we can put our idea on top of it.
What are the APIs that I'm working on it. What kind of APIs that I build.
Is it whether services to show the case of the current Whether or banking services or APIs for internal uses by you organization?
If you develop or build APIs for internal uses by your organization DON'T versioning your APIs at all because you have to put in your mind that when you apply the versioning to your APIs, you increase the maintenances process for all versions of your APIs. And you actually build APIs for internal uses ( NOT for customers ), or by other way you have not external consumers to use your APIs.

Now let us assume taht we have built an whether services APIs for external uses by multiple consumers.

The signature of our Controller it would be like so:

    [Route("api/whether")]
    [ApiController]
    public class WhetherController : ControllerBase
    {
        [HttpGet("ShowCuurentStatus")]
        public string ShowCuurentStatus()
        {
            string result = "The current status  of the weather is: 35";
            return result;
        }
    }
Enter fullscreen mode Exit fullscreen mode

We have an endpoint that return the current status of the whether, and for demo purpose I returned a hard code result like so:

The current status of the weather is: 35
Enter fullscreen mode Exit fullscreen mode

Let us say we have more than one hundred (100) of consumers uses our APIs. And our endpoint works perfectly with them.And after long time we decide as the owner of this API to improve the result of the ShowCuurentStatus( ) Action Method. And we decide to include the Air Quality to the result depend on the current status of the weather. for instance, the result it will become like so:

The current status of the weather is: 35. The Air Quality is: Poor
Enter fullscreen mode Exit fullscreen mode

So, when we decide this change, we put in mind that, we need to apply this change without breaking the old result. How we can do that.
We can use the REST APIs visioning.
First, we have to install a NuGet packages:

Microsoft.AspNetCore.Mvc.Versioning
Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer
Enter fullscreen mode Exit fullscreen mode

What is the best approach to versioning you APIs?

To version your REST APIs you have more than one way to let your consumers to get the result from that endpoint depend on specific version.

*You can apply the versioning in query string parameter:
*

api/whether/ShowCuurentStatus?api-version=1.0
Enter fullscreen mode Exit fullscreen mode

Or by applying it in Request-Header

Or by Accept Header like so:

GET /api/whether/ShowCuurentStatus
Accept: application/json;api-version=1.0
Enter fullscreen mode Exit fullscreen mode

Also, you can apply the versioning by URL Path approach,

/api/v1/whether/ShowCuurentStatus
Enter fullscreen mode Exit fullscreen mode

The best approach to versioning you APIs is Request-Header, and the Request-Header like a meta data for your endpoint.

Now let us see how we can implement this on ASP.NET Core 6

In the program.cs class add these lines of code:

builder.Services.AddVersionedApiExplorer();
builder.Services.AddApiVersioning(config =>
{
    config.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(1, 0);
    config.AssumeDefaultVersionWhenUnspecified = true; // To Ignore 404 Error
    config.ReportApiVersions = true; // To show Which Version the Reauest Supported

    config.ApiVersionReader = new HeaderApiVersionReader("api-version");
});
Enter fullscreen mode Exit fullscreen mode

In the AddApiVersioning( ) method we configure it to accept by default the version 1.0 for all endpoints in our APIs, and this means that, if the consumer forgets to add the version of the endpoint to the header the result will directly match and return the version 1.0 for requested endpoint.

config.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(1, 0);
config.AssumeDefaultVersionWhenUnspecified = true;
Enter fullscreen mode Exit fullscreen mode

In the configuration of the AddApiVersioning( ) I enforce the Header to be the approach that it should be used by consumers when requesting my endpoints by applying this line of code:

config.ApiVersionReader = new HeaderApiVersionReader("api-version");
Enter fullscreen mode Exit fullscreen mode

The HeaderApiVersionReader objcet accept a string of array to name your version.

Letter I will show you how to combine more than one approach to get the result by different ways.

Let us jump to our WhetherController and apply the version two of the ShowCuurentStatus( ) Action Method:

 [HttpGet("ShowCuurentStatus")]
        [ApiVersion("1.0")]
        public string ShowCuurentStatus()
        {
            string result = "The current status of the weather is: 35";
            return result;
        }


        [HttpGet("ShowCuurentStatusV2")]
        [ApiVersion("2.0")]
        public string ShowCuurentStatusV2()
        {
            string result = "The current status of the weather is: 35  The Air Quality is: Poor";
            return result;
        }
Enter fullscreen mode Exit fullscreen mode

Now if you see the result of the version 2 of our method it returns a totally different result like so:

The current status of the weather is: 35. The Air Quality is: Poor
Enter fullscreen mode Exit fullscreen mode

Let us give it a try by running the application and test it by Postman

In the next image if you see, I make a request to the ShowCuurentStatus( ) endpoint without mentioning any version, and the result coming by default from version 1.0

Image description

Second let us make a request to version two of the ShowCuurentStatusV2( ) endpoint without applying the version of the endpoint in the header, and as you can see the result is 400 bad request

Image description

This error is coming here because I decorate the ShowCuurentStatusV2( ) Action Methos to accept version 2.0 only.
Let us add the version 2.0 to the header of the request, and now here we go:

Image description

Look carefully at the header of the request, I added a new header to request, and the name of that new header is:

api-version: 2
Enter fullscreen mode Exit fullscreen mode

The 2 here is the number of the version.

How to use multiple approach to accept the version of your endpoints

If I want to give my customers more than one way to apply the version of my endpoint to fetch the current status of the whether instead of the Request-Header only, I can do that by this way:

config.ApiVersionReader = ApiVersionReader.Combine(new HeaderApiVersionReader("api-version"),
                    new QueryStringApiVersionReader("api-V"));
Enter fullscreen mode Exit fullscreen mode

Here I combined two Api version reader to request the endpoints by using Combine method of the ApiVersionReader object.

Also, I can let my consumers to know when I decide to deprecate anyone of my endpoints and that by adding a second parameter to the ApiVersion attribute like so:

   [HttpGet("ShowCuurentStatus")]
        **[ApiVersion("1.0", Deprecated = true)]**
        public string ShowCuurentStatus()
        {
            string result = "The current status of the weather is: 35";
            return result;
        }
Enter fullscreen mode Exit fullscreen mode

And here the version one of the ShowCuurentStatus( ) Action Methos now is deprecated, if you give it a try you will see the result like so Look to next image:
Look at the api-deprecated-versions header at the end of the Headers tap of the result.

Image description

And that all I have to show you how to versioning your REST APIs in ASP.NET Core 6.
Thanks for reading.

Top comments (0)

DEV has this feature:

Settings

Go to your customization settings to nudge your home feed to show content more relevant to your developer experience level. 🛠