nic*_*125 4 c# api asp.net-mvc routing asp.net-web-api
我正在实现Web API版本控制中的Web API版本控制.我的控制器位于2个独立的命名空间中,我使用了一个自定义的SelectController方法来根据查询参数选择要使用的版本.例如
http://myapi/api/values?version=1.0
Run Code Online (Sandbox Code Playgroud)
这一切都很好,但控制器中的一些操作使用Route属性
[Route("api/values/getNames")]
public HttpResponseMessage Get() { ... }
Run Code Online (Sandbox Code Playgroud)
默认使用哪些映射到正确的控制器
config.MapHttpAttributeRoutes();
Run Code Online (Sandbox Code Playgroud)
在WebApiConfig.cs中
如果我有多个版本的API具有相同的路由,这将不起作用.我是否能够为config.MapHttpAttributeRoutes()提供自定义实现,以便我可以选择要使用的API的正确版本,或者有更好的方法吗?
Mar*_* N. 11
在Codeplex上的官方WebApi 2.1 examplex中有一个例子.它依赖于请求标头值来存储版本.
我认为它更好,因为它允许所有版本的路由保持不变.客户端只需在请求中包含HTTP标头(在本例中为版本号)即可选择版本.
此示例演示如何使用ASP.NET Web API中的属性路由和约束来通过"api-version"HTTP标头动态过滤控制器.当路由使用约束时,每个约束都有机会阻止路由匹配给定的请求.在此示例中,自定义RouteFactoryAttribute(VersionedRoute)为每个属性路由添加约束.
...
自定义约束实现(VersionConstraint)是基于匹配整数值的'api-version'的值实现的.约束的允许版本的值由放置在每个控制器上的VersionedRoute属性提供.当请求进入时,'api-version'的标头值与预期版本匹配.此示例使用标头,但约束实现可以使用任何条件来确定请求是否对路由有效.
无论如何,最终的结果将最终看起来像这样:
[VersionedRoute("api/Customer", 1)]
public class CustomerVersion1Controller : ApiController
{
// controller code goes here
}
[VersionedRoute("api/Customer", 2)]
public class CustomerVersion2Controller : ApiController
{
// controller code goes here
}
Run Code Online (Sandbox Code Playgroud)
除了查询参数支持之外,这是一个允许您使用Web API 2版本化路由(标题)的解决方案(即使用名为'api-version'的标头或名为'?api-version = XXX的查询字符串参数".
HTTP Route约束完成工作:
/// <summary>
/// Add a route constraint to detect version header or by query string
/// </summary>
public class RouteVersionHttpConstraint : IHttpRouteConstraint
{
public const string VersionHeaderName = "api-version";
private const int DefaultVersion = 1;
/// <summary>
/// Add a route constraint to detect version header or by query string
/// </summary>
/// <param name="allowedVersion"></param>
public RouteVersionHttpConstraint(int allowedVersion)
{
AllowedVersion = allowedVersion;
}
public int AllowedVersion
{
get;
private set;
}
/// <summary>
/// Perform the controller match
/// </summary>
/// <param name="request"></param>
/// <param name="route"></param>
/// <param name="parameterName"></param>
/// <param name="values"></param>
/// <param name="routeDirection"></param>
/// <returns></returns>
public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection)
{
if (routeDirection == HttpRouteDirection.UriResolution)
{
int version = GetVersionHeaderOrQuery(request) ?? DefaultVersion;
if (version == AllowedVersion)
{
return true;
}
}
return false;
}
/// <summary>
/// Check the request header, and the query string to determine if a version number has been provided
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
private int? GetVersionHeaderOrQuery(HttpRequestMessage request)
{
string versionAsString;
IEnumerable<string> headerValues;
if (request.Headers.TryGetValues(VersionHeaderName, out headerValues) && headerValues.Count() == 1)
{
versionAsString = headerValues.First();
int version;
if (versionAsString != null && Int32.TryParse(versionAsString, out version))
{
return version;
}
}
else
{
var query = System.Web.HttpUtility.ParseQueryString(request.RequestUri.Query);
string versionStr = query[VersionHeaderName];
int version = 0;
int.TryParse(versionStr, out version);
if (version > 0)
return version;
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
和路线工厂:
/// <summary>
/// Versioning support for the WebAPI controllers
/// </summary>
public class RouteVersionAttribute : RouteFactoryAttribute
{
public int Version { get; private set; }
public RouteVersionAttribute() : this(null, 1)
{
}
/// <summary>
/// Specify a version for the WebAPI controller
/// </summary>
/// <param name="version"></param>
public RouteVersionAttribute(int version) : this(null, version)
{
}
public RouteVersionAttribute(string template, int version)
: base(template)
{
Version = version;
}
public override IDictionary<string, object> Constraints
{
get
{
var constraints = new HttpRouteValueDictionary();
constraints.Add("version", new RouteVersionHttpConstraint(Version));
return constraints;
}
}
public override IDictionary<string, object> Defaults
{
get
{
var defaults = new HttpRouteValueDictionary();
defaults.Add("version", 1);
return defaults;
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
[RouteVersion("api/versiontest", 1)]
public class Version1TestController : BaseApiController
{
// get: api/versiontest
[HttpGet]
public HttpResponseMessage get()
{
return Request.CreateResponse(HttpStatusCode.OK, new { Version = "API Version 1 selected" });
}
}
[RouteVersion("api/versiontest", 2)]
public class Version2TestController : ApiController
{
// get: api/versiontest
[HttpGet]
public HttpResponseMessage get()
{
return Request.CreateResponse(HttpStatusCode.OK, new { Version = "API Version 2 selected" });
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12880 次 |
| 最近记录: |