我在ASP.NET Web API控制器中有一个相当冗长的Get()方法。像这样:
public PaginatedResult Get(int perPage = 10, int pageNum = 0, string param1 = null, [...] string param20 = null)
我想要的是能够处理请求包含不属于方法签名的查询参数的情况。也就是说,如果有人要求:
/?perPage=10¶n19=foo¶m21=bar
......我希望能够说,“嘿,那里'paran19'和'param21'都不存在,所以它们不会影响这个查询的结果!”
我能想到的唯一方法就是在Request上调用GetQueryNameValuePairs(),然后使用reflection将该列表与我的Get()方法接受的params进行比较。但这对于这个问题似乎有些过分。有没有更好的办法?理想情况下,一个足够灵活,可以轻松应用于多种方法。
答案 0 :(得分:0)
所以,希望这个自我答案在SO上并不差,但是从Cj S.的答案中得到一点点刺激,我更多地关注Web API消息生命周期,最后创建了一个Action Filter: / p>
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放入响应中,它使用一些有用的元数据包装响应。但是这段代码应该很容易重新用于使用无关的params做其他事情。使用filterContext的ActionArguments属性的能力意味着我们可以跳过使用反射,但如果其他人知道更有效的方法,我仍然不会感到惊讶!