DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Implementing CRUD Operations With NLP Using Microsoft.Extensions.AI
  • Zero to AI Hero, Part 3: Unleashing the Power of Agents in Semantic Kernel
  • Docker + .NET APIs: Simplifying Deployment and Scaling
  • Alexa Skill With .NET Core

Trending

  • Mastering Advanced Aggregations in Spark SQL
  • How the Go Runtime Preempts Goroutines for Efficient Concurrency
  • Streamlining Event Data in Event-Driven Ansible
  • What Is Plagiarism? How to Avoid It and Cite Sources
  1. DZone
  2. Data Engineering
  3. Databases
  4. API Versioning in .NET Core

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.

By 
Neel Bhatt user avatar
Neel Bhatt
·
Nov. 01, 18 · Tutorial
Likes (6)
Comment
Save
Tweet
Share
47.6K Views

Join the DZone community and get the full member experience.

Join For Free

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.

API .NET

Published at DZone with permission of Neel Bhatt, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Implementing CRUD Operations With NLP Using Microsoft.Extensions.AI
  • Zero to AI Hero, Part 3: Unleashing the Power of Agents in Semantic Kernel
  • Docker + .NET APIs: Simplifying Deployment and Scaling
  • Alexa Skill With .NET Core

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!