0

I have a form with data listed in a table structure

@model IEnumerable<myType>
@Html.AntiForgeryToken()
@using (Ajax.BeginForm("Save", "NOC", null, ajaxopts, new { @encType = "multipart/form-data", @id = "myform", @name = "myform" }))
{

<table>
<tr>
<td><input type="hidden" name="myType[0].ID" id="myType[0].ID" value="16" /></td>
<td><input type="text" name="myType[0].Name" id="myType[0].Name" value="Jim" /></td>
<td><input type="checkbox" name="myType[0].Selected" id="myType[0].Selected" checked /></td>
</tr>
<tr>
<td><input type="hidden" name="myType[1].ID" id="myType[1].ID" value="17" /></td>
<td><input type="text" name="myType[1].Name" id="myType[1].Name" value="Bob" /></td>
<td><input type="checkbox" name="myType[1].Selected" id="myType[1].Selected" /></td>
</tr>
</table>
<button id="process" value="Save" class="btn btn-primary">Save</button>
}

In Chrome I can see that in the Form Data section the list of data being posted to the controller....

myType[0].ID: 16
myType[0].Name: Jim
myType[0].Selected: on
myType[1].ID: 17
myType[1].Name: Bob

but in the controller I get null

[HttpPost]
public async Task<ActionResult> SaveData(IEnumerable<myType> model)
{
  return Json("Hi");
} 

Also if I look in the preview on Chrome Dev Tools I see "Hi" in the Preview returned from the Controller.

My Javascript looks like this

$("#process").on("click", function (event){
  event.preventDefault();
  var formData = $("#myForm").serialize();
  $.ajax({
    url: url,
    type: "POST",
    data: formData
  })
});

model is

public class myType
{
  public int ID { get; set; }
  public string Name { get; set; }
  public bool Selected { get; set; }
}

There are no javascript errors showing, just no data to the controller?

any help would be hugely appreciated.

Thanks

Jason Coley
  • 125
  • 9
  • Are you seriously generating manual html like that? First you need to show your model (and if property `Selected` is typeof `bool` it will never bind anyway). And your script function will never be called anyway - it would need to be `$("#process")....` And the `Ajax.BeginForm` will not post to the method you have shown anyway - you specify the action as `"Save_NOCList"` but the method you have shown is `SaveData` –  Jul 23 '15 at 23:36
  • well I cut out superfluous code and yes missed some things from copying some stuff from my actual page, and thx for pointing out the missing model, still any ideas as to why this doesn't work? – Jason Coley Jul 24 '15 at 00:08
  • 1
    Your edits still contain typos - your script is pointless - you have `Ajax.BeginForm()` which is making an ajax post and in any case it does not work since you dont have a form with `id="myForm"` (its `id="nocform"`) and your now posting back to method `Save()` which does not exist (its `SaveData()`). But the real issue is your manually generating html which has no relationship to your model. –  Jul 24 '15 at 00:12
  • Do this correctly using strongly typed html helpers and you will see how the `name` attributes really need to be in order to bind to your model. –  Jul 24 '15 at 00:14
  • OK thx I will try that now, the table is generated from a javascript function, as it is created into a popup from a table in the main view. This is my first attempt at using MVC, AJAX and JQuery, so thank you for your help – Jason Coley Jul 24 '15 at 00:18
  • 1
    Hint - `IEnumerable` does not contain a property named `myType` which is a collection of complex objects containing properties `ID`, `Name` and `Selected` - the name attributes need to be `name=[0].ID`, name="[0].Name"` etc. But that's only one of the multiple problems you have with the html your generating. I suggest you post your javascript function for adding a new row since its clearly wrong. –  Jul 24 '15 at 00:29
  • removing the myType before the names/ids fixed the issue – Jason Coley Jul 24 '15 at 00:43
  • I'll add an answer shortly explaining this and some other issues that you have. –  Jul 24 '15 at 00:44
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/84126/discussion-between-jason-coley-and-stephen-muecke). – Jason Coley Jul 24 '15 at 00:44

1 Answers1

0

Your manually generating html that have name attributes which do not relate to your model. In order to post back to IEnumerable<myType> model your elements need to be

<input type="hidden" name="[0].ID />
<input type="hidden" name="[1].ID />

etc. Your should also remove the id attributes since these are invalid and any jquery function that attempts to use them would fail (for example the . (dot) will be interpreted as a class identifier).

Note also that your use of checkbox will not work since a value of on will not bind to a boolean value.

Based on your comments, your generating this html using a javascript function to dynamically add new elements. If so, I suggest your review this answer. Your should also populate your initial model with some objects and use a for loop to generate the correct html (make the model IList<myType>)

for(int i = 0; i < Model.Count; i++)
{
  @Html.HiddenFor(m => m.ID)
  @Html.TextBoxFor(m => m.Name)
  @Html.CheckBoxFor(m => m.Selected)
}

and then inspect the html it generates.

Community
  • 1
  • 1