2010-02-22 43 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. 
      } 
     } 
相關問題