Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

API Versioning in .NET Core

DZone's Guide to

API Versioning in .NET Core

.NET Core is a great framework for building out front- and backend applications. Read on to learn how to version the APIs your app's call using this framework.

· Web Dev Zone ·
Free Resource

Start coding something amazing with our library of open source Cloud code patterns. Content provided by IBM.

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:

Click on Ok and in the next window, select API as shown below: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:

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:

  • 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:

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 

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 

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:

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:

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.

Code something amazing with the IBM library of open source blockchain patterns. Content provided by IBM.

Topics:
web dev ,.net core ,api versioning ,tutorial ,web application development

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}