Search code examples
c#asp.net-coreasp.net-web-apienumsmodel-binding

How to handle enum as string binding failure when enum value does not parse


In our ASP.net Core Web API application I am looking for a way to catch binding errors when my controller method accepts a complex object which has an ENUM property when ENUMs are de/serialized as strings.

eg.

class Person
{
    public string Name {get; set;}
    public SexEnum Sex {get; set;}
}

enum SexEnum
{
    Male,
    Female,
    Other
}

We use system wide StringEnumConverter so a JSON serialized instance of Person looks like so:

{
    "name": "Ann",
    "sex": "female"
}

Now if I post this JSON (note the typo in the sex property):

{
    "name": "Ann",
    "sex": "femal"
}

the whole object received by the controller method is NULL as binding failed.

I would like to catch that binding error and, instead of having the pipeline go into the controller as if nothing is wrong, return a BAD REQUEST to the client including the detail of which property value failed to bind.

I know the type I am trying to deserialize into, I know the property type I am trying to deserialize and I can see the value does not parse into the type. So I think there must be a way of providing that detail to the client. I just don't know where and how to plug this in.

I would like the solution to be system wide so that all enums are covered, without having to put attributes on the properties of the model or on the enums themselves. (This is because we distribute our API models as a nuget package which cannot have any dependencies.)


Solution

  • Following up on Simply Ged's answer above, AFAICS, this actually cannot be done as the model binding exceptions are swallowed (https://github.com/aspnet/Mvc/issues/3898)

    ModelState contains model binding errors and you can get some information out of that. As we currently use only JSON serialization, I ended up implementing a filter to check the ModelState errors for JsonSerializationException. It is not perfect though as eg. to get the requested value (that failed the binding) out of the JsonSerializationException you need to parse the inner exception message.

    If someone finds a better solution, I will be happy to hear.