khellang / Middleware

Various ASP.NET Core middleware
MIT License
811 stars 112 forks source link

How can I avoid returning internal class information in error? #199

Closed mschaefer-gresham closed 1 year ago

mschaefer-gresham commented 1 year ago

When I pass invalid json to my public api I get this problem details back which includes the name and object hierarchy of my model class (see < PATH TO MY INTERNAL DTO MODEL CLASS IS PROVIDED HERE > below).

Is there a way I can prevent these internal details from being returned using the settings alone (i.e. without having to override something and remove it myself)?

Note: IncludeExceptionDetails is false in this case.

{
    "errors": {
        "": [
            "Cannot deserialize the current JSON object (e.g. {\"name\":\"value\"}) into type 'System.Collections.Generic.List`1[< PATH TO MY INTERNAL DTO MODEL CLASS IS PROVIDED HERE >]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.\nTo fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.\nPath '', line 1, position 4."
        ]
    },
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
    "title": "Bad request.",
    "status": 400,
    "detail": "See the errors property for details.",
    "instance": "/api/my-endpoint",
    "traceId": "00-2373ca874ee13456cbf38743e0425c90-c3102cb77903efea-00"
}

It seems from this post I will need to customize the error message myself. But I am really hoping I can avoid doing this.

I can't customize the Newtonsoft error messsage, so it seems the only way to do this is to override the error message inside of InvalidModelStateResponseFactory:

.ConfigureApiBehaviorOptions(setupAction =>
{
   setupAction.InvalidModelStateResponseFactory = context =>
   {
        var pdf = context.HttpContext.RequestServices.GetRequiredService<ProblemDetailsFactory>();
        var pd = pdf.CreateValidationProblemDetails(context.HttpContext, context.ModelState);
        pd.Errors["myKey"] = new string[]{"My new error message"};   // ===> override message here if it contains class info
        ....
        return new BadRequestObjectResult(pd)
        {
            ContentTypes = { "application/problem+json" }
        };
    }
} 

If there is a better I would appreciate some help.