Web API Versioning Using URI

Web API Versioning Using URI

In this article, I am going to discuss the Web API Versioning Using URI with an example. We will also discuss why we need versioning and the different options that are available to maintain versioning in ASP.NET Web API. So, at the end of this article, you will have a very good understanding of the following three things.

  1. Why Web API versioning is required?
  2. The Different options available in Web API to maintain the versioning.
  3. How to version a Web API using URI’s?

So let’s start the discussion

Why Web API versioning is required?

Once you develop and deploy a Web API service then different clients start consuming your Web API services.

As you know, day by day the business grows and once the business grows then the requirement may change, and once the requirement change then you may need to change the services as well, but the important thing you need to keep in mind is that you need to do the changes to the services in such a way that it should not break any existing client applications who already consuming your services.

This is the ideal scenario when the Web API versioning plays an important role. You need to keep the existing services as it is so that the existing client applications will not break, they worked as it is, and you need to develop a new version of the Web API service which will start consuming by the new client applications.

Different options available in Web API to maintain the versioning: 

The different options that are available to maintain versioning are as follows

  1. URI’s
  2. Query String
  3. Version Header
  4. Accept Header
  5. Media Type

How to version a Web API using URI’s?

In this article, I am going to discuss how to maintain versioning using URI’s. In our upcoming articles, I will discuss the rest of the versioning options one by one. So let us understand Web API Versioning using URI’s with an example. 

Create one empty ASP.NET Web API application with the name WebAPIVersioning. Once you create the application, let’s create the following EmployeeV1 model within the Models folder.

EmployeeV1.cs

namespace WebAPIVersioning.Models
{
    public class EmployeeV1
    {
        public int EmployeeID { get; set; }
        public string EmployeeName { get; set; }
    }
}

Version 1 of the above Employee class (EmployeeV1) has just 2 properties (EmployeeID & EmployeeName). 

Let’s create an empty Web API controller with the name EmployeesV1Controller within the Controllers folder which will be act as our version 1 controller. Once you create the controller, then please copy and paste the following code in it.

using System.Web.Http;
using WebAPIVersioning.Models;
using System.Collections.Generic;
using System.Linq;

namespace WebAPIVersioning.Controllers
{
    public class EmployeesV1Controller : ApiController
    {
        List<EmployeeV1> employees = new List<EmployeeV1>()
        {
            new EmployeeV1() { EmployeeID = 101, EmployeeName = "Anurag"},
            new EmployeeV1() { EmployeeID = 102, EmployeeName = "Priyanka"},
            new EmployeeV1() { EmployeeID = 103, EmployeeName = "Sambit"},
            new EmployeeV1() { EmployeeID = 104, EmployeeName = "Preety"},
        };

        public IEnumerable<EmployeeV1> Get()
        {
            return employees;
        }

        public EmployeeV1 Get(int id)
        {
            return employees.FirstOrDefault(s => s.EmployeeID == id);
        }
    }
}
Finally, modify the WebApiConfig.cs file as shown below.
using System.Web.Http;

namespace WebAPIVersioning
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "Version1",
                routeTemplate: "api/v1/employees/{id}",
                defaults: new { id = RouteParameter.Optional, controller = "EmployeesV1" }
            );
        }
    }
}

The clients of our Version1 Web API service can use the following URLs to get either the list of all employees or a specific employee by using the EmployeeID. At the moment, as part the employee objects, the service returns the Employee Id and Name properties. 

Web API Versioning Using URI

Implementing Web API Versioning using URI

Let’s say the business grows and as a result, the requirements have changed and now some of the new clients want the FirstName and LastName properties instead of the Name property. If we change the Version 1 Web API service, then it will break all the existing client applications. So there is a need to create the Version 2 of the Web SPI service which will be consumed by the new clients who wants the FirstName and LastName properties instead of the Name property.

If we do so, I mean if we create Version 2 of the Web API Service, then all the existing client application will not break, they work as it is as before and now they have 2 options. If they want they can make use of the version 2 Web API service by making changes to their application or else they still continue their work as it is without changing their application.

So, the important point to keep in mind is that with Web API Versioning we are not breaking any existing client application and at the same time we are also satisfying the new client requirements.

Following are the steps to create Version 2 of the Web API Service

Step1: Add a class file within the Models folder with the name it EmployeeV2 and then copy and paste the following code.

namespace WebAPIVersioning.Models
{
    public class EmployeeV2
    {
        public int EmployeeID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
}

Notice in EmployeeV2 class, instead of the Name property, we have the FirstName and LastName properties.

Step2: Add a new Web API 2 empty controller within the controllers folder with the name “EmployeesV2Controller” and then copy and paste the following code.

using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using WebAPIVersioning.Models;

namespace WebAPIVersioning.Controllers
{
    public class EmployeesV2Controller : ApiController
    {
        List<EmployeeV2> employees = new List<EmployeeV2>()
        {
            new EmployeeV2() { EmployeeID = 101, FirstName = "Anurag", LastName = "Mohanty"},
            new EmployeeV2() { EmployeeID = 102, FirstName = "Priyanka", LastName = "Dewangan"},
            new EmployeeV2() { EmployeeID = 103, FirstName = "Sambit", LastName = "Satapathy"},
            new EmployeeV2() { EmployeeID = 104, FirstName = "Preety", LastName = "Tiwary"},
        };

        public IEnumerable<EmployeeV2> Get()
        {
            return employees;
        }

        public EmployeeV2 Get(int id)
        {
            return employees.FirstOrDefault(s => s.EmployeeID == id);
        }
    }
}

Now, the “EmployeesV2Controller” returns “EmployV2” object that has the FirstName and LastName properties instead of the Name property. 

Step3: Modify the WebApiConfig.cs file as shown below.

using System.Web.Http;

namespace WebAPIVersioning
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "Version1",
                routeTemplate: "api/v1/employees/{id}",
                defaults: new { id = RouteParameter.Optional, controller = "EmployeesV1" }
            );

            config.Routes.MapHttpRoute(
                name: "Version2",
                routeTemplate: "api/v2/employees/{id}",
                defaults: new { id = RouteParameter.Optional, controller = "EmployeesV2" }
            );
        }
    }
}

As shown in the above WebApiConfig.cs file, now we have 2 routes. Notice the route template, for each of the routes. The
Version 1 clients use /api/v1/employees/{id} route while the
Version 2 clients use /api/v2/employees/{id} route 

That’s it. We have implemented the versioning in our Web API service. So, if we navigate to 
/api/v1/employees – We get the employee with Employee Id and Name properties as shown below

Web API Versioning Using URI

/api/v2/employees – We get employees with Employee Id, FirstName and LastName properties as shown below.

Web API Versioning Using URI

At the moment we are using the convention-based routing to implement the Web API versioning. We can also use the Attribute Routing instead of convention-based routing to implement the Web API versioning. What we need to do is, we need to use the [Route] attribute on methods in EmployeesV1Controller and EmployeesV2Controller as shown below.

EmployeesV1Controller
namespace WebAPIVersioning.Controllers
{
    public class EmployeesV1Controller : ApiController
    {
        List<EmployeeV1> employees = new List<EmployeeV1>()
        {
            new EmployeeV1() { EmployeeID = 101, EmployeeName = "Anurag"},
            new EmployeeV1() { EmployeeID = 102, EmployeeName = "Priyanka"},
            new EmployeeV1() { EmployeeID = 103, EmployeeName = "Sambit"},
            new EmployeeV1() { EmployeeID = 104, EmployeeName = "Preety"},
        };

        [Route("api/v1/employees")]
        public IEnumerable<EmployeeV1> Get()
        {
            return employees;
        }

        [Route("api/v1/employees/{id}")]
        public EmployeeV1 Get(int id)
        {
            return employees.FirstOrDefault(s => s.EmployeeID == id);
        }
    }
}
EmployeesV2Controller
namespace WebAPIVersioning.Controllers
{
    public class EmployeesV2Controller : ApiController
    {
        List<EmployeeV2> employees = new List<EmployeeV2>()
        {
            new EmployeeV2() { EmployeeID = 101, FirstName = "Anurag", LastName = "Mohanty"},
            new EmployeeV2() { EmployeeID = 102, FirstName = "Priyanka", LastName = "Dewangan"},
            new EmployeeV2() { EmployeeID = 103, FirstName = "Sambit", LastName = "Satapathy"},
            new EmployeeV2() { EmployeeID = 104, FirstName = "Preety", LastName = "Tiwary"},
        };
        [Route("api/v2/employees")]
        public IEnumerable<EmployeeV2> Get()
        {
            return employees;
        }

        [Route("api/v2/employees/{id}")]
        public EmployeeV2 Get(int id)
        {
            return employees.FirstOrDefault(s => s.EmployeeID == id);
        }
    }
}

As we are using the Attribute Routing, so we can safely comment the following 2 route templates in WebApiConfig.cs file

namespace WebAPIVersioning
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();

            //config.Routes.MapHttpRoute(
            //    name: "Version1",
            //    routeTemplate: "api/v1/employees/{id}",
            //    defaults: new { id = RouteParameter.Optional, controller = "EmployeesV1" }
            //);

            //config.Routes.MapHttpRoute(
            //    name: "Version2",
            //    routeTemplate: "api/v2/employees/{id}",
            //    defaults: new { id = RouteParameter.Optional, controller = "EmployeesV2" }
            //);
        }
    }
}

At this point, build the solution and test the application and it should work exactly the same way as before. In the next article, I will discuss Web API Versioning using Query String Parameter with an example.

SUMMARY

In this article, I try to explain how to implement Web API Versioning Using URI step by step with an example. I hope this article will help you with your need. I would like to have your feedback. Please post your feedback, question, or comments about this article.

Leave a Reply

Your email address will not be published. Required fields are marked *