Versioning Your APIs

Introduction

If you’ve ever written an API and used it in a real-world application, you’ll discover the need to make changes to enhance your software.  The problem with changing an API is that once the interface has been published and used by other applications, the end points cannot be changed.  The best way to deal with this problem is to version your API so that a new version can have different end points.  This will give consumers time to change their code to match the new versions.

One sensitive consumer of API data is the mobile application.  If your company produces mobile applications, then you’ll need to deploy the new mobile app to the app store after the API has been deployed and is able to consume requests.  This creates a chicken or the egg problem of which should go first.  If the API is versioned, then it can be deployed in advance of the mobile application being available for download.  The new mobile app can use the new version of the API while the older mobile app versions still consume data from the previous versions of your API.  This can also avoid the problem of forcing your end users to upgrade ASAP.

Versioning Method 1

To version your API, there is an obvious but painful method of versioning.  This involves using a feature in IIS that allows multiple applications to be created under one website.  The process is to make a copy of the previous version of your API, then make changes to the code to represent the next version of the API.  Next, create a new application in IIS, say “V2.0”.  Then the path to your API will be something like “myapi.com/V2.0/controllername/method”.

Here is a list of the drawbacks to this method:

  • Deployment involves the creation of a new application every time a new version is deployed.
  • Any web.config file in the root directory of IIS would be inherited by all applications.
  • Keeping multiple versions of code becomes difficult to track.
  • Continuous integration becomes a headache because each version will need a deployment.

Several of these issues can be “fixed” by using creative merging/splitting of branches.  The inheritance problem can be fixed by leaving the root directory empty.  The creation of new applications under IIS can be automated through Powershell scripting (deployment process can check if app exists and create it if it doesn’t).

Versioning Method 2

A NuGet package that can be added to your solution to allow automatic versioning of controllers (here’s the package for .Net Core).  There is a great blog post on this package here.  I looked over the blog post and decided to do a little testing of my own.  I tested a sample Web API project for .Net Core to see if I could get the same results as duplicating projects and installing them as applications under IIS.  This is what I came up with for my version 2 controller:

using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;

namespace WebApiVersionedSample.Controllers
{
  [ApiVersion("2.0")]
  [ApiVersion("2.1")]
  [Route("v{version:apiVersion}/Values")]
    public class Values2Controller : Controller
    {
      [HttpGet, MapToApiVersion("2.0")]
      public IEnumerable GetV20()
      {
          return new string[] { "value1 - version 2", "value2 - version 2" };
      }

      [HttpGet, MapToApiVersion("2.1")]
      public IEnumerable GetV21()
      {
        return new string[] { "value1 - version 2.1", "value2 - version 2.1" };
      }

      [HttpGet("{id}", Name = "Get"), MapToApiVersion("2.0")]
      public string Get20(int id)
      {
          return $"id={id} version 2.0";
      }

      [HttpGet("{id}", Name = "Get"), MapToApiVersion("2.1")]
      public string Get21(int id)
      {
        return $"id={id} version 2.1";
      }
    }
}

As you can see, I set this up to accept version 2.0 or version 2.1, and I removed the “api” default path.  If you specify version 2.0, your consumer application can only see the GetV20 method for a get operation and your application will see Get20(int id) for any get method that passes and integer id variable.  In my sample code, I only printed the version number to show what code was executed when I selected a particular version.  Normally, you’ll call a business class from your method and that business class can be shared between two or more versions if the functionality didn’t change.  If, however, you have different logic in your business class between version 2.0 and version 2.1, then you’ll need to create another business class to call from your get method for version 2.1 and leave your version 2.0 untouched.

If you want to keep things simple, you can start a new version by creating new controllers for each endpoint and just add the version number to the end of the name.  Then you can change any one or more get, post, put or delete to conform to your new version.  Just be aware that this logic will need to continue into your business classes if necessary.

For my version 1.0 controller, as an example, I used the ValuesController object with an attribute at the top like so:

[ApiVersion("1.0")]
[Route("v{version:apiVersion}/Values")]
public class ValuesController : Controller

The “Route” shows how the version number precedes “/Values” controller name.  To access this in your browser hit F5 and change the version number.

Example: “http://localhost:64622/v1.0/values” or “http://localhost:64622/v2.1/values”.

To change your startup browser location, expand your properties and double-click on the launchSettings.json file:

Now you can change the application url and the launchUrl:

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:64622/",
      "sslPort": 0
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "v1.0/values",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "WebApiVersionedSample": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "v1.0/values",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "http://localhost:64623/"
    }
  }
}

This method of versioning your API has a few advantages over the previous method:

  • Deployments are set.  Add new version code and re-deploy.
  • No need to keep multiple copies of source code.
  • No IIS changes are necessary.

There are some potential pitfalls that developers will need to be aware of.  One complex situation is the possibility of a database change.  This can ripple down to a change to your Entity Framework POCOs, and possibly your context object.  If you are cautious and add non-breaking changes (like adding a new field), then you can change your database repository code without breaking your previous versions.  If you have breaking changes (such as a change to a stored procedure), then you’ll need to get creative and design it so both the old version and new version of your code still work together.

Where to Find the Code

You can download the sample code used in this blog post by going to my GitHub account (click here).

 

Get ASP.Net Core Web API Up and Running Quickly

Summary

I’m going to show you how to setup your environment so you can get results from an API using ASP.Net Core quickly.  I’ll discuss ways to troubleshoot issues and get logging and troubleshooting tools working quick.

ASP.Net Core Web API

Web API has been around for quite some time but there are a lot of changes that were made for .Net Core applications.  If you’re new to the world of developing APIs, you’ll want to get your troubleshooting tools up quickly.  As a seasoned API designer I usually focus on getting my tools and logging up and working first.  I know that I’m going to need these tools to troubleshoot and there is nothing worse than trying to install a logging system after writing a ton of code.

First, create a .Net API application using Visual Studio 2015 Community edition.  You can follow these steps:

Create a new .Net Core Web Application Project:

Next, you’ll see a screen where you can select the web application project type (select Web API):

A template project will be generated and you’ll have one Controller called ValuesController.  This is a sample REST interface that you can model other controllers from.  You’ll want to setup Visual Studio so you can run the project and use break-points.  You’ll have to change your IIS Express setting in the drop-down in your menu bar:

Select the name of the project that is below IIS Express (as shown in yellow above).  This will be the same as the name of your project when you created it.

Your next task is to create a consumer that will connect to your API, send data and receive results.  So you can create a standard .Net Console application.  This does not need to be fancy.  It’s just a throw-away application that you’ll use for testing purposes only.  You can use the same application to test your installed API just by changing the URL parameter.  Here’s how you do it:

Create a Console application:

Give it a name and hit the OK button.

Download this C# source file by clicking here.  You can create a cs file in your console application and paste this object into it (download my GitHub example by clicking here).  This web client is not necessary, you can use the plain web client object, but this client can handle cookies.  Just in case you decide you need to pass a cookie for one reason or another.

Next, you can setup a url at the top of your Program.cs source:

private static string url = "http://localhost:5000";

The default URL address is always this address, including the port number (the port does not rotate), unless you override it in the settings.  To change this information you can go into the project properties of your API project and select the Debug tab and change it.

Back to the Console application…

Create a static method for your first API consumer.  Name it GetValues to match the method you’ll call:

private static object GetValues()
{
	using (var webClient = new CookieAwareWebClient())
	{
		webClient.Headers["Accept-Encoding"] = "UTF-8";
		webClient.Headers["Content-Type"] = "application/json";

		var arr = webClient.DownloadData(url + "/api/values");
		return Encoding.ASCII.GetString(arr);
	}
}

Next, add a Console.Writeline() command and a Console.ReadKey() to your main:

static void Main(string[] args)
{
	Console.WriteLine(GetValues());

	Console.ReadKey();
}

Now switch to your API project and hit F-5.  When the blank window appears, then switch back to your consumer console application and hit F-5.  You should see something like this:

If all of this is working, you’re off to a good start.  You can put break-points into your API code and troubleshoot inputs and outputs.  You can write your remaining consumer methods to test each API that you wrote.  In this instance, there are a total of 5 APIs that you can connect to.

Logging

Your next task is to install some logging.  Why do you need logging?  Somewhere down the line you’re going to want to install this API on a production system.  Your system should not contain Visual Studio or any other tools that can be used by hackers or drain your resources when you don’t need them.  Logging is going to be your eyes on what is happening with your API.  No matter how much testing you perform on your PC, you’re not going to get a fully loaded API and there are going to be requests that are going to hit your API that you don’t expect.

Nicholas Blumhardt has an excellent article on adding a file logger to .Net Core.  Click here to read it.  You can follow his steps to insert your log code.  I changed the directory, but used the same code in the Configure method:

loggerFactory.AddFile("c:/logs/myapp-{Date}.txt");

I just ran the API project and a log file appeared:

This is easier than NLog (and NLog is easy).

Before you go live, you’ll probably want to tweak the limits of the logging so you don’t fill up your hard drive on a production machine.  One bot could make for a bad day.

Swashbuckle Swagger

The next thing you’re going to need is a help interface.  This interface is not just for help, it will give interface information to developers who wish to consume your APIs.  It can also be useful for troubleshooting when your system goes live.  Go to this website and follow the instructions on how to install and use Swagger.  Once you have it installed you’ll need to perform a publish to use the help.  Right-click on the project and select “Publish”.  Click on “Custom” and then give your publish profile a name.  Then click the “Publish” button.

Create an IIS website (open IIS, add a new website):

The Physical Path will link to your project directory in the bin/Release/PublishOutput folder.  You’ll need to make sure that your project has IUSR and IIS_IUSRS permissions (right-click on your project directory, select the security tab.  Then add full rights for IUSR and do the same for IIS_IUSRS).

You’ll need to add the url to your hosts file (c:\Windows\System32\drivers\etc folder)

127.0.0.1 MyDotNetWebApi.com

Next, you’ll need to adjust your application pool .Net Framework to “No Managed Code”.  Go back to IIS and select “Application Pools”:

Now if you point your browser to the URL that you created (MyDotNetWebApi.com in this example), then you might get this:

Epic fail!

OK, it’s not that bad.  Here’s how to troubleshoot this type of error.

Navigate to your PublishOutput folder and scroll all the way to the bottom.  Now edit the web.config file.  Change your stdoutLogFile to “c:\logs\stdout”

Refresh your browser to make it trigger the error again.  Then go to your c:\logs directory and check out the error log.  If you followed the instructions on installing Swagger like I did, you might have missed the fact that this line of code:

var pathToDoc = Configuration["Swagger:Path"];

Requires an entry in the appsettings.json file:

"Swagger": {
  "Path": "DotNetWebApi.xml"
}

Now go to your URL and add the following path:

www.yoururl.com/swagger/ui

Next, you might want to change the default path.  You can set the path to another path like “help”.  Just change this line of code:

app.UseSwaggerUi("help");

Now you can type in the following URL to see your API help page:

www.yoururl.com/help

To gain full use of Swagger, you’ll need to comment your APIs.  Just type three slashes and a summary comment block will appear.  This information is used by Swagger to form descriptions in the help interface.  Here’s an example of commented API code and the results:

Update NuGet Packages

.Net Core allows you to paste NuGet package information directly into the project.json file.  This is convenient because you don’t have to use the package manager to search for packages.  However, the versions of each package are being updated at a rapid rate, so even for the project template packages there are updates.  You can startup your Manage NuGet Packages window and click on the “Updates” tab.  Then update everything.

The downside of upgrading everything at once is that you’ll probably break something.  So be prepared to do some troubleshooting.  When I upgraded my sample code for this blog post I ran into a target framework runtime error.

Other Considerations

Before you deploy an API, be sure to understand what you need as a minimum requirement.  If your API is used by your own software and you expect to use some sort of security or authentication to keep out unwanted users, don’t deploy before you have added the security code to your API.  It’s always easier to test without using security, but this step is very important.

Also, you might want to provide an on/off setting to disable the API functions in your production environment for customers until you have fully tested your deployment.  Such a feature can be used in a canary release, where you allow some customers to use the new feature for a few days before releasing to all of your customers.  This will give you time to estimate load capabilities of your servers.

I also didn’t discuss IOC container usage, unit testing, database access, where to store your configuration files, etc.  Be sure and set a standard before you go live.

One last thing to consider is the deployment of an API.  You should create an empty API container and check it into your version control system.  Then create a deployment package to be able to deploy to each of your environments (Development, QA, stage, production, etc.).  The sooner you get your continuous integration working, the less work it will be to get your project completed and tested.  Manual deployment, even for a test system takes a lot of time.  Human error being the number one killer of deployment efficiency.

Where to Get the Code

As always, you can download the sample code at my GitHub account by clicking here (for the api code) and here (for the console consumer code).  Please hit the “Like” button at the end of this article if this subject was helpful!