2

If I send a JSON body with a wrong type (e.g. integer where a string is expected in a model by Asp.Net Core), I get a following message:

"$.name": [ "The JSON value could not be converted to System.String. Path: $.name | LineNumber: 1 | BytePositionInLine: 11." ]

This information is not very clear for a random user of a Web Api. Additionally if the same error happens with enum, it will also leak information about fully qualified name of the enum (including namespace) and is even more meaningless for a user than System.String.

Is there any better way to handle this in WebApi? E.g. to change all messages to a generic Value was not of expected type or something like that?

I know of two possible solutions, but both are rather cumbersome:

  1. All models should accept string (though we'll still get the one with string, but it's at least more or less understandable) or object (if it's possible). Then all the validation and mapping should be done manually
  2. Wringing a Converter for each type that is used in model and supplying it to WebApi to use

I really hope there is a better way that allows us to e.g "catch" the exception from parser or inherit from a default converter, etc.

Ilya Chernomordik
  • 27,817
  • 27
  • 121
  • 207
  • _"This information is not very clear for a random user of a Web Api"_ - isn't it? And doesn't release mode hide all internals from error messages? – CodeCaster Feb 18 '20 at 15:42
  • 1
    No, it's not very clear for a user (not a developer of this particular API, especially if they never used .Net), but I have not tried to change to the release mode, I did not think this can affect the output, I will check if it does. – Ilya Chernomordik Feb 18 '20 at 20:12
  • Release mode does not change anything unfortunately – Ilya Chernomordik Feb 19 '20 at 08:34

2 Answers2

2

If you are using NewtonsoftJson, use this setting in Startup.cs. It will give "The input was not valid."

.AddNewtonsoftJson(options => 
{
    options.AllowInputFormatterExceptionMessages = false;
});
Ehsan Mohammadi
  • 1,168
  • 1
  • 15
  • 21
4L4M1N
  • 76
  • 2
  • 7
  • I do use the new .net core json library, is it possible to do there as well? – Ilya Chernomordik Apr 07 '20 at 07:47
  • I haven't tried it yet. May be you have to write custom convertor with modified exception message. This will help: https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to – 4L4M1N Apr 07 '20 at 14:46
  • Thanks for tips anyway, I'll check if there is something that can be done there – Ilya Chernomordik Apr 07 '20 at 15:25
0

Your test/debug version of the API should provide detailed information about how a request is wrong, and you should also put information about these errors in your public documentation.

Your release version should hide all of these details and return some sort of 4XX.

This means every public API should be something like:

public IActionResult MyApiFunction()
{
 try
 {
    ... do something
 }
 catch(Exception ex)
 {
   ... do some logging
   return BadRequest();
 }
}

The bottom line is that the user of the API didn't follow the spec, therefore it was a bad request, end of.

Neil
  • 11,059
  • 3
  • 31
  • 56
  • Well, I understand that, and it's exactly what I want, the point is that cannot figure out how to that. I cannot do this try/catch as it happens during model binding as a part of the framework. So my question is how to achieve that – Ilya Chernomordik Feb 18 '20 at 20:13
  • 1
    No, you should definitely not wrap each action method in a boilerplate try-catch block. Plenty of other places in ASP.NET (MVC) where you can configure error handling. – CodeCaster Feb 18 '20 at 22:23