Reputation: 35384
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 protected]&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?
Upvotes: 2
Views: 1731
Reputation: 218852
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; }
}
Upvotes: 1
Reputation: 3393
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.
}
Upvotes: 0