Альтернативный способ обработки версий API состоит в том, чтобы фактически иметь разные версии контроллера для каждой версии API, таким образом, вам не нужно выполнять всю проверку для каждого номера версии в каждом методе действия. Каждый контроллер применим только к одной версии API.
Его очиститель (IMO) для меня обрабатывает управление версиями во время маршрута, а не во время действия. Вы можете сделать это с помощью ограничения маршрутизации, чтобы проверить номер версии.
В приведенном ниже примере контроллеры V10 и V20 могут быть направлены только в том случае, если пройдено ограничение маршрута - т.е. присутствует заголовок, если заголовок по умолчанию отсутствует (то есть 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) }
);
Вы можете сделать это, используя строку запроса, чтобы передать версию, аналогичную текущей в данный момент, и просто перейти на ограничение маршрута, однако я обнаружил, что проще поддерживать использование необязательного заголовка в запросе. (он также более «RESTful», не вдаваясь в эту дискуссию). Отсутствие заголовка означает стандартную (последнюю) версию API.
Пример ограничения версии API:
/// <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
}