Reputation: 1735
I have an issue with model binding a checkbox from a form to an action on the server with a custom object containing a boolean.
Doing a google there seems to be a lot of problems with this, and no good solution. I have tried multiple things, and the problem seems to only happen when it is sent through an ajax call rather than a normal postback.
I have the following in my project (cut down for brevity):
View
@Html.LabelFor(model => model.TillAccess)
@Html.CheckBoxFor(m => m.TillAccess)
Model
public class CreateUserModel
{
public Boolean TillAccess { get; set; }
}
Controller Action
[HttpPost]
public virtual ActionResult CreateUserWizard(CreateUserModel model)
{
...
}
I have added 2 buttons to the form, one sends as a postback and works. It sends the following with a postback if I check it on fiddler2:
TillAccess=true&TillAccess=false
It sends the following if I send it with the ajax button, and doesnt work:
{"TillAccess":["true","false"]}
Is there an issue with the way MVC model binds JSON that stops this working??
I can't get this working through AJAX (which I will be using heavily), every other field binds fine, just not the checkbox, and the fact this works perfect as a normal postback suggests its an issue with the JSON serialiser or model binder for MVC?
UPDATE
The ajax call is as follows:
function CreateUser() {
var FormData = JSON.stringify($('#CreateUserWizardForm').serializeObject());
$.ajax({
url: '@Url.Action(MVC.User.User.ActionNames.CreateUserWizard)',
data: FormData,
contentType: "application/json",
dataType: "json",
type: 'POST',
cache: 'false',
success: function (response) {
alert('successfully created user!');
},
error: function (xhr) {
alert('There was an error creating a user');
}
});
}
Full ajax post is as follows just fyi:
{"BusinessUnitId":"cd56b710-0171-11e1-be50-0800200c9a66","Person.Salutation":"","Person.FirstName":"","Person.LastName":"","TillAccess":["true","false"],"OfficeAccess":"false","TillLoginId":"","OfficeEmailAddress":"","OfficePassword":""}
UPDATE
The serializeObject method was downloaded from the internet (as I was having json issues with the post) and is as follows:
$.fn.serializeObject = function () {
var o = {};
var a = this.serializeArray();
$.each(a, function () {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
UPDATE
The reason I used this serializeObject method was due to an error I received if I used the inbuilt call of:
$('#CreateUserWizardForm').serialize()
It created a post of:
BusinessUnitId=cd56b710-0171-11e1-be50-0800200c9a66&Person.Salutation=&Person.FirstName=&Person.LastName=&TillAccess=true&TillAccess=false&OfficeAccess=false&TillLoginId=&OfficeEmailAddress=&OfficePassword=
Which gave me an error as follows:
System.ArgumentException: Invalid JSON primitive: BusinessUnitId.
UPDATE - ANSWER (I tried to add my answer at the bottom, but it won't let me)
I found the solution. It was my AJAX call that was wrong. I changed it to the following and it is working.
$.ajax({
url: '@Url.Action(MVC.User.User.ActionNames.CreateUserWizard)',
data: $('#CreateUserWizardForm').serialize(),
type: 'POST',
cache: 'false',
success: function (response) {
alert('successfully created user!');
},
error: function (xhr) {
alert('There was an error creating a user');
}
});
The old AJAX call:
var FormData = JSON.stringify($('#CreateUserWizardForm').serializeObject());
$.ajax({
url: '@Url.Action(MVC.User.User.ActionNames.CreateUserWizard)',
data: FormData,
contentType: "application/json",
dataType: "json",
type: 'POST',
cache: 'false',
success: function (response) {
alert('successfully created user!');
},
error: function (xhr) {
alert('There was an error creating a user');
}
});
Upvotes: 3
Views: 2244
Reputation: 1735
I found the solution. It was my AJAX call that was wrong. I changed it to the following and it is working.
$.ajax({
url: '@Url.Action(MVC.User.User.ActionNames.CreateUserWizard)',
data: $('#CreateUserWizardForm').serialize(),
type: 'POST',
cache: 'false',
success: function (response) {
alert('successfully created user!');
},
error: function (xhr) {
alert('There was an error creating a user');
}
});
The old AJAX call:
var FormData = JSON.stringify($('#CreateUserWizardForm').serializeObject());
$.ajax({
url: '@Url.Action(MVC.User.User.ActionNames.CreateUserWizard)',
data: FormData,
contentType: "application/json",
dataType: "json",
type: 'POST',
cache: 'false',
success: function (response) {
alert('successfully created user!');
},
error: function (xhr) {
alert('There was an error creating a user');
}
});
Upvotes: 3
Reputation: 46008
You need to send
{"model":{"TillAccess":["true","false"]}}
The model binder is not binding your model because it cannot match model
parameter with any property.
UPDATE:
TillAccess
property is of type bool
, but you're sending an array of 2 strings. I think this is a problem
Upvotes: 0