简体   繁体   中英

How to make ASP.NET Core bind partially to valid data?

Let's say I have this model:

public enum State
{
    Valid = 1,
    Invalid = 2
}

public class Person
{
    public string Name { get; set; }
    
    public State state { get; set; }
}

And this controller action:

[HttpPost]
public object SavePerson([FromBody] Person person)
{
    return person;
}

If I send this JSON, everything works just fine:

{
    "name": "John",
    "state": 1
}

However, if I change the "state": 1 to an invalid enumeration like "state": "" or "state": "1" , then the person parameter would be null.

In other words, if I send a JSON that is partially valid, ASP.NET Core ignores all fields.

How can I configure ASP.NET Core to at least extract the valid fields from the body?

You need to handle deserialization exception.

This code will put a default value each time it will encounter a problem in a field but the json string itself must be a valid json string.

    static void Main(string[] args)
    {
        //This should be run on startup code (there are other ways to do that as well - you can put this settings only on controllers etc...)
        JsonConvert.DefaultSettings = () => new JsonSerializerSettings
        {
            Error = HandleDeserializationError
        };

        var jsonStr = "{\"name\": \"John\",\"state\": \"\" }";
        var person = JsonConvert.DeserializeObject<Person>(jsonStr);         

        Console.WriteLine(JsonConvert.SerializeObject(person)); //{"Name":"John","state":0}
    }

    public static void HandleDeserializationError(object sender, ErrorEventArgs args)
    {
        var error = args.ErrorContext.Error.Message;
        args.ErrorContext.Handled = true;
    }

For WebAPI you should have a Startup.cs file looks like this:

    public void ConfigureServices(IServiceCollection services)
    {
        //look for services.AddControllers() -> or add it if it does not exist
        services.AddControllers()
            .AddMvcOptions(options =>
            {
               //... might have options here
            })
               //this is what you need to add
            .AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.Error = HandleDeserializationError
            });
    }

Try this nullable operator:

public State? state { get; set; }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM