Reputation: 273
I have a security problem in my app. When somebody sends wrong json to my endpoint (for example, pass type string instead if int), my API displays json deserialisation exception:
{
"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"
}
When I try to handle it using IExceptionFilter
, I can not do this, because the exception is thrown before this pipeline was reached.
When I use middleware - I can't catch this exception either.
My controller setup:
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());
});
How to handle this exception and replace it with a custom one?
Upvotes: 0
Views: 128
Reputation: 273
Thanks for @Parsa99 - he suggested the answer. For anyone who will try to find in in the future, I will post here an example that I was found in the internet.
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);
Upvotes: 2