【问题标题】:Failing to pass data from view to the Action by Html.BeginForm()无法通过 Html.BeginForm() 将数据从视图传递到 Action
【发布时间】:2015-07-22 11:50:13
【问题描述】:

我是 asp.net mvc 的新手,所以我失败的原因也可能是一些基本的原因,但经过近一天的工作,我似乎无法找到它。

我要做的是从索引视图中获取已编辑的模型并将其传递给没有视图的第二个操作,并在相关控制器中返回 return RedirectToAction("Index")。在OrdersItemsController 我的操作如下:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult MarkedShipped(IEnumerable<orders_items> orderItems)
{
    if (ModelState.IsValid)
    {
        foreach (var item in orderItems)
        {
            unitOfWork.GenericRepository<orders_items>().Update(item);
        }
    }
    return RedirectToAction("Index");
}

在视图的 OrdersItems 文件夹中的 Index.cshtml 中,我所做的如下:

@model IEnumerable<Project.DataAccess.orders_items>
@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

@using (Html.BeginForm("MarkedShipped", "OrdersItems", new { orderItems = Model }))
{

    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <table class="table">
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.quantity)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.itemprice)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.trackingnumber)
            </th>
        </tr>

        @foreach (var item in Model)
        {
            <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>

        }
    </table>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="MarkShipped" class="btn btn-default" />
        </div>
    </div>
}

我的问题是,我无法使用 orderItems 参数从视图中获取模型,我不确定这是否是我想要完成的正确“语法”;但是当调用该操作时,orderItems 得到的是orders_items 的列表,其中Count = 0 不是空值。

我也检查了是否存在应用程序级别的异常,但在 Global.asax 中的 Application_Error 没有发现异常

我现在被困了一天,所以如果有人能指出如何将模型(或“编辑后的数据”)传递给我更新数据库的操作,我将不胜感激。谢谢。

【问题讨论】:

  • 将 FormMethod.Post 放入 BeginForm 参数中。
  • 您不能使用foreach 循环 - 它会生成重复的name 属性,而没有绑定到集合所需的索引器,并且重复的id 属性是无效的html。您需要使用for 循环(或自定义EditorTemplate 用于您的模型类型)。你的模型需要是IList&lt;T&gt;,然后是@for(int i = 0; i &lt; Model.Count; i++) { @Html.EditorFor(m =&gt; m[i].trackingnumber) ...}
  • 而且您不能将模型添加为路由参数 - 它是一个集合,这意味着绑定将失败(查看您生成的 html 以了解)。无论如何,添加原始模型作为路由参数有什么意义(您已经知道它在服务器中是什么)。
  • 我认为编辑后的模型是作为参数路由的,因为 EditorFor 助手直接与给定属性链接,我的理解是:它直接更改模型属性的项目。所以当传递模型时,我以为我传递了更新的集合。
  • @Neel 我也试过了,但没有任何区别。

标签: c# asp.net razor asp.net-mvc-5


【解决方案1】:

首先,您不能将作为集合的模型(或包含作为复杂对象或集合的属性的模型)添加到表单路由参数。助手在内部调用 .ToString() 方法,如果您检查为表单标签生成的 html,您将看到类似

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

并且绑定将失败,因为您的集合无法绑定到字符串。即使它确实有效,也将毫无意义,因为它只会回传模型的原始值。

接下来,您不能使用foreach 循环来生成表单控件。同样,如果您检查生成的 html,您将看到 EditorFor() 方法正在生成具有重复的 id 属性(无效的 html)和重复的 name 属性的输入,这些属性没有必要的索引器来绑定到集合邮政。您需要为 typeof orders_items 使用自定义 EditorTemplatefor 循环

使用for循环意味着你的模型必须实现IList&lt;T&gt;并且视图需要是

@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)
  }
  ....
}

使用EditorTemplate,在/Views/Shared/EditorTemplates/orders_items.cshtml 中创建一个partial(注意文件名必须与类名匹配)

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

然后在主视图中(可以使用IEnumerable&lt;T&gt;

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

EditorFor() 方法接受 IEnumerable&lt;T&gt; 并将根据 EditorTemplate 中的 html 为您集合中的每个项目生成一行

在这两种情况下,如果您检查 html,您现在将看到模型在发布时绑定所需的正确名称属性

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

【讨论】:

  • 非常感谢您的回答,我按照您的解释进行了实施,并且可以按预期完美运行。你一直很有帮助。谢谢!
【解决方案2】:

在这里尝试使用 For 而不是 foreach。

@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>
        }

检查这个:- http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

【讨论】:

  • 我实现了这个,我删除了 foreach 并添加了一个 for 循环,但这并不能帮助我将数据传递回控制器
【解决方案3】:

您可以执行以下操作

 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>

通过这种方式,每个 html 元素都有自己的唯一 ID,并且可以单独从它们那里检索信息。您可以使用 for 或 Foreach。只需确保您的剃刀迭代器正在运行。您可以查看源中的元素 id 以查看它是否正常工作。

【讨论】:

  • 您不能使用foreach 循环,html 助手将在for 循环内生成唯一的id 属性,因此覆盖它是没有意义的。在任何情况下,id 属性都与它无关 - 它的 namevalue 属性的值被发送回控制器
  • 我正在使用 razor 动态生成 html 块。如果您不强制指定 ID(就像我所做的那样),那么在控制器中查看模型时,您只会获得在第一个块中输入的值。
  • 你需要学习一些MVC的基础知识。正确的用法是根据我对问题的第一条评论 - 即@Html.EditorFor(m =&gt; m[i].trackingnumber)您的代码完全错误并且无法正常工作。
猜你喜欢
  • 1970-01-01
  • 2017-11-24
  • 2015-04-28
  • 1970-01-01
  • 2013-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-24
相关资源
最近更新 更多