I'm trying to tack on some additional data a POST request sent to my server. Originally, I was sending just several forms worth of information:
$.ajax({
url: 'SaveAllDetails',
type: 'POST',
data: $('form').serialize(),
dataType: 'json'
});
and the MVC Controller method:
[HttpPost]
public ActionResult SaveAllDetails([Bind(Prefix = "order")]ExistingOrderDetailsModel existingOrderDetailsModel,
[Bind(Prefix = "task")]ExistingTaskDetailsModel existingTaskDetailsModel, [Bind(Prefix = "device")]DeviceDetailsModel deviceDetailsModel)
{
....
}
This works great. MVC's model binder is able to correctly de-serialize the URL-encoded string.
Now, requirements have changed. I need to send an additional array of data along with my three forms. This array of data is not held within a form and does not have a binding prefix. I need to do this all in the same Controller method because all validation needs to be performed inside of a single transaction.
So, I've now got:
var subcomponentsGridRows = JSON.stringify(subcomponentsDetailsView.getAllGridData());
var existingOrderDetailsFormData = $('form#existingOrderDetailsForm').serialize();
var existingTaskDetailsFormData = $('form#existingTaskDetailsForm').serialize();
var deviceDetailsFormData = $('form#existingDeviceDetailsForm').serialize()
$.ajax({
url: 'SaveAllDetails',
type: 'POST',
data: {
existingOrderDetailsModel: existingOrderDetailsFormData,
existingTaskDetailsModel: existingTaskDetailsFormData,
deviceDetailsModel: deviceDetailsFormData,
subcomponentsGridRows: subcomponentsGridRows
},
dataType: 'json'
});
This doesn't work for at least one reason. Each form is represented as a URL-encoded string. subcomponentsGridRows is a JSON structure. The MVC model binder isn't capable of deciphering both types of information in one go as far as I can tell.
What's a good way to go about tackling this problem?
You might find the following plugin
useful.
Here's how it might be useful to you. Let's start by cleaning your controller action by defining a view model:
public class MyViewModel
{
public ExistingOrderDetailsModel Order { get; set; }
public ExistingTaskDetailsModel Task { get; set; }
public DeviceDetailsModel Device { get; set; }
public AdditionalRowsViewModel[] AdditionalRows { get; set; }
}
In this example the AdditionalRowsViewModel
will obviously hold the additional information you are trying to pass to the controller action.
And then your controller action will become:
[HttpPost]
public ActionResult SaveAllDetails(MyViewModel model)
{
....
}
OK, this step was absolutely necessary, it's just that when I see a controller action taking more than 1 parameter I simply define a view model.
And finally let's adapt our AJAX call:
$.ajax({
url: 'SaveAllDetails',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({
order: $('form#existingOrderDetailsForm').serializeObject(),
task: $('form#existingTaskDetailsForm').serializeObject(),
device: $('form#existingDeviceDetailsForm').serializeObject(),
additionalRows: subcomponentsDetailsView.getAllGridData()
}),
success: function(result) {
// do something with the result of the AJAX call here
}
});
Things to notice:
dataType: 'json'
parameter in your AJAX request. You are using ASP.NET MVC and hopefully you are returning a Jsonresult from your controller action which is successfully setting the Content-Type
response header to the correct value. jQuery is intelligent enough to use the value of this response header and pre-process the result
variable that will be passed to the success
callback of your AJAX request. So in this case you will already get a javascript objectcontentType: application/json
parameter. Otherwise how do you expect that ASP.NET MVC will know that the client is sending JSON and apply the correct model binder? By the way the default Content-Type request header that jQuery will send is application/x-www-form-urlencoded
, so if you are sending JSON payload in your POST request that would be a conflict and violation of the protocol.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With