如何自定义模型绑定因JSON反序列化异常失败时返回的错误信息?

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

我的应用程序存在安全问题。当有人向我的端点发送错误的 json 时(例如,传递类型 string 而不是 int),我的 API 将显示 json 反序列化异常:

{
    "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
    "title": "One or more validation errors occurred.",
    "status": 400,
    "errors": {
        "$.questions[0].answers": [
            "The JSON value could not be converted to TestingService.Business.Features.V1.Test.Models.Answer[]. Path: $.questions[0].answers | LineNumber: 11 | BytePositionInLine: 20."
        ]
    },
    "traceId": "00-690e01e0fb451eed8afa4530616fa13f-0396f3a592bd1518-00"
}

当我尝试使用

IExceptionFilter
处理它时,我不能这样做,因为在到达此管道之前抛出了异常。

当我使用中间件时 - 我也无法捕获此异常。

我的控制器设置:

services.AddControllers(options =>
                options.Filters.Add(new ApiErrorFilter()))
        .AddJsonOptions(options =>
            {
                options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
                options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
                options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
                options.JsonSerializerOptions.Converters.Add(new Core.Infrastructure.DateTimeConverter());
            });

如何处理这个异常并将其替换为自定义异常?

c# asp.net-core asp.net-core-webapi model-binding system.text.json
1个回答
0
投票

感谢@Parsa99 - 他提出了答案。对于将来尝试查找的人,我将在这里发布一个我在互联网上找到的示例。

services.AddControllers(options =>
            {
                options.Filters.Add<ApiErrorFilter>();
            })
            .ConfigureApiBehaviorOptions(opt=>
            {
                opt.SuppressModelStateInvalidFilter = false;
                opt.InvalidModelStateResponseFactory = context=>{
                
                    bool knownExceptions = context.ModelState.Values
                    .SelectMany(x => x.Errors)
                    .Where(x => x.Exception is JsonException || (x.Exception is null && String.IsNullOrWhiteSpace(x.ErrorMessage) == false)).Count() > 0;
                    if (knownExceptions)
                    {
                        var error = new ProblemDetails
                        {
                            Status = (int)HttpStatusCode.InternalServerError,
                            Title = "Test",
                        };

                            return new ObjectResult(error)
                        {
                            StatusCode = StatusCodes.Status422UnprocessableEntity,
                        }; //new BadRequestResult(new { state = false, message = "InvalidParameterError" });
                    }
                // ...
                    return new BadRequestObjectResult(context.ModelState);
                };
            })
            .AddJsonOptions(DefaultJsonOptions.OptionsConfiguration);

© www.soinside.com 2019 - 2024. All rights reserved.