Skip to content

How to Version Your Service

Chris Martinez edited this page Jun 12, 2017 · 11 revisions

REST services are implemented in ASP.NET as a controller. To version your service, you simply need to decorate your controller with the appropriate API version information.

How It Works

API versioning does not have a direct influence on routing. The way that you create and define routes remains unchanged. The key difference is that routes may now overlap depending on whether you are using convention-based routing, attribute-based routing, or both. In the case of attribute routing, multiple controllers will define the same route. The default services in each flavor of ASP.NET assumes a one-to-one mapping between routes and controllers and, therefore, considers duplicate routes to be ambiguous. The API versioning services replace the default implementations and allow controllers to also be disambiguated by API version. Although multiple routes may match a request, they are expected to be distinguishable by API version. If the routes cannot be disambiguated, this is likely a developer mistake and the behavior is the same as the default implementation.

Supported Routing Methods

The following table outlines the various supported routing methods:

Routing Method Supported
Attribute-based routing Yes
Convention-based routing Yes
Attribute and convention-based routing (mixed) Yes*
* Due to limitations in the routing infrastructure in ASP.NET Web API, API versioning is not guaranteed to work for controllers that define both attribute and convention-based routes for the same route

Convention-based routing is normally defined by inferring the route from the name of the controller type without the Controller suffix. For example, HelloWorldController is interpreted as the HelloWorld route. Unfortunately, this causes an issue for service API versioning if you want split the implementation across different types. To address this issue, you can decorate convention-based controllers that are versioned into different types using the ControllerNameAttribute. In the strictest sense, this is not a convention, but this is only way to make a new controller type match an existing convention-based route with an API version. For example:

[ApiVersion( "2.0" )]
[ControllerName( "HelloWorld" )]
public class HelloWorld2Controller : Controller
{
    public string Get() => "Hello world v2.0!";
}

This approach is not required if you split the controller types into separate namespaces. For example:

namespace My.Services.V1
{
    [ApiVersion( "1.0" )]
    public class HelloWorldController : Controller
    {
        public string Get() => "Hello world v1.0!";
    }
}
namespace My.Services.V2
{
    [ApiVersion( "2.0" )]
    public class HelloWorldController : Controller
    {
        public string Get() => "Hello world v2.0!";
    }
}

Supported API Versioning Methods

Several API versioning methods are supported out-of-the-box:

Multiple methods of API versioning can be supported simultaneously. Use the ApiVersionReader.Combine method to compose two or more IApiVersionReader together. You can also implement your own method of extracting the requested API version using a custom IApiVersionReader.

Clone this wiki locally