Question: How can I get ASP.NET Core WebAPI method to bind to a model's boolean field?

Question

How can I get ASP.NET Core WebAPI method to bind to a model's boolean field?

Answers 2
Added at 2017-01-01 20:01
Tags
Question

I have a form that I'm posting to my WebAPI endpoint using JQuery:

<form>
  Email: <input type="email" name="email" /><br>
  Name: <input type="text" name="name" /><br>
  <input type="checkbox" name="agree" /> I wish to subscribe
</form>

...

function Subscribe() {
    $.ajax({
        url: "api/Subscription/subscribe",
        method: "POST",
        data: $("#SubscriptionForm").serialize()
    })
    .done(function() { alert("yay!"; })
    .fail(function() { alert(":("); });
}

This is, as expected, submitting the form in application/x-www-form-urlencoded form (e.g., email=me@domain.com&name=Joe&agree=on). On the receiving end, my API method looks something like this:

[HttpPost("subscribe", Name = "Subscribe")]
public IActionResult Subscribe(Subscription subscription) {
    if(!ModelState.IsValid) {
        return BadRequest();
    }
    SubscriptionRepository.Create(subscription);
    return Ok();
}

Subscription is a POCO with some string and bool types corresponding to the form fields being submitted, e.g.:

public class Subscription {
   string Email { get; set; }
   string Name { get; set; }
   bool Agree { get; set; }
}

The Problem

As long as none of the checkboxes on the form are checked, the WebAPI method is able to bind the other form fields to the model successfully. But when at least one checkbox is selected, ModelState.IsValid returns false.

I suspect WebAPI is somehow incapable of converting the on value passed for a selected checkbox to a bool. This seems like a pretty basic, universal need, so am I missing something simple?

Answers
nr: #1 dodano: 2017-01-01 20:01

Try to catching the error using :

if (!ModelState.IsValid)
{
    var errors = ModelState.SelectMany(x => x.Value.Errors.Select(z => z.Exception));

    // Breakpoint, examine the list with Exceptions.
}
nr: #2 dodano: 2017-01-01 21:01

If the checkbox has a value attribute, it will be posted when the form is submitted (and check box is selected). If the checkbox was not selected and you try to submit the form, that item will not be submitted, so your boolean property will get the default value, false

If the checkbox does not have a value attribute, then when you select the checkbox and submit the form, the value "on" will be send ( that is what happening to you), If check box is not selected, nothing will be send for that element.

So simply add value="true" to your html which render the checkbox.

<form id="SubscriptionForm">
    Email: <input type="email" name="email" /><br>
    Name: <input type="text" name="name" /><br>
    <input type="checkbox" value="true" name="agree" /> I wish to subscribe
    <input id="submit" type="submit" />
</form>

Also you need to make sure that your properties are public ,otherwise model binder will not be able to set the values of those!

public class Subscription 
{
   public string Email { get; set; }
   public  string Name { get; set; }
   public  bool Agree { get; set; }
}
Source Show
◀ Wstecz