Jonesie Jonesie - 3 months ago 23
Ajax Question

ASP.Net MVC Model wont bind on ajax post

I'm having trouble getting a model to bind on my action when I post from ajax (via jquery).

Model:

public class NoteEditViewModel
{
public bool AddMode { get; set; }
public int ID { get; set; }
public int PersonID { get; set; }
public string Note { get; set; }

public NoteEditViewModel()
{

}
}


Action:

[HttpPost]
public ActionResult Edit(NoteEditViewModel note)
{
...
}


JS: (actually typescript)

$.ajax({
url: this.options.editUrl,
method: 'POST',
data: JSON.stringify(this.convertFormToJSON(this.options.noteFormElement)),
//data: $(this.options.noteFormElement).serialize(),
//data: JSON.stringify({
// AddMode: $("#AddMode").val(),
// ID: $("#ID").val(),
// PersonID: $("#PersonID").val(),
// Note: $("#Note").val()
//}),
//dataType: 'json',
//traditional:true,
//contentType: 'application/json; charset=utf-8',
success: (partialResult) => {
this.options.noteModalElement.modal('hide');
}
});

convertFormToJSON(form : JQuery) {
var array = form.serializeArray();
var json = {};

jQuery.each(array, function () {
json[this.name] = this.value || '';
});

return json;
}


You can see what I've tried here. The action would either receive an empty instance of the model or null.

I did managed to get this to work with a custom ModelBinder, thus:

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var body = controllerContext.RequestContext.HttpContext.Request.Form[0];
var model = JsonConvert.DeserializeObject<NoteEditViewModel>(body);
return model;
}


This may not be the best/safest, but at least it works.

I cant see what I've done wrong here but creating a model binder for each model seems crazy. Non-ajax posts seem to work fine.

Thanks

Answer

You do not need a custom ModelBinder. Your values will be successfully submitted using

$.ajax({
    url: this.options.editUrl,
    method: 'POST',
    data: $('form').serialize(),
    success: (partialResult) => {
      this.options.noteModalElement.modal('hide');
    }
});

The reason your model is not binding in the POST method is because the name of your parameter (note) is also the name of a property in your model and the DefaultModelBinder sets the value of property Note to the posted value, but also attempts to set the instance of NoteEditViewModel to that value (a string) which fails and the model becomes null

Change the signature of the method to

[HttpPost]
public ActionResult Edit(NoteEditViewModel model)

and you model will be correctly bound

Comments