我在用 [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
参数可为空,并且我希望由于我已经努力编写了自定义模型绑定程序,因此我可以完全控制错误处理。
如何防止自动添加此错误?
首先,模型绑定发生在模型验证之前。这就是为什么您会收到其他验证错误。
其次,如果您使用
[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;
});