Skip to content

How to Version Your Service

Chris Martinez edited this page Feb 15, 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:

You can also implement your own method of extracting the requested API version using a custom IApiVersionReader. For example, you might want to implement API versioning using media type negotiation. API versioning by media type is not natively supported because there is no standard content type format (application/vnd.my.company.1+json) or parameter name (application/json;version=1) to support it. It also may be necessary for service authors to change the mappings for media type formatters within their ASP.NET applications.

Clone this wiki locally