全局错误处理程序,包括 Model Binder 错误
Global error handler including Model Binder errors
我在一个 AspNet Core 3.1 web-api 项目上工作,该项目正在由 PenTest 机构进行测试,当不正确的输入数据导致包含有关项目代码内部信息的响应时,他们会标记情况,如下所示:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-371d845d720a4f4c8ad3d618e4386125-7086a0b4fb30614c-00",
"errors": {
"$.flags": [
"The JSON value could not be converted to System.Int32. Path: $.flags | LineNumber: 0 | BytePositionInLine: 47."
]
}
}
所以我们决定用一些中性的东西来改变“errors/$.flags”的消息属性,比如“输入数据不正确”。
我通过提供自定义 JsonConverter 属性 class 解决了这个特殊情况,并且它可以很好地为适当的模型 属性 装饰。另一个类似的问题是,空集合元素会导致此类响应,我通过在输入端点参数(IModelBinder 接口的实现)上为复杂 class 提供自定义模型联编程序来修复。
该项目有很多端点和输入模型 classes,因此提供自定义 JsonConverters 或模型绑定器看起来无效且不符合未来要求,因为每个新端点的输入都需要配备一些一种解决方案。所以问题来了——是否有可能有某种全局错误处理程序来覆盖模型联编程序错误?中间件中的标准 aspnet 核心错误处理程序无法处理模型联编程序错误,因为它们在实际调用操作之前发生在操作调用逻辑中。
或者可能有一种方法可以配置 System.Text.Json 功能来为各种 JsonExceptions 提供自定义错误消息在绑定错误的情况下抛出?
对于模型绑定错误,您可以在 asp.net core web api.I 中得到 400 Bad Request api.I 建议您可以自定义 ValidationProblemDetails
来显示错误。
public class CustomBadRequest : ValidationProblemDetails
{
public CustomBadRequest(ActionContext context)
{
Title = "Invalid arguments to the API";
Detail = "The inputs supplied to the API are invalid";
Status = 400;
ConstructErrorMessages(context);
Type = context.HttpContext.TraceIdentifier;
}
private void ConstructErrorMessages(ActionContext context)
{
foreach (var keyModelStatePair in context.ModelState)
{
var key = keyModelStatePair.Key;
var errors = keyModelStatePair.Value.Errors;
if (errors != null && errors.Count > 0)
{
if (errors.Count == 1)
{
var errorMessage = GetErrorMessage(errors[0]);
Errors.Add(key, new[] { errorMessage });
}
else
{
var errorMessages = new string[errors.Count];
for (var i = 0; i < errors.Count; i++)
{
errorMessages[i] = GetErrorMessage(errors[i]);
}
Errors.Add(key, errorMessages);
}
}
}
}
string GetErrorMessage(ModelError error)
{
return "Incorrect input data.";
}
}
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = context =>
{
var problems = new CustomBadRequest(context);
return new BadRequestObjectResult(problems);
};
});
}
结果:
我在一个 AspNet Core 3.1 web-api 项目上工作,该项目正在由 PenTest 机构进行测试,当不正确的输入数据导致包含有关项目代码内部信息的响应时,他们会标记情况,如下所示:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-371d845d720a4f4c8ad3d618e4386125-7086a0b4fb30614c-00",
"errors": {
"$.flags": [
"The JSON value could not be converted to System.Int32. Path: $.flags | LineNumber: 0 | BytePositionInLine: 47."
]
}
}
所以我们决定用一些中性的东西来改变“errors/$.flags”的消息属性,比如“输入数据不正确”。
我通过提供自定义 JsonConverter
该项目有很多端点和输入模型 classes,因此提供自定义 JsonConverters 或模型绑定器看起来无效且不符合未来要求,因为每个新端点的输入都需要配备一些一种解决方案。所以问题来了——是否有可能有某种全局错误处理程序来覆盖模型联编程序错误?中间件中的标准 aspnet 核心错误处理程序无法处理模型联编程序错误,因为它们在实际调用操作之前发生在操作调用逻辑中。
或者可能有一种方法可以配置 System.Text.Json 功能来为各种 JsonExceptions 提供自定义错误消息在绑定错误的情况下抛出?
对于模型绑定错误,您可以在 asp.net core web api.I 中得到 400 Bad Request api.I 建议您可以自定义 ValidationProblemDetails
来显示错误。
public class CustomBadRequest : ValidationProblemDetails
{
public CustomBadRequest(ActionContext context)
{
Title = "Invalid arguments to the API";
Detail = "The inputs supplied to the API are invalid";
Status = 400;
ConstructErrorMessages(context);
Type = context.HttpContext.TraceIdentifier;
}
private void ConstructErrorMessages(ActionContext context)
{
foreach (var keyModelStatePair in context.ModelState)
{
var key = keyModelStatePair.Key;
var errors = keyModelStatePair.Value.Errors;
if (errors != null && errors.Count > 0)
{
if (errors.Count == 1)
{
var errorMessage = GetErrorMessage(errors[0]);
Errors.Add(key, new[] { errorMessage });
}
else
{
var errorMessages = new string[errors.Count];
for (var i = 0; i < errors.Count; i++)
{
errorMessages[i] = GetErrorMessage(errors[i]);
}
Errors.Add(key, errorMessages);
}
}
}
}
string GetErrorMessage(ModelError error)
{
return "Incorrect input data.";
}
}
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = context =>
{
var problems = new CustomBadRequest(context);
return new BadRequestObjectResult(problems);
};
});
}
结果: