Versioning REST APIs in ASP.NET Core 6.0
Tags: dotnet, aspnetcore
Published: 2022-09-30 18:26:23

> 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 to build our idea based on it.
What are the APIs that I'm working on it. What are the kinds 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 your 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:

```C#
    [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;
        }
    }
```
We have an endpoint that return the current status of the whether, and for demo purpose I returned a hard code result like so:

 ```json
The current status of the weather is: 35
```

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:

 ```json
The current status of the weather is: 35. The Air Quality is: Poor
```
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:

```C#
Microsoft.AspNetCore.Mvc.Versioning
Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer
```

## 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
```
Or by applying it in **Request-Header**

Or by **Accept Header** like so:

```
GET /api/whether/ShowCuurentStatus
Accept: application/json;api-version=1.0
```
Also, you can apply the versioning by **URL Path** approach,

```
/api/v1/whether/ShowCuurentStatus
```

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:

```C#
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");
});
```

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. 

```C#
config.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(1, 0);
config.AssumeDefaultVersionWhenUnspecified = true;
```
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:

```C#
config.ApiVersionReader = new HeaderApiVersionReader("api-version");
```
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_:

```C#
 [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;
        }
```

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

 ```json
The current status of the weather is: 35. The Air Quality is: Poor
```
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rzszd2jjpmo1ncdc5t83.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/snuupvj8ba18wy6lj3b6.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/99lkhwxn0mux3biwj14q.png)

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
```

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:

```C#
config.ApiVersionReader = ApiVersionReader.Combine(new HeaderApiVersionReader("api-version"),
                    new QueryStringApiVersionReader("api-V"));
```

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:

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

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6b3atz444hs495jzye5v.png)

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