2010-02-22 35 views
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 

但是,是否有可能让这个用户可以使用查询字符串PARAMS versionv

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

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

+0

是的,你不能用头直接虽然浏览器,如果用户想手动导航有在地址栏中的网址,即类型,你可以,如果你正在做的所有请求虽然AJAX虽然 - 我认为你是如果哟你返回JSON? http://api.jquery.com/jQuery.ajax/请参阅beforeSend添加标题。 – Rosstified 2010-02-23 04:39:08

+0

当然,您可以使用相同的想法,但根据查询字符串而不是标题,取决于您对API的要求及其可访问性。 – Rosstified 2010-02-23 04:55:34

回答

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")]; 
+0

Goo的想法。我想知道是否有可能使它更通用一些,并传入查询字符串值的名称*(即'v'),然后传入actionparamater(即版本)的*名称*。那么我们可以多次使用这个动作过滤器,并在多个动作方法上使用..? – 2010-02-23 01:16:50

+0

好主意,看我的编辑。 – Charlino 2010-02-23 02:11:23

+0

真棒酱。 – 2010-02-23 03:40:11

0

的替代处理API版本的方法实际上有不同的版本每个API版本的控制器,这样你就不需要在每个操作方法中都检查每个版本号。每个控制器仅适用于一个版本的API。

它的清洁程序(IMO)对我来说是在路由时间而不是操作时间处理版本控制。您可以使用路由约束来检查版本号。

在下面的示例中,控制器V10和V20只能被路由到如果路由contraint通过 - 即报头存在,如果没有头中的默认(其为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 
} 
+0

这是一个非常好的想法,实际上:)我真的很喜欢它。但是对于标题值,我不能只从浏览器调用api,但是..对吧? – 2010-02-23 03:42:20

0

只是为了更多的东西添加到这个老问题......你可以在这里结合的技术,并通过改变检查,以便支持请求头或查询字符串版本选择@ Rosstified的答案,包括查询字符串检查:

 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. 
      } 
     } 
相关问题