17

I am trying to enable versioning on a REST API, where the version is specified in the header, as "api-version":2.

According to this tutorial I just need to create

VersionConstraint : IHttpRouteConstraint

and

VersionedRoute: RouteFactoryAttribute

The usage would be to apply the [VersionedRoute("api/controllerName", 2)] Attribute to Controllers, which are designed for specific versions (e.g. version 2 in this case).

This is all good and well, but unfortunately, it's all in MVC5 and I'm using MVC6. Therefore, RouteFactoryAttribute and IHttpRouteConstraint don't work.

I managed to find IRouteConstraint to replace IHttpRouteConstraint (hoping it will work), but I cannot find a replacement for RouteFactoryAttribute.

If anyone can provide a sample of this using MVC 6, or at least mention the correct classes (ideally with namespaces) I need to inherit from?

Dave New
  • 38,496
  • 59
  • 215
  • 394
bilo-io
  • 597
  • 3
  • 17
  • Thanks, I already looked at that code and it seems unnecessarily too much. Looking at old examples, there should be a more compact way to do this. – bilo-io Oct 02 '15 at 12:30
  • Since this is a new framework, there might not be a one-to-one mapping between apis. Sure you can try find out if there is a simpler approach with the new api. – Kiran Oct 02 '15 at 13:03
  • @Bilo_ZA were you able to find a solution to this? – Qudoos Nov 25 '15 at 16:38
  • I have updated my solution and I think it fits the bill. – Maxime Rouiller Nov 26 '15 at 18:45

1 Answers1

10

Here's the minimum amount of work you need.

First, go there and copy the code for the 3 following files:

Once you have this, we'll change the GetVersion method of VersionRangeValidator for the following:

public static string GetVersion(HttpRequest request)
{
    if (!string.IsNullOrWhiteSpace(request.Headers["api-version"]))
        return request.Headers["api-version"];

    return "1";
}

That will read the header and return the API version. The default will be v1 in this scenario.

Here's how to use it on controllers (or it can be the same controllers with 2 actions:

[Route("api/data")]
public class DataController 
{
    [VersionGet("", versionRange: "[1]")]
    public string GetData()
    {
        return "v1 data";
    }
}

[Route("api/data")]
public class DataV2Controller 
{
    [VersionGet("", versionRange: "[2]")]
    public string GetData()
    {
        return "v2 data";
    }
}

So now you just need to give it the right header and it's good. This code has been tested with jQuery like this:

$(document).ready(function(){
    $.ajax({url: '/api/Data/', headers: { 'api-version': 1 }})
    .then(function(data){
            alert(data);
            });
    $.ajax({url: '/api/Data/', headers: { 'api-version': 2 }})
    .then(function(data){
            alert(data);
            });
});
Maxime Rouiller
  • 13,614
  • 9
  • 57
  • 107
  • In your example you mention that the same controller can have 2 actions for different versions. I tested that and it works well but if the ```api-version``` does not match any, e.g: ```api-version: 3``` the routing will find an ambiguous route as there are 2 HttpGet Actions with same signature and it will throw an error: ```AmbiguousActionException: Multiple actions matched. The following actions matched route data and had all constraints satisfied```. Any recommendation on how to handle that scenario? The parameter ```Order``` doesn't make any difference to set what action is preferred. Thx – diegosasw Dec 23 '15 at 02:18
  • You'll have to modify the code that was given in the sample but for me it would be about always providing a default handler. I sadly haven't tried that scenario and I will not be able to give you an answer before 2016. I currently don't have a VS2015 installed on this machine. :( – Maxime Rouiller Dec 23 '15 at 13:47
  • If my answer however matched your original question, please take the time to mark it as answered. :) – Maxime Rouiller Dec 23 '15 at 13:47
  • This is the valid answer. Unfortunately I'm not the user who created the question so I can't mark it as answered ;) – diegosasw Dec 23 '15 at 19:33
  • Lol Christmas insanity – Maxime Rouiller Dec 23 '15 at 20:51