AJAX message for controller does not set VIewModel parameter correctly

I try to send parameters to the controller action when the field is changed via AJAX, but the search for the first parameter is always null.

The controller actions I'm trying to send are:

public ActionResult Model_GroupCompanyIDChanged(ActionViewModel vm, int oldVal, int newVal) { vm.Model.Observation = "Changed from " + oldVal + " to " + newVal; return Refresh(vm); } 

My zip code serializes the form on the screen and sends it along with the old and new values โ€‹โ€‹of the newly changed field. Old and new value parameters are set correctly in the action parameters, but the vm parameter is always zero in the controller action. There is no problem with the controller URL, as I can debug the action and see that it gets called.

 function ChangeRefreshScreen(ControllerURL, formActionUrl, oldVal, newVal) { var origModel = $("form[action='" + formActionUrl + "']").serialize(); var data = { "oldVal": oldVal , "newVal": newVal , "vm": origModel }; RefreshScreenPassData(ControllerURL, formActionUrl, data); } function RefreshScreenPassData(ControllerURL, formActionUrl, data) { alert(data); $.ajax({ url: ControllerURL, type: 'POST', data: data, success: function (response) { RefreshScreenContent(response); }, error: AjaxError }); } 

Contrast this on the following screen, which works for processing when a specific field is pressed:

Controller action:

 public ActionResult Model_ActionDateClicked(ActionViewModel vm) { vm.Model.Observation = "Clicked"; return Refresh(vm); } 

JavaScript (uses the similar RefreshScreenPassData function above to do the actual POST):

 function ElementClickedRefresh(ControllerURL, formActionUrl) { var origModel = $("form[action='" + formActionUrl + "']").serialize(); RefreshScreenPassData(ControllerURL, formActionUrl, $("form[action='" + formActionUrl + "']").serialize()); } 

In a nutshell, the first sample of the change event first sets the parameters to the object, since there is more than one parameter, and only old and new int parameters are set on the server side when ViewModel vm is zero. In the second clicked image, vm is installed correctly using the serialized form.

The formActionUrl parameter is the same for both sides, and this is not a problem because I debugged the messages, and the only difference I see for the request body in the first example (change event), the vm parameter looks like an encoded URL:

oldVal = 0 & newVal = 02 & Vm = __ RequestVerificationToken% 3DoeQx0RyQ-nOPQ1namoIeRuAWRzfVltfPx5ntsdpuaFTSdADuG_eC__Y54hlWmf8AOAigvyH8R_6qP77bJr1Mm5Yag7a7R9oSQse6e9NJMYg1% 26ViewMode% 3DEdit% 26Model.ActionDate% 3D11% 252F07% 252F2013% 2B09% 253A32% 253A08% 26Model.Observation% 3DClicked% 26Model.OriginatorUserID% 3D1% 26Model .ActiononUserID% 3D0% 26Model.ActionStatusID% 3D1% 26Model.ActionTypeID% 3D0% 26Model.ClientID% 3D23% 26Model.ClientContactID% 3D0% 26Model.PriorityID% 3D0% 26Model.CloseOutDatel 3DA%% 26 %Model.CloseOutDate% 3D%%% % 3D% 26Model.Comments% 3D% 26Model.BusinessUnitID% 3D0% 26Model.Group Company % 252F07% 252F2013% 2B09% 253A32% 253A19% 26Model.ModifiedUserID% 3D1% 26Model.ModifiedDateTime% 3D11% 252F07% 252F2013% 2B09% 253A32% 253A19

but for the second event clicked that works, this is not:

__ RequestVerificationToken = oeQx0RyQ-nOPQ1namoIeRuAWRzfVltfPx5ntsdpuaFTSdADuG_eC__Y54hlWmf8AOAigvyH8R_6qP77bJr1Mm5Yag7a7R9oSQse6e9NJMYg1 & ViewMode = Edit & Model.ActionDate = 11% 2F07% 2F2013 + 09% 3A32% 3A08 & Model.Observation = Modified & Model.OriginatorUserID = 1 & Model.ActiononUserID = 0 & Model.ActionStatusID = 1 & Model.ActionTypeID = 0 & Model.ClientID = 23 & Model.ClientContactID = 0 & Model.PriorityID = 0 & Model.CloseOutDate = & Model.ActionNotes = & Model.ProgressNotes = & Model.Comments = & Model.BusinessUnitID = 0 & Model.GroupCompanyID = 0 & Model.Confidential = false & Model.Id = 1 & Model.Archived = false & Model.AddedUserID = 1 & Model.AddedDateTime = 11% 2F07% 2F2013 + 09% 3A32% 3A19 & Model.ModifiedUserID = 1 & Model.ModifiedDateTime = 11% 2F07% 2F2013 + 09% 3A32% 3A19

I tried to set my parameter string manually by changing javascript to:

 function ChangeRefreshScreen(ControllerURL, formActionUrl, oldVal, newVal) { var origModel = $("form[action='" + formActionUrl + "']").serialize(); var data = "oldVal=" + oldVal + "&newVal=" + newVal + "&vm=" + origModel RefreshScreenPassData(ControllerURL, formActionUrl, data); } 

and the body of the POST request changes to

oldVal = 02 & newVal = 023 & Vm = __ RequestVerificationToken = xiYEcz53UNPVoGZ3RQGO_HFn54LIu0bTjQB-PB13tTEWZ7vUHMbsW25s7rI7D7lBLtACutEpynoNnk66jxijzSzFMCBO_nDoXf_FqsR9Cc81 & ViewMode = Edit & Model.ActionDate = 11% 2F07% 2F2013 + 09% 3A32% 3A08 & Model.Observation = Hits & Model.OriginatorUserID = 1 & Model .ActiononUserID = 0 & Model.ActionStatusID = 1 & Model.ActionTypeID = 0 & Model.ClientID = 23 & Model.ClientContactID = 0 & Model.PriorityID = 0 & Model.CloseOutDate = & Model.ActionNotes = & Model .ProgressNotes = & Model.Comments = & Model.BusinessUnitID = 0 & Model.GroupCompanyID = 023 & Model.Confidential = false & Model.Id = 1 & Model.Archived = false & Model.AddedUserID = 1 & Model.AddedDateTime = 11% 2F07% 2F2013 + 09% 3A32% 3A19 & Model.ModifiedUserID = 1 & Model.ModifiedDateTime = 11% 2F07% 2F2013 + 09% 3A32% 3A19

but it still does not bind the view model parameter.

What am I doing wrong without setting a parameter when it comes from a JavaScript object?

UPDATE 1

I tried manually calling JSON stringify in an attempt to get this, but it still does not work:

 function ChangeRefreshScreen(ControllerURL, formActionUrl, oldVal, newVal) { var origModel = $("form[action='" + formActionUrl + "']").serialize(); var data = "oldVal=" + oldVal + "&newVal=" + newVal + "&vm=" + JSON.stringify(origModel) RefreshScreenPassData(ControllerURL, formActionUrl, data); } 

UPDATE 2

The following worked for me when he adds old and new vals to the form, but they need to be deleted again, otherwise the next time they will be in the form more than once, which spin the old and new vals:

 function ChangeRefreshScreen(ControllerURL, formActionUrl, oldVal, newVal) { var $myForm = $("form[action='" + formActionUrl + "']"); $myForm.append("<input type='hidden' name='oldVal' value='" + oldVal + "' id='oldVal' />"); $myForm.append("<input type='hidden' name='newVal' value='" + newVal + "' id='newVal' />"); var origModel = $myForm.serialize(); RefreshScreenPassData(ControllerURL, formActionUrl, origModel); $('#oldVal').remove(); $('#newVal').remove(); } 

It would be better not to add elements to the DOM, but at least this is a small piece of code and does not require heavy CPU usage. I still hope to retry one of the Gordatron solutions and see if I can get it to work, but may not be in time.

+4
source share
3 answers

Method 1

It seems that falsification of form data does not work for you.

How about trying the following

 function ChangeRefreshScreen(ControllerURL, formActionUrl, oldVal, newVal) { var $myForm = $("form[action='" + formActionUrl + "']"); $myForm.append("<input type='hidden' name='oldVal' value='" + oldVal + "' />"); $myForm.append("<input type='hidden' name='newVal' value='" + newVal + "' />"); var origModel = $myForm.serialize(); RefreshScreenPassData(ControllerURL, formActionUrl, origModel); } 



Update

Method 2

Although the above solution will work in your case (because it worked in a similar case with me), there is another way to do something here.

There are two formats in which POST data is transmitted to the server. One of them is the encoding of the form, which you use with $("form[action='" + formActionUrl + "']").serialize() , and the other with JSON.

In your question above you use a mixture of both

 var data = { "oldVal": oldVal, "newVal": newVal, "vm": origModel }; 

i.e. In the JSON object, you add the serialized form as vm . This is why you get zero in vm in your action, and oldVal and newVal filled correctly.

I would suggest that if you do not want to use the solution above in my answer, you should only go with JSON. those. create a JSON object with your form values โ€‹โ€‹and publish using

 $.ajax({ type: 'POST', url: ControllerURL, contentType: "application/json", data: JSON.stringify(data), success: function (response) { RefreshScreenContent(response); }, error: AjaxError }); 

Note: contentType: "application/json"

I know that getting all form values โ€‹โ€‹using id / names and creating a JSON object will be a little tedious, but, fortunately, I wrote a small toJSON plugin for you some time ago, which does this for you.

All you have to do is execute

 var form = $("form[action='" + formActionUrl + "']").toJSON(); var data = { "oldVal": oldVal, "newVal": newVal, "vm": form }; 

Hope this helps

+1
source

I did a little test to find out if I can recreate your problem. I succeeded, and I managed to get it to work, but I don't know if it has a better way to do this or what you want.

To recreate it, I created a test application and added a model:

 public class Item { public string id {get;set;} public string name { get; set; } } 

view:

 <h2>Test</h2> @using(Html.BeginForm()){ @Html.EditorFor(Model => Model.id) @Html.EditorFor(Model => Model.name) } 

with js:

 $(function () { var origModel = $("form").serialize(); var data = { "oldVal": 'old' , "newVal": 'new' , "vm": origModel }; RefreshScreenPassData("/Home/Test", data); }); function RefreshScreenPassData(ControllerURL, data) { alert(data); $.ajax({ url: ControllerURL, type: 'POST', data: data, dataType:'json', success: function (response) { RefreshScreenContent(response); }, error: AjaxError }); } function AjaxError(e) { alert(e); } 

Controller:

  [HttpGet] public ActionResult Test() { return View(new Item() { id = "1", name = "name" }); } [HttpPost] public ActionResult Test(Item vm, string oldVal,string newval) { return View(new Item() { id = vm.id+"oo", name = vm.name+"000" }); } 

What I learned:

Manual representation of this does not work

 $.ajax({ url: ControllerURL, type: 'POST', data: { "oldVal": 'old' , "newVal": 'new' , "vm": {"id":"1","name":"name"} }, success: function (response) { RefreshScreenContent(response); }, error: AjaxError }); 

your first parameter in action is not null, but its properties are zero (i.e. vm is not null, but vm.id and vm.name)

This WORKS :

  $.ajax({ url: ControllerURL, type: 'POST', data: { "oldVal": 'old' , "newVal": 'new' , "id": "1" , "name": "name" }, success: function (response) { RefreshScreenContent(response); }, error: AjaxError }); 

NEXT PROBLEM:

that the .serialise method on the form returns a string like the url parameter type:

 id=1&name=name 

not json. so I'm quickly looking for a way to get the json form on the form and found this ( Convert form data to a javascript object using jQuery ) .. so I then faked this together:

 jQuery(function () { var data = { "oldVal": 'old' , "newVal": 'new' }; var o = {}; var a = $("form").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 || ''; } }); jQuery.extend(data, o); RefreshScreenPassData("/Home/Test", data); }); function RefreshScreenPassData(ControllerURL, data) { alert(JSON.stringify(data)); $.ajax({ url: ControllerURL, type: 'POST', data: data, success: function (response) { alert(response); }, error: AjaxError }); } 

It simply converts the form into an object and then uses the extension to โ€œcombineโ€ it with other properties that you want to pass back.

This is actually not a solution to your problems, but I hope that it will give enough to move you.

+1
source

another option does not send json .. just serialized completely.

Model:

 public class Item { public string id {get;set;} public string name { get; set; } } 

ViewModel:

 public class ViewModel { public Item model { get; set; } public String CapsName { get { return this.model.name.ToUpper(); } } public String OtherField { get; set; } } 

Controller:

  [HttpGet] public ActionResult Test2() { return View("ViewModelTest",new ViewModel() { model = new Item() { id = "1" , name = "name" } , OtherField="bubba"}); } [HttpPost] public ActionResult Test2(ViewModel vm, string oldVal, string newval) { return View(new Item() { id = vm.model.id + "oo" , name = vm.model.name + "000" }); //pointless code to allow me to put in a break point } 

View:

  @using(Html.BeginForm()){ @Model.CapsName<br /> @Html.EditorFor(m => m.model.id) @Html.EditorFor(m => m.model.name) @Html.EditorFor(m=>m.OtherField) } 

JS:

  jQuery(function () { var data = { "oldVal": 'old' , "newVal": 'new' }; RefreshScreenPassData("/Home/Test2", $.param(data) + "&" + $("form").serialize()); }); function RefreshScreenPassData(ControllerURL, data) { alert(data); $.ajax({ url: ControllerURL, type: 'POST', data: data, success: function (response) { alert(response); }, error: AjaxError }); } 

data that these are messages:

 oldVal=old&newVal=new&model.id=1&model.name=name&OtherField=bubba 

and then the breakpoint is deleted. I have a full view model, a model and old and new values โ€‹โ€‹as expected.

0
source

Source: https://habr.com/ru/post/1492909/


All Articles