2

我有一个如下的操作方法

public JsonResult Index(string version)
{
   .. do stuff, return some data v1 or v2. Default = v2.
}

因此,此操作方法返回一些数据,这些数据可以格式化为Version 1Version 2(无论输出是什么......只要知道它们在示意图上是不同的)。

因此,当用户想要调用访问此资源时,他们会执行以下操作:

http://www.blah.com/api/Index

没什么太难的。

他们也可以这样做...

http://www.blah.com/api/Index?version=1.0

但是,是否有可能使用户可以使用查询字符串参数versionv

eg. http://www.blah.com/api/Index?v=1.0 

这将填充 ActionMethod 中的版本参数。可能的?

4

3 回答 3

3

我猜您可以使用操作过滤器来操作操作方法参数。

基本上只需检查集合中的“v” QueryString,如果存在,将其放入ActionParameters集合中。

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var version = filterContext.HttpContext.Request.QueryString["v"];
    if (!string.IsNullOrEmpty(version))
        filterContext.ActionParameters["version"] = version;
}

HTH,
查尔斯

编辑:让它更通用一点......

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")];
于 2010-02-23T00:57:09.047 回答
0

Just to add something more to this old question... You can combine the techniques here and so support version selection by request header OR query string by changing the check in @Rosstified's answer to include a QueryString check:

        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.
            }
        }
于 2015-01-23T08:36:06.817 回答
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
}
于 2010-02-23T02:32:41.850 回答