自定义IModelBinder:如何仅输出自定义错误

问题描述 投票:0回答:1

我在用 [ApiController] 属性装饰的控制器中有以下方法:

public ActionResult<string> Test([FromQuery][ModelBinder(BinderType = typeof(ComplexObjectModelBinder)) TComplexObject complexObject)
{
    return "Called!"     
}

我的模型活页夹看起来像这样:

 public class ComplexObjectModelBinder : IModelBinder
 {
     public Task BindModelAsync(ModelBindingContext bindingContext)
     {
         IQueryCollection query = bindingContext.HttpContext.Request.Query;

         if (!query.ContainsKey("parameter1"))
         {
             bindingContext.ModelState.AddModelError("parameter1", $"The `{"parameter1"}` parameter is required.");
             bindingContext.Result = ModelBindingResult.Failed();

             return Task.CompletedTask;
         }

         TComplexObject complexObject = new();

         bindingContext.Result = ModelBindingResult.Success(complexObject);

         return Task.CompletedTask;
     }
 }

总体来说效果不错;当找到所有参数时,对象就被正确绑定了。 问题是,如果未指定“Parameter1”,我会在 400 Bad Request 中收到 2 个错误(而不是 1 个):

{
    "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
    "title": "One or more validation errors occurred.",
    "status": 400,
    "errors": {
        "complexObject": [
            "The complexObject field is required."
        ],
        "parameter1": [
            "The `parameter1` parameter is required."
        ]
    },
    "traceId": "00-40b5c98a19d29dde8ce7614644b18011-b57f2db011466c7e-00"
}

我期望只收到与

parameter1
相关的自定义错误。我不希望
complexObject
参数可为空,并且我希望由于我已经努力编写了自定义模型绑定程序,因此我可以完全控制错误处理。

如何防止自动添加此错误?

asp.net-core model-binding asp.net-apicontroller model-validation
1个回答
0
投票

首先,模型绑定发生在模型验证之前。这就是为什么您会收到其他验证错误。

其次,如果您使用

[ApiController]
,当模型状态无效时,它将收到包含错误详细信息的自动 HTTP 400 响应。

对于您的场景,我建议您自定义操作过滤器并配置

SuppressModelStateInvalidFilter
以禁用自动模型状态验证。

自定义 IActionFilter:

public class MyActionFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Access a value from the request headers
        if (!context.HttpContext.Request.Query.ContainsKey("parameter1"))
        {
            context.ModelState.Clear();
            context.ModelState.AddModelError("parameter1", $"The `{"parameter1"}` parameter is required.");
            context.Result = new BadRequestObjectResult(new ValidationProblemDetails(context.ModelState));
                                
        }
        else
        {
            // Handle other model validation error
                
        }
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // This method runs after the action is executed
    }
}

注册过滤器并配置

SuppressModelStateInvalidFilter 
:

builder.Services.AddControllers(options =>
{
    options.Filters.Add(new MyActionFilter());  // Apply the filter globally
});
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressModelStateInvalidFilter = true;
});
© www.soinside.com 2019 - 2024. All rights reserved.