0

I've seen many posts on SO considering this topic, though applying solutions didn't work for me and I am confused right now. Mb I'm missing sth?

Please consider I'm a noob at .js stuff.

So I get my values from dynamicly created form elements with this JS and attempt to post it:

EDIT 12:21: I got this script which should parse each element from form into custom made array resembling json. I still get null reference though. Got any idea how to get it?

 var getValues = function (myForm) {
 var array = [];
 var parser;
 $("formElement").each( function (i, elem) {
 parser.empty()
 parser = {
 Id: $(elem,"#Id ").val(),
 someOption: $(elem, "#someOption ").val(),
 someText: $(elem, "#someText ").val(),
 someNumber: $(elem, "#someNumber ").val()
 }
 array.push(parser);
 });
 console.log(array);
 $.ajax({
 type: "POST",
 url: 'angus',
 traditional: true,
 data: {json: array },
 success: function (data) {
 $("#getData").empty();
 $("#getData").append(array);
 }
 }); 
 };

I get this in log: (objects of index like i,i+1,i+2,i+3 match the viewmodels - is it right? and I have mixed feelings about those proto and functions - what is it?) enter image description here

In my controller action I get null exception:

 [HttpPost]
 public ActionResult angus(IEnumerable<TrashViewModel> json)
 {
 return View(json.ToList());
 }

I created my viewmodel:

 [Serializable]
public class TrashViewModel
{
 public int Id { get; set; }
 public string someOption { get; set; }
 public string someText { get; set; }
 public string someNumber { get; set; }
}

I had my forms HTML attributes names match those of viemodel class.

EDIT: html:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="formExample" ng-controller="ExampleController">
 <button class="btn btn-primary" ng-controller="addRow" ng-click="addLine()">Dodaj przycisk</button>
 <form novalidate class="simple-form">
 <div class="here">
 <div class="formElement row">
 <input type="hidden" name="Id" value="1"/>
 <div class="col-md-2">
 <select name="someOption" class="optns form-group col-md-12" ng-model="user.class">
 <option selected value="1"> Rodzaj... </option>
 <option value="test">2</option>
 <option value="2">test</option>
 <option value="2">2</option>
 <option value="3">3</option>
 @*tutaj beda dodane opcje*@
 </select>
 </div>
 <div class="col-md-1">
 <input name="someNumber" class="form-group col-md-12" type="number" ng-model="user.number" value="" text="Ilość..." /><br />
 </div>
 <div class="col-md-9">
 <input name="someText" class="form-group col-md-12" type="text" ng-model="user.text" value="" text="Uwagi..." /><br />
 </div>
 </div>
 </div>
 <input type="button" value="Reset" />
 <input type="submit" value="Save" />
 </form>
</div>

appended html:

 var strVar = "";
 strVar += "<div class=\"formElement row\">";
 strVar += " <input type=\"hidden\" name=\"Id\" value=\" "+ $scope.counter +"\"\/>";
 strVar += " <div class=\"col-md-2\">";
 strVar += " <select name=\"someOption\" class=\"optns form-group col-md-12\" ng-model=\"user.class\">";
 strVar += " <option selected value=\"1\"> Rodzaj... <\/option>";
 strVar += " <option value=\"test\">2<\/option>";
 strVar += " <option value=\"2\">test<\/option>";
 strVar += " <option value=\"2\">2<\/option>";
 strVar += " <option value=\"3\">3<\/option>";
 strVar += " @*tutaj beda dodane opcje*@";
 strVar += " <\/select>";
 strVar += " <\/div>";
 strVar += " <div class=\"col-md-1\">";
 strVar += " <input name=\"someNumber\" class=\"form-group col-md-12\" type=\"number\" ng-model=\"user.number\" value=\"\" text=\"Ilość...\" \/><br \/>";
 strVar += " <\/div>";
 strVar += " <div class=\"col-md-9\">";
 strVar += " <input name=\"someText\" class=\"form-group col-md-12\" type=\"text\" ng-model=\"user.text\" value=\"\" text=\"Uwagi...\" \/><br \/>";
 strVar += " <\/div>";
 strVar += " <\/div>";

I end up with null exception which by what other posts suggest is because of viemodel class doesn't match the serialized objects. Don't know what to do at this point.

Thank you!

asked Sep 1, 2016 at 7:17
6
  • Your need to show the html your generating. Show some typical name attributes - are they correctly indexed? Commented Sep 1, 2016 at 7:20
  • @StephenMuecke added it to the post, thx for consideration Commented Sep 1, 2016 at 7:37
  • 1
    If your dynamically adding multiple items with duplicate name attributes, then using serializeArray() (or serialize()) is simply not going to work. You could generate the correct name attributes with indexers as per this examplein which case its simply data: form.serialize(), and remove traditional: true, Commented Sep 1, 2016 at 8:53
  • 1
    The alternative is to manually generate an array of objects by looping through each <div class="row"> - it would need to look like [{ Id: 1, someOption: 'xxx', ... }, { Id: 2, someOption: 'yyy', ... }, ... ] and then JSON.stringify() it and set contentType: 'json', Commented Sep 1, 2016 at 8:57
  • thx @StephenMuecke will try it out :) Commented Sep 1, 2016 at 9:07

4 Answers 4

1

In order to POST your array, you need to stringify the data and set the contentType option. You ajax code needs to be

$.ajax({
 type: 'POST',
 url: '@Url.Action("angus")', // do not hard code url's
 contentType: "application/json; charset=utf-8",
 data: JSON.stringify({ model: array }), 
 success: function (data) {

and the controller

[HttpPost]
public ActionResult angus(IEnumerable<TrashViewModel> model)
answered Sep 5, 2016 at 8:19

Comments

1

try replacing

 var parsed = $(myForm).serializeArray();

with

 var parameters = {
 Id : $("#Id ").val(),
 someOption : $("#someOption ").val(),
 someText : $("#someText ").val(),
 someNumber : $("#someNumber ").val()
 };

then pass it to the submit

JSON.stringify(parameters)
answered Sep 1, 2016 at 8:41

1 Comment

it does the job for single element, now I'm changing it for array since that's the whole point - if it works will sure mark as answer :) thx
1

in your JavaScript code, 3 things jump out at me:

  1. you're using .serializeArray(), which creates an array of objects each with a name and value property. this does not match the structure of your TrashViewModel object
  2. you're wrapping the serialized object inside a new object with a single property called "json", which adds more structure to your data
  3. you're stringifying said object

all of that is unnecessary, since the .ajax() method will package the data in the correct format for you. you simply need to pass the serialized form as the data parameter.

data: $(myform).serialize()

on the controller, you should just set the parameter on the action to be your TrashViewModel object. please note that it's a single object, not an enumerable.

public ActionResult Angus(TrashViewModel form)
{
 // do something
}

if you were to use .serializeArray(), then you'd need to create a model object with Name and Value properties so that the model binder can properly resolve the params.

// JavaScript 
data: $(myform).serializeArray()
// Controller
public class NameValueModel
{
 public string Name { get; set; }
 public string Value { get; set; }
}
public ActionResult Angus(NameValueModel[] form)
{
 // do something
}
answered Sep 1, 2016 at 8:48

1 Comment

my thoughts exactly though I'm not yet comprehending all the stuff around json, thanks for this, will try it out
0

I'm not 100% happy about outcome, because I still have to parse json string at the end on server side. I think I'll soon do Q&A, so others won't have to fight a week to do sth like this. Thanks to:

  • @StephenMuecke
  • @Emil
  • @Jeff M

So actually what I did:

js to get inputs and push it custom style then do post ajax request:

 var array = [];
 var parser;
 $(".formElement").each( function (i, elem) {
 //parser.empty()
 parser = {
 Id: $("#Id", $(this)).val(),
 someOption: $("#someOption", $(this)).val(),
 someText: $("#someText", $(this)).val(),
 someNumber: $("#someNumber", $(this)).val()
 };
 console.log(parser);
 array.push(parser);
 });
 console.log(array);
 $.ajax({
 type: "POST",
 url: 'angus',
 traditional: true,
 data: { json: JSON.stringify(array) },
 success: function (data) {
 $("#getData").empty();
 $("#getData").append(array);
 }
 });

controller: (don't mind the logic, because it's useless here except it gave info during debugging)

the most important thing was to give string type as parameter; I'm 100% sure that my json bounced off of the complex type viewmodel

 [HttpPost]
 public ActionResult angus(string json)
 {
 var check = json.ToString() == null;
 return RedirectToAction("ErrorAction");
 }
answered Sep 1, 2016 at 11:09

6 Comments

You DO NOT have to parse the parameter. Change string json to IEnumerable<TrashViewModel> model then modify the ajax as per my previous comments - delete traditional: true, add contentType: 'json' and change it to data: JSON.stringify({ model: array })
@StephenMuecke tried both stringify and serialization you mentioned - still get null results $.ajax({ type: "POST", url: 'angus', contentType: 'json', //data: JSON.stringify({ json: array }), data: $(myForm).serialize(), success: function (data) { $("#getData").empty(); $("#getData").append("Sukces!"); $("#getData").addClass(); } });
Sorry, that needed to be contentType: "application/json; charset=utf-8", (and have tested and works fine). But you have invalid html (duplicate id attributes) so you would be posting back duplicate values of the controls in the first formElement - you need to use class names
@StephenMuecke mother of god... it works! will edit top and give upvote with answer :o btw if you'd like to do the honors just post the answer for this, I can't stress enough how you have helped me :) and you deserve 100% of it
@StephenMuecke I meant your answer (though it could've been unclear at 1st) :)
|

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.