5

我想为我的 Web API 创建一个全局验证属性。所以我按照教程完成了以下属性:

public class ValidationActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (actionContext.ModelState.IsValid)
        {
            return;
        }

        var errors = new List<KeyValuePair<string, string>>();
        foreach (var key in actionContext.ModelState.Keys.Where(key =>
            actionContext.ModelState[key].Errors.Any()))
        {
            errors.AddRange(actionContext.ModelState[key].Errors
                  .Select(er => new KeyValuePair<string, string>(key, er.ErrorMessage)));
        }

        actionContext.Response =
            actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, errors);
    }
}

然后我将它添加到 Global.asax 中的全局过滤器中:

configuration.Filters.Add(new ValidationActionFilter());

它适用于我的大多数操作,但不适用于具有可选和可为空请求参数的操作。

例如:

我创建了一条路线:

routes.MapHttpRoute(
    name: "Optional parameters route", 
    routeTemplate: "api/{controller}", 
    defaults: new { skip = UrlParameter.Optional, take = UrlParameter.Optional });

我的一个动作ProductsController

public HttpResponseMessage GetAllProducts(int? skip, int? take)
{
    var products = this._productService.GetProducts(skip, take, MaxTake);

    return this.Request.CreateResponse(HttpStatusCode.OK, this._backwardMapper.Map(products));
}

现在,当我请求此 url 时:http://locahost/api/products我收到带有 403 状态代码和以下内容的响应:

[
{
    "Key": "skip.Nullable`1",
    "Value": "A value is required but was not present in the request."
},
{
    "Key": "take.Nullable`1",
    "Value": "A value is required but was not present in the request."
}
]

我相信这不应该显示为验证错误,因为这些参数都是可选的和可为空的。

有没有人遇到过这个问题并找到了解决方案?

4

2 回答 2

4

您可能还希望避免/禁止对 GET 请求中的原始类型进行模型验证。

public class ModelValidationFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            if (!actionContext.ModelState.IsValid && actionContext.Request.Method != HttpMethod.Get)
            { ...
于 2013-02-12T09:58:43.630 回答
2

似乎您在 Web API 和 MVC 之间弄乱了代码,您应该使用Web API 中的RouteParameter而不是MVC中的UrlParameter

routes.MapHttpRoute(
    name: "Optional parameters route", 
    routeTemplate: "api/{controller}", 
    defaults: new { skip = RouteParameter.Optional, take = RouteParameter.Optional }
    );

但:

您的路由跳过采用的默认参数对您的路由机制没有任何作用,因为您只是在查询字符串中使用它们,而不是在路由模板中。所以最纠正的路线应该是:

routes.MapHttpRoute(
    name: "Optional parameters route", 
    routeTemplate: "api/{controller}"
    );
于 2012-08-10T16:52:32.180 回答