2013-07-24 95 views
1

我在ASP.NET Web API控制器中有相當長的Get()方法。事情是這樣的:在ASP.NET Web API中查找無法識別的查詢參數

public PaginatedResult Get(int perPage = 10, int pageNum = 0, string param1 = null, [...] string param20 = null) 

我想是能夠處理的情況下,其中一個請求包括查詢參數,這不是方法簽名的一部分。也就是說,如果有人請求這樣的:

/?perPage=10&paran19=foo&param21=bar 

...我希望能夠說,「嘿,既不是‘paran19’也不是‘param21’存在,這樣他們就不會影響這個結果查詢!」

我能想到的處理此問題的唯一方法是調用GetQueryNameValuePairs(),然後使用反射將該列表與我的Get()方法接受的參數進行比較。這似乎是這個問題的矯枉過正。有沒有更好的辦法?理想情況下,一個足夠靈活,可以輕鬆應用於多種方法。

+1

我認爲你最終需要在其他地方尋找那些「不匹配」的參數(你提到了一個好方法:GetQueryNameValuePairs)。您可能需要考慮構建一個自定義ModelBinder來執行此操作,以免最終將控制器的複雜性添加到控制器中。 –

回答

0

所以,希望這種自我回答不是糟糕的形式,但是從Cj S.的回答中有點刺激,我更加關注Web API消息生命週期,最終創建了一個Action Filter:

public class QueryParamMatchingActionFilter : ActionFilterAttribute 
{ 

    public override void OnActionExecuting(HttpActionContext filterContext) 
    { 
     List<string> queryParamNames = filterContext.Request.GetQueryNameValuePairs().Select(q => (string)q.Key.ToLowerInvariant()).ToList(); 

     List<string> methodParams = filterContext.ActionArguments.Select(q => (string)q.Key.ToLowerInvariant()).ToList(); 

     List<string> unrecognized = queryParamNames.Where(qp => !methodParams.Any(mp => mp == qp)).ToList(); 

     if (unrecognized.Count > 0) 
     { 
      List<string> errors; 
      if (filterContext.Request.Properties.ContainsKey("MY_ERRORS")) 
       errors = (List<string>)filterContext.Request.Properties["MY_ERRORS"]; 
      else 
       errors = new List<string>(); 

      foreach (string badParam in unrecognized) 
      { 
       errors.Add(String.Format("UNRECOGNIZED PARAMETER IGNORED: {0}", badParam)); 
      } 

      filterContext.Request.Properties["MY_ERRORS"] = errors; 
     } 
    } 

} 

所以現在我可以用「[QueryParamMatchingActionFilter]」來裝飾我的控制器。 MY_ERRORS的內容通過我已經設置的DelegatingHandler放入響應中,該響應包含一些有用的元數據。但是這段代碼應該足夠簡單,可以重新使用外部參數來做其他事情。使用filterContext的ActionArguments屬性的能力意味着我們可以跳過使用反射,但如果有人知道更有效的方法來做到這一點,我仍然不會感到驚訝!

相關問題