70

API Versioning in .NET Core

 5 years ago
source link: https://www.tuicool.com/articles/hit/n6Ffmq2
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

In this post, we will see how to use different options for versioning in .NET Core API projects. Versioning APIs is very important and it should be implemented in any API project. Let's see how to achieve this in .NET Core.

Prerequisites:

  • Visual Studio 2017 community edition, download here .
  • .NET Core 2.0 SDK from here (I have written a post to install SDK here ).

Create the API App Using a .NET Core 2.0 Template in VS 2017

Once you have all these installed, open your Visual Studio 2017 -> Create New Project -> Select Core Web application:

q6R7JzY.png!web Click on Ok and in the next window, select API as shown below: mmUz6ny.png!web Visual Studio will create a well-structured application for you.

Install the NuGet Package for API Versioning

The first step is to install the NuGet package for API Versioning.

Search with "Microsoft.AspNetCore.Mvc.Versioning" in the NuGet Package Manager and click on Install:

Azqueua.png!web

This NuGet package is a service API versioning library for Microsoft ASP.NET Core.

Changes in Startup Class

Once the NuGet package is installed, the next step is to add the API Versioning service in the ConfigureService   method as shown below:

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

Some points here:

  • The ReportApiVersions   flag is used to add the API versions in the response header as shown below:

FfeENjJ.png!web

  • The  AssumeDefaultVersionWhenUnspecified   flag is used to set the default version when the client has not specified any versions. Without this flag, the  UnsupportedApiVersion   exception will occur when the version is not specified by the client.
  • The  DefaultApiVersion  flag is used to set the default version count.

Create Multiple Versions of the Sample API

Once the API versioning service is added, the next step is to create multiple versions of our Values API.

For now, just keep the GET method and remove the rest of the methods and create version 2 of the same API, as shown below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace ApiVersioningSampleApp.Controllers {
 [ApiVersion("1.0")]
 [Route("api/Values")]
 public class ValuesV1Controller: Controller {
  // GET api/values
  [HttpGet]
  public IEnumerable < string > Get() {
   return new string[] {
    "Value1 from Version 1",
    "value2 from Version 1"
   };
  }
 }

 [ApiVersion("2.0")]
 [Route("api/Values")]
 public class ValuesV2Controller: Controller {
  // GET api/values
  [HttpGet]
  public IEnumerable < string > Get() {
   return new string[] {
    "value1 from Version 2",
    "value2 from Version 2"
   };
  }
 }
}

In the above code:

  • We have applied the attribute [ApiVersion("1.0")] for Version 1.
  • We have applied the attribute [ApiVersion("2.0")] for Version 2.
  • Also changed the GET value to understand which version is getting called.

Just run your application and you will see the Version 1 API is getting called because we did not specify any specific version; thus the default version (1.0 in our case) will be called:

QZjAbmr.png!web

There are some ways by which you can specify the version of the API, we'll discuss below.

Query String-Based Versioning

In this, you can specify the version of the API in the query string. For example, to call version 2 of the Values API, the below call should work:

/api/values?api-version=2.0   ENNbU3R.png!web

URL-Based Versioning

There are many people who do not like query based patterns, in which case we can implement URL-based versioning by changing the route as shown below:

[Route("api/{v:apiVersion}/Values")]  

In such a case, the below call will return the version 2 of the API:

/api/2.0/values  

yMfMfaa.png!web

This approach is more readable.

HTTP Header-Based Versioning

If you do not wish to change the URL of the API then you can send the version of API in the HTTP header.

To enable this, the version reader needs to be added to the ConfigureService   method as shown below:

o.ApiVersionReader = new HeaderApiVersionReader("x-api-version");

Once you enable this, the query string approach will not work. If you wish to enable both of them then just use the below code:

o.ApiVersionReader = new QueryStringOrHeaderApiVersionReader("x-api-version");

Once the API Version reader is enabled, you can specify the API version while calling this particular API. For example, I have given Version 1 while calling the API from Postman:

6RJvyyb.png!web

Some Useful Features

Deprecating the Versions

Sometimes we need to deprecate some of the versions of the API, but we do not wish to completely remove that particular version of the API.

In such cases, we can set the Deprecated flag to  true   for that API, as shown below:

[ApiVersion("1.0", Deprecated = true)]
[Route("api/Values")]
public class ValuesV1Controller: Controller {

 //// Code

}

It will not remove this version of the API, but it will return the list of deprecated versions in the header, api-deprecated-versions, as shown below:

EnIZba6.png!web

Assign the Versions Using Conventions

If you have lots of versions of the API, instead of putting the ApiVersion   attribute on all the controllers, we can assign the versions using a conventions property.

In our case, we can add the convention for both the versions as shown below:

o.Conventions.Controller<ValuesV1Controller>().HasApiVersion(new ApiVersion(1, 0)); 
o.Conventions.Controller<ValuesV2Controller>().HasApiVersion(new ApiVersion(2, 0));

Which means that we are not required to put [ApiVersion] attributes above the controller

API Version Neutral

There might be a case when we need to opt out the version for some specific APIs.

For example, Health checking APIs which are used for pinging. In such cases, we can opt out of this API by adding the attribute [ApiVersionNeutral]   as shown below:

[ApiVersionNeutral] 
[RoutePrefix( "api/[controller]" )] 
public class HealthCheckController : Controller {
////Code
}

Other Features to Consider:

  • Add MapToApiVersion   in the attribute if you wish to apply versioning only for specific action methods instead of the whole controller. For example:

[HttpGet, MapToApiVersion("2.0")]
public IEnumerable<string> Get() {
return new string[] { "value1 from Version 2", "value2 from Version 2" };
}
  • We can get the version information from the method  HttpContext.GetRequestedApiVersion(); , this is useful to check which version has been requested by the client.
  • Version Advertisement can be used by each service to advertise the supported and deprecated API versions it knows about. This is generally used when the service API versions are split across hosted applications.
  • We can allow clients to request a specific API version by media type. This option can be enabled by adding the below line in the API versioning options in the  ConfigureService   method:
options => options.ApiVersionReader = new MediaTypeApiVersionReader();

Hope this helps.

You can find my all .NET core posts here .


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK