0

As I mentioned in title I'm trying to send an array of view models back to a controller through an Ajax request.

I'll use some dummy values and names:

MyViewModel.cs

int VM_id1;
int VM_id2;
string VM_str1;
string VM_str2;

Controller

// here I get 0 and null values
public ActionResult MyPostController(List<MyViewModel> vm) { ... }

View with ajax

In my view I have a form with fields from above, and a preview window where every time I submit form, those values are added there(not posting to controller yet). Then, when I'm ok with the list of added values I have another submit button that sends the array of view models to controller.

var vmData = new Array();
...
vmData.push($("form").serializeArray());//not the exact code but the idea is that I'm pushing serialized data from form
// the ajax request
$.ajax({
   type:"POST" ,
   url: "someURL"
   dataType: "json"   ,
   contentType: "application/json; charset=utf-8",
   data: JSON.stringify(vmData)
   //data: {vm: JSON.stringify(vmData)}//this generates an error
})

vmData in Chrome console looks like this (example for 2 array values):

(2)[Array(4), Array(4)]
[
    0 : Array(4)
       0:{name: "VM_id1" ,value: "123"}
       1:{name: "VM_id2" ,value: "99"}
       2:{name: "VM_str1" ,value: "string1"}
       3:{name: "VM_str2" ,value: "string2"}
    1 : Array(4)
       0:{name: "VM_id1" ,value: "1"}
       1:{name: "VM_id2" ,value: "55"}
       2:{name: "VM_str1" ,value: "someval1"}
       3:{name: "VM_str2" ,value: "someval1"}
 ]

vmData stringified:

[
  0: [{name: "VM_id1" ,value: "123"}, 1:{name: "VM_id2" ,value: "99"},{name: "VM_str1" ,value: "string1"} ,{name: "VM_str2" ,value: "string2"}]
  1:[{...},{...},{...},{...}]
]

Problem: when data is posted in controller I get 2 list items with null values for all fields. What am I doing wrong?

Another thing, if I manage to solve this, is that I want to pass __RequestVerificationToken also, but that's another problem.

Thank you for your time!

6
  • In razor pages,you need to add __RequestVerificationToken . Commented Dec 14, 2020 at 11:24
  • And remember add [FromBody] attribute. Commented Dec 14, 2020 at 11:26
  • @Yinqiu I forgot to mention, it's not an WebAPI, it's an ActionResult Commented Dec 14, 2020 at 11:40
  • public ActionResult MyPostController([FromBody]List<MyViewModel> vm) Commented Dec 14, 2020 at 11:40
  • You can see my this reply Commented Dec 14, 2020 at 11:41

2 Answers 2

0

I do what you are doing, but a slightly different way. So I create a class wrapper like so:

public class HomeIndexModel
{

  public List<MyViewModel> Items { get; set; }

}

In the form I'll have:

<form id="x" ..>

   @for (var i = 0; i < Model.Items.Count; i++)
   {
      ..
      @Html.TextBoxFor(m => m.Items[i].Name)
      ..
   }

</form>

And I'll do the following to send it back to the server:

$.ajax({
   type: "post",
   url: "..",
   data: $("#x").serialize()
});

And that can be received by this action:

public ActionResult Index(HomeIndexModel model)
{
   var items = model.Items.Where(i => i.IsSelected == true);

   //Save
}

Your way could work here too; I find having the top-level wrapper has some benefits (it makes it easier to pass along additional data). To include a serialization token, a serialization token is essentially a form element that gets rendered, and as such, it should be included in the form serialization and sent back to the server.

Sign up to request clarification or add additional context in comments.

4 Comments

I have an array of $("#x").serialize(), I get the idea but it think same thing will happen
You have more than one form you are trying to post back to the server?
kind of, I have one form, but when I submit, data is appended to a preview div, and in same time is saved serialized in a javascript array variabile . On each submit I push data in that variable. Finally I send this array variable to server through ajax -> here I have the problem(when data gets to server is null)
basically I have a modal with a form where I input some customer info(let's say: name, surname, email, phone) -> when submit, this customer is printed to a preview section in my modal. After I add 3,4 customers to this preview section I send an array with customers to server(the actual submit to server).
0

So, main problem was that server expected other format of data -> so a flattening of the serializeArray() output was required.

var formData = $("form").serializeArray();

// flattening
var toSend = {};
formData .forEach(function(x){ toSend[x.name] = x.value; })

// get __RequestVerificationToken value
headers["__RequestVerificationToken"] = formData.reverse(0.pop().value;

// pushing to array of viewModels
vmData.push(toSend);

So this:

 [
       0:{name: "VM_id1" ,value: "123"}
       1:{name: "VM_id2" ,value: "99"}
       2:{name: "VM_str1" ,value: "string1"}
       3:{name: "VM_str2" ,value: "string2"}
 ]

Gets flattened to this(which is what server expected):

{
  VM_id1 : "123",
  VM_id2 : "99",
  VM_str1 : "string1",
  VM_str2 : "string2"
}

Also I needed to send __RequestVerificationToken to controller as well -> solved with this approach.

Finally my ajax looks like this:

  $.ajax({
       type:"POST" ,
       url: "someURL"
       dataType: "json"   ,
       contentType: "application/json; charset=utf-8",
       headers: headers,
       data: JSON.stringify(vmData)
    })

And my controller action

[HttpPost]
[ValidateJsonAntiforgeryToken]
public ActionResult MyPostController(IEnumerable<MyViewModel> vmData) { ... }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.