1

我在 ASP.NET Web API 控制器中有一个相当长的 Get() 方法。像这样的东西:

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() 方法接受的参数进行比较。不过,对于这个问题来说,这似乎有点矫枉过正。有没有更好的办法?理想情况下,一种足够灵活,可以轻松应用于多种方法。

4

1 回答 1

0

所以,希望这个自我回答在 SO 上不是很糟糕的形式,但是在 Cj S. 的回答中得到一点启发,我更多地研究了 Web API 消息生命周期,并最终创建了一个动作过滤器:

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 属性的能力意味着我们可以跳过使用反射,但如果其他人知道更有效的方法来做到这一点,我仍然不会感到惊讶!

于 2013-07-24T22:43:45.197 回答