An alternate way to handle the versioning of the API is to actually have different versions of the controller for each API version, that way you dont need to have all the checking for every version number in each action method. Each controller is only applicable to one version of the API.
Its cleaner (IMO) to me handle the versioning at the route time rather than action time. You can do this with a routing constraint to check for the version number.
In the below example, the controller V10 and V20 can only be routed to if the route contraint passed - i.e. the header was present, if no header the default (which is v2).:
routes.MapRoute(
"EmployeeListingv1",
"employees",
new { controller = "V10Employees", action = "Index" }, // Parameter defaults
new { ApiV = new ApiVersionConstraint(ApiVersion.Version10) }
);
routes.MapRoute(
"EmployeeListingv2",
"employees",
new { controller = "V20Employees", action = "Index" }, // Parameter defaults
new { ApiV = new ApiVersionConstraint(ApiVersion.Version20) }
);
You could do it using the query string to pass the version like you are currently doing and just change to a route constraint, however I've found it easier to maintain using an optional header in the request. (its also more "RESTful' without getting into that whole debate). No header means default (latest) version of the API.
Sample API Version constraint:
/// <summary>
/// Enable routing of requests to controllers based on the
/// API version contained in the header.
/// </summary>
public class ApiVersionConstraint : IRouteConstraint
{
const string VersionHeader = "X-MY-API-NAME-HERE-VERSION";
private ApiVersion _version = ApiVersion.Unsupported;
public ApiVersionConstraint(ApiVersion version)
{
this._version = version;
}
#region IRouteConstraint Members
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
string vers = string.Empty;
if (httpContext.Request.Headers[VersionHeader] != null)
{
vers = httpContext.Request.Headers[VersionHeader];
}
else
{
vers = "2.0"; // set default here.
}
ApiVersion fromHeader = ApiVersion.Unsupported;
switch (vers)
{
case "1.0":
{
fromHeader = ApiVersion.Version10;
break;
}
case "2.0":
{
fromHeader = ApiVersion.Version20;
break;
}
default:
{
fromHeader = ApiVersion.Unsupported;
break;
}
}
return fromHeader == _version;
}
#endregion
}