How to add custom “Cannot deserialize” error message in ASP.NET Core 2

后端 未结 1 1815
走了就别回头了
走了就别回头了 2021-01-28 16:52

I am building an asp.net-core REST api.

How to change the default error: \"Cannot deserialize the current JSON array (e.g. [1,2,3]) into type \'Namespace.Name.Space.Typ

相关标签:
1条回答
  • 2021-01-28 17:31

    I think something already catches it and wraps it in 400 bad request.

    ASP.NET Core 2.1 and later version have added the [ApiController] attribute, which automatically handles model validation errors by returning a BadRequestObjectResult with ModelState passed in.

    A simple solution is that you remove the [ApiController] and return your own error message totally:

    if (!ModelState.IsValid)
    {
        return BadRequest(new { ErrorMessage = "Cannot deserialize" });
    }
    

    If you want to keep the ProblemDetails template, you could make use of the InvalidModelStateResponseFactory property.

    The default response type for HTTP 400 responses is ValidationProblemDetails class. So, we will create a custom class which inherits ValidationProblemDetails class and define our custom error messages.

    public class CustomBadRequest : ValidationProblemDetails
    {
        public CustomBadRequest(ActionContext context)
        {
            ConstructErrorMessages(context);
            Type = context.HttpContext.TraceIdentifier;
        }
    
        private void ConstructErrorMessages(ActionContext context)
        {
            var myerror = "Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Core22APITest.Controllers.TestBindController+RetrieveMultipleResponse' because the type requires a JSON object (e.g. {\"name\":\"value\"}) to deserialize correctly.\r\nTo fix this error either change the JSON to a JSON object (e.g. {\"name\":\"value\"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.\r\nPath '', line 1, position 1.";
            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]);
                        if(errorMessage == myerror)
                        {
                            Errors.Add(key, new[] { "Cannot deserialize" });
                        }
                        else
                        {
                            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]);
                            if (errorMessages[i] == myerror)
                            {
                                errorMessages[i] =  "Cannot deserialize" ;
                            }
                        }
    
                        Errors.Add(key, errorMessages);
                    }
                }
            }
        }
    
        string GetErrorMessage(ModelError error)
        {
            return string.IsNullOrEmpty(error.ErrorMessage) ?
                "The input was not valid." :
            error.ErrorMessage;
        }
    }
    

    In startup.cs:

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
                .ConfigureApiBehaviorOptions(options =>
                {
                    options.InvalidModelStateResponseFactory = context =>
                    {
                        var problems = new CustomBadRequest(context);
    
                        return new BadRequestObjectResult(problems);
                    };
                });
    

    Postman Result:

    Refer to https://coderethinked.com/customizing-automatic-http-400-error-response-in-asp-net-core-web-apis/

    0 讨论(0)
提交回复
热议问题