Jquery ajax form submit doesn't bundle complex model in mvc 4

I have a form that I need to submit via ajax, but it is not model bound.

My jquery source code is below

function SubmitForm() { console.log($("#PackageSubscription").serialize()); $.ajax({ url: '/HelpDesk/CalculateCost', cache: false, processData: false, data: $("#PackageSubscription").serialize(), type: 'POST', success: function (data) { } }); 

}

Exactly the same form is linked when I use the standard mvc submit (synchronous) via the submit button.

Interestingly, the console log has all the form values, and they are exactly the same when we submit the form synchronously (the console log line from the ajax call and the form values ​​from the Fiddler request inspector are exactly the same)

some sample data is similar to

 MemberId=12345678 &SitePackges[0].SiteId=50 &SitePackges[0].SizeIndicator=2 &SitePackges[0].LstPackageDisplayItems[0].PackageId=4 &SitePackges[0].LstPackageDisplayItems[0].Name=PAT and Emergency Lighting &SitePackges[0].LstPackageDisplayItems[0].IsSubscribed=True &SitePackges[0].LstPackageDisplayItems[0].LastServiceDate= &SitePackges[0].LstPackageDisplayItems[0].ProposedDate= &SitePackges[0].LstPackageDisplayItems[1].PackageId=6 &SitePackges[0].LstPackageDisplayItems[1].Name=Fire Alarm and Extinguishers &SitePackges[0].LstPackageDisplayItems[1].IsSubscribed=True &SitePackges[0].LstPackageDisplayItems[1].LastServiceDate= &SitePackges[0].LstPackageDisplayItems[1].ProposedDate= 

and my viewmodel looks like

 public class PpmTypePackageSubscriptionModel { public int MemberId { get; set; } public DateTime TimeStamp { get; set; } public List<SitePackage> SitePackges { get; set; } public double TotalCost { get; set; } public PpmTypePackageSubscriptionModel() { SitePackges=new List<SitePackage>(); } } public class SitePackage { public int SiteId { get; set; } public int SizeIndicator { get; set; } public string Site { get; set; } public List<PackageDisplayItem> LstPackageDisplayItems { get; set; } public SitePackage() { LstPackageDisplayItems=new List<PackageDisplayItem>(); } } 

See View mark below.

 @using Booker.WebUI.Models @model PpmTypePackageSubscriptionModel @using (@Html.BeginForm("CalculateCost", "HelpDesk", FormMethod.Post, new { @class = "form", id = "PackageSubscription", name = "PackageSubscription" })) { @Html.AntiForgeryToken() @Html.HiddenFor(x => x.MemberId) <table class="table table-responsive table-condensed table-hover table-striped"> @for (int i = 0; i < Model.SitePackges.Count; i++) { <tr> <td class="siteHeading"> @Html.HiddenFor(x => x.SitePackges[i].SiteId) @Html.DisplayFor(x => x.SitePackges[i].Site) @Html.HiddenFor(x => x.SitePackges[i].SizeIndicator) @Html.DisplayFor(x => x.SitePackges[i].SizeIndicator) </td> </tr> <tr> <th class="col-sm-3"> Name </th> <th class="col-sm-2"> Subscribe </th> <th class="col-sm-2"> Last Service Date If Known </th> <th class="col-sm-2"> Proposed Date </th> </tr> for (int j = 0; j < Model.SitePackges[i].LstPackageDisplayItems.Count; j++) { <tr> <td> @Html.HiddenFor(x => x.SitePackges[i].LstPackageDisplayItems[j].PackageId) @Html.HiddenFor(x => x.SitePackges[i].LstPackageDisplayItems[j].Name) @Html.DisplayFor(x => x.SitePackges[i].LstPackageDisplayItems[j].Name) </td> <td> @Html.RadioButtonFor(x => x.SitePackges[i].LstPackageDisplayItems[j].IsSubscribed, true, new { @class = "pull-left " })<label class="pull-left">Yes&nbsp;&nbsp;</label> @Html.RadioButtonFor(x => x.SitePackges[i].LstPackageDisplayItems[j].IsSubscribed, false, new { @class = "pull-left" })<label class="pull-left">No</label> </td> <td> @Html.TextBoxFor(x => x.SitePackges[i].LstPackageDisplayItems[j].LastServiceDate, "{0:d MMM yyyy}", new { @class = "jquery_datepicker form-control", autocomplete = "off" }) </td> <td> @Html.TextBoxFor(x => x.SitePackges[i].LstPackageDisplayItems[j].ProposedDate, "{0:d MMM yyyy}", new { @class = "jquery_datepicker form-control", autocomplete = "off" }) </td> </tr> } } </table> <div class="row"> <div class="col-sm-3"><p>Parking Availability</p></div> <div class="col-sm-5"> <select id="ParkingAvailability" class="form-control" name="ParkingAvailability"> <option value="1">Free Carpark</option> <option value="2">Paid Carpark</option> </select> </div> </div> <div class="row"> <div class="col-sm-3"><p>Access Time</p></div><div class="col-sm-5"> <input class="form-control" name="SiteContactEmail" value="0900-1500 MonSat"> </div </div> <div class="row"> <div class="col-sm-3"> <input class="btn btn-primary" @*type="submit"*@ onclick="SubmitForm(); return false;" value="Calculate Cost" /> </div> <div class="col-sm-5"> <span id="totalCost" class="hide form-control"></span> </div> </div> <div class="row"> <div class="col-sm-5 col-sm-offset-3"> <input class="btn btn-success" type="submit" value="Submit For Approval" /> <input class="btn btn-danger" type="submit" value="Cancel Signup" /> </div> </div> 

}

My main appearance is as follows

 <div id="tabs"> <ul> <li><a href="#tabs-1">Member Sites </a></li> <li><a href="#tabs-2">Services and Packages</a></li> </ul> <div id="tabs-1"> @Html.Partial("_MemberSites") </div> <div id="tabs-2"> @Html.Action("GetAllPpmTypePackages", new { @id = @Model.MemberNumber }) </div> </div> 

And my action methods look like

  [HttpGet] public ActionResult GetAllPpmTypePackages(int id) { // Processing to create the viewmodel and pass to view } [HttpPost] [ValidateAntiForgeryToken] public ActionResult CalculateCost(PpmTypePackageSubscriptionModel ppmTypePackageSubscriptionModel) { // Processing } 
+1
jquery ajax asp.net-mvc asp.net-mvc-4
source share
3 answers

If I understand correctly, the form is not updated, because you are not doing anything with the data received from the ajax response.

You must bind the result to the ajax success function. Ajax is asynchronous, so the data is published, but the answer is not necessarily immediate. When the response is received successfully (without timeout, connection loss, etc.), the ajax call goes to the success function, and the response data is stored in your case in the "data" variable.

Try the following:

 function SubmitForm() { console.log($("#PackageSubscription").serialize()); $.ajax({ url: '/HelpDesk/CalculateCost', cache: false, processData: false, data: $("#PackageSubscription").serialize(), type: 'POST', success: function (data) { alert(data); // This will only show the response for you, use for debugging only $("#MemberId").value(data.MemberId); } }); 
0
source share

Remove processData: false from your ajax. Then he will contact your model. Please read this below:

processData (default: true) Type: Boolean By default, the data passed to the data parameter as an object (technically, nothing but a string) will be processed and converted to a query string that matches the standard content types "application / x-www- form-urlencoded "If you want to send DOMDocument or other raw data, set this parameter to false.

0
source share

This may be a problem with the serialize () function.

Try using JSON.stringify instead.

 <script type="text/javascript"> function OnBtnSubmitClick(s, e) { var item1 = SecurityCode.GetText(); var item2 = SecurityCoderMnem.GetText(); var item3 = SecurityRegNum.GetText(); var item4 = SecurityIsin.GetText(); var item5 = document.getElementById("DocOrderSecurityOut_Id").value; var item6 = document.getElementById("IsEdit").value; var jsmodel = { DocOrderSecurityOut: { SecurityCode: item1, SecurityCoderMnem: item2, SecurityRegNum: item3, SecurityIsin: item4, Id: item5 }, IsEdit: item6 }; $.ajax({ url: '@Url.Action("AjaxForm", "DocOrderSecurityOut")', data: JSON.stringify(jsmodel), dataType: 'html', contentType: "application/json; charset=utf-8", type: "POST", beforeSend: function () { loadingPanel.Show(); }, complete: function () { loadingPanel.Hide(); }, error: function (x, status, error) { alert("Error code: " + x.status + '\n' + "State: " + status + ". More info: " + error); }, success: function (response) { $("#container").html(response); } }); } 

Controller:

 [HttpPost] public ActionResult AjaxForm(DocOrderSecurityOutViewModel model) { // magic } 

At Global.asax:

  ValueProviderFactories.Factories.Add( new JsonValueProviderFactory()); 
0
source share

All Articles