我有一个像下面这样的动作方法
public JsonResult Index(string version)
{
.. do stuff, return some data v1 or v2. Default = v2.
}
因此,此操作方法返回一些数据,可以将其格式化为Version 1
或Version 2
(无论输出是什么......只知道它们在逻辑上不同)。
因此,当用户想要调用访问此资源时,请执行以下操作:
http://www.blah.com/api/Index
没什么太难的。
他们也可以这样做......
http://www.blah.com/api/Index?version=1.0
但是,是否可以使用户可以使用查询字符串参数version
或v
eg. http://www.blah.com/api/Index?v=1.0
这将填充ActionMethod中的version参数。可能的?
答案 0 :(得分:3)
我猜你可以使用动作过滤器操作动作方法参数。
基本上只需检查QueryString
集合中的“v”,如果存在,请将其放入ActionParameters
集合中。
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var version = filterContext.HttpContext.Request.QueryString["v"];
if (!string.IsNullOrEmpty(version))
filterContext.ActionParameters["version"] = version;
}
HTHS,
查尔斯
编辑:让它更通用......
public class QueryStringToActionParamAttribute : ActionFilterAttribute
{
private string _queryStringName;
private string _actionParamName;
public QueryStringToActionParamAttribute(string queryStringName, string actionParamName)
{
_queryStringName = queryStringName;
_actionParamName = actionParamName;
}
public override void OnActionExecuting(ActionExecutedContext filterContext)
{
var queryStringValue = filterContext.HttpContext.Request.QueryString[_queryStringName];
if (!string.IsNullOrEmpty(queryStringValue))
{
filterContext.ActionParameters[_actionParamName] = queryStringValue;
}
}
}
然后你可以这样称呼它:
[QueryStringToActionParam("v", "version")];
答案 1 :(得分:0)
处理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
}
答案 2 :(得分:0)
只是为这个旧问题添加更多内容......您可以在这里结合使用这些技术,因此通过更改@ Rosstified的答案以包含QueryString检查来支持请求标头或查询字符串的版本选择:
if (httpContext.Request.Headers[VersionHeader] != null) {
vers = httpContext.Request.Headers[VersionHeader];
} else {
if (httpContext.Request.QueryString["v"] != null) {
vers = httpContext.Request.QueryString["v"];
} else {
vers = "1.0"; // set default here.
}
}