Failing to pass data from view to the Action by Html.BeginForm()

别等时光非礼了梦想. 提交于 2019-12-02 03:10:48

Firstly you cannot add a model which is a collection (or a model which contains a property which is a complex object or collection) to a forms route parameters. Internally the helper calls the .ToString() method and if you inspect the html generated for your form tag you will see something like

<form action=OrdersItems/MarkedShipped?orderItems=System.Collection.Generic.......

and binding will fail since you collection cannot be bound to a string. Even if it did work, it would be rather pointless because it would just post back the original values of the model.

Next, you cannot use a foreach loop to generate form controls. Again if you inspect the html your generating you will see that the EditorFor() method is generating inputs with duplicate id attributes (invalid html) and duplicate name attributes which do not have the necessary indexers to bind to a collection when you post. You need to use either a for loop of a custom EditorTemplate for typeof orders_items

Using a for loop means that your model must implement IList<T> and the view needs to be

@model IList<Hochanda.CraftsHobbiesAndArts.DataAccess.orders_items>
@using (Html.BeginForm()) // only necessary to add the controller and action if they differ from the GET method
{
  ....
  @for(int i = 0; i < Model.Count; i++)
  {
    @Html.DisplayFor(m => m[i].quantity)
    ....
    @Html.EditorFor(m => m[i].trackingnumber)
  }
  ....
}

Using an EditorTemplate, create a partial in /Views/Shared/EditorTemplates/orders_items.cshtml (note the name of the file must match the name of the class)

@model Hochanda.CraftsHobbiesAndArts.DataAccess.orders_items
<tr>
  <td>@Html.DisplayFor(m => m.quantity)</td>
  ....
  <td>@Html.EditorFor(m => m.trackingnumber)</td>
  ....
</tr>

and then in the main view (you can use IEnumerable<T>)

@model IEnumerable<Hochanda.CraftsHobbiesAndArts.DataAccess.orders_items>
@using (Html.BeginForm())
{
  <table class="table">
    <thead>
      ....
    <thead>
    <tbody>
      @Html.EditorFor(m => m)
    </tbody>
  </table>
  ....
}

The EditorFor() method accepts IEnumerable<T> and will generate one row for each item in you collection based on the html in the EditorTemplate

In both cases, it you inspect the html you will now see the correct name attributes necessary for you model to bind when you post

<input type="text" name="[0].trackingnumber" ... />
<input type="text" name="[1].trackingnumber" ... />
<input type="text" name="[3].trackingnumber" ... />

Try For instead of foreach here.

@for (int i = 0; i < Model.Count; i++)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.quantity)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.itemprice)
                </td>
                <td>
                    @Html.EditorFor(modelItem => item.trackingnumber)
                </td>
                <td>
                    @Html.ActionLink("Edit", "Edit", new { id = item.itemid })
                </td>
            </tr>
        }

Check this :- http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

You can do the following

 for (int i = 0; i < @ViewBag.Persons; i++)
  {

    <li>
        <table>

            <tr>
                <td>
                    @Html.LabelFor(m => m.Fullname,new { @id = "FullnameLabel" + @i })
                </td>
                <td>
                    @Html.TextBoxFor(m => m.Fullname, new { @id = "Fullname" + @i })
                </td>

            </tr>

In this way each html element gets its own unique id and its possible to retrieve the information back from them individually. You can use for or Foreach. Just make sure that your razor iterator is functioning. You can view the element ids in the source to see if it is working.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!