It has been quite awhile since I've dealt with complex model binding across a set of inputs in mvc.
If one controller action's params (or a property on one of those params) is an IEnumerable<T> then Mvc will not write the element names in a way that will properly go back to the server.
I Json serialized the parent model into an html attribute on to some parent of the value(s) I want to submit. Some questions allow many answers, and I want to save each time a question answer is changed.
I'm working on making that serialization not contain the about to be consumedIEnumerable<T>property.
var save = function (element, value, event, previousValue,debug) {
console.log('saving:' + value + ' to ' + saveUrl);
var demoText = $(element).closest('[data-demographic]').attr('data-demographic');
var demoJson = htmlDecode(demoText);
var demoModel = JSON.parse(demoJson);
var oldAnswers = demoModel.PossibleAnswers;
demoModel.PossibleAnswers = [];
//TODO: handle multi-select, single-select radio, etc...
if (Object.prototype.toString.call(value) === '[object Array]') {
//value and previousValue could be arrays for multi-select answers
$.each(value, function (i, e) {
demoModel.PossibleAnswers.push({ Id: e });
});
} else {
demoModel.PossibleAnswers.push({ Id: value,Text:$(element).parent().text().trim() });
}
var data = JSON.stringify(demoModel);
data=data.replace('][', '].[');
$.ajax({
dataType: 'json',
url: saveUrl,
contentType: 'application/json; charset=utf-8',
accept: debug ? {
json: 'application/json',
} : {},
type: 'POST', data: data,
success: function (data, status, jqXhr) {
if (debug) {
var answerMirror = data.PossibleAnswers;
delete data.PossibleAnswers;
console.log(data);
console.log(answerMirror);
} else { //update dom to new read-only model?
//TODO: adjust with new html
console.log(data);
}
}
});
};
There's the heart of it. Notice I don't actually have to use the special name=foo.bar[0].Id on my inputs, but that is probably still a good idea.
This thing was almost working without doing any JSON.stringify but the IEnumerable<T> data was ignored by Mvc's model binder. With that in mind, I had to specify the contentType of the ajax request.