【问题标题】:Form within a foreach loop not posting the model back to the controller在 foreach 循环中形成不将模型发布回控制器
【发布时间】:2016-09-13 17:32:51
【问题描述】:

我四处搜索,找不到问题的答案。

我有一个像这样接受Foo 的视图:

@model IEnumerable<MyApplication.Models.Foo>

在视图内部我有一张桌子。我填充表格只是通过我的Foo 模型执行一个简单的foreach 循环。我添加了一个列,用户可以在其中向文本区域中的每一行添加详细信息并保存。

所以视图看起来像这样:

@foreach (var item in Model)
  {
    <tr>
      <th>
           @using (Html.BeginForm("AddDetails", "MyController", FormMethod.Post))
             {
               @Html.AntiForgeryToken()        
               @Html.HiddenFor(u => item.Id)

               @Html.TextAreaFor(u => item.Details, new { @class = "form-control" })                              

               <input type="submit" value="Save" class="btn btn-sm btn-default" />
             }
      </th>
    </tr>
  }

我的控制器是这样设置的:

    [HttpPost]
    public ActionResult AddDetails(Foo foo)
    { 
    }

当我在该控制器上设置断点时,foo 始终具有 null 属性的 Details 值,并且 Id 始终是 0。当它被传递到视图中时,它的所有属性都设置为正确,所以我不确定为什么它没有正确回发?

我试过这个:

@using (Html.BeginForm("AddDetails", "MyController", FormMethod.Post, new { foo = Model }))

我还尝试删除foreach 循环并将其更改为仅将单个模型传递给视图,并且视图仅接受单个模型而不是IEnumerable。当我这样做时,它会很好地回发。

这也不起作用。我想知道这是否与我的表单位于 foreach 循环中这一事实有关,也许我需要做更多的工作,例如向元素添加 data-id 属性并捕获点击事件按钮并对控制器进行 AJAX 调用并传递正确的值?

编辑抱歉,我完全忘记了视图模型。看起来是这样的:

public class Foo
{
    public int Id { get; set; }

    public string Details { get; set; }
}

【问题讨论】:

  • 如果您分享更多关于您绑定到视图/在表单中使用的视图模型的信息,可能会有所帮助
  • 当您将foreach 更改为for 循环时会发生什么?我很确定这是您的问题,因为这样,默认的模型绑定器无法正确重建您要发布的对象。 See this question作为参考
  • @Jonesopolis 我现在将尝试将其更改为for 循环。我摆脱了foreach 循环只是为了测试它,当我摆脱它时它会很好地回发。尝试后我会更新另一条评论。
  • 查看你生成的html。 name 属性是 name="item.Details",而您的 Foo 模型没有名为 item 的属性。虽然有一些技巧可以解决这个问题,但您的观点毫无意义,并且是一种令人困惑的用户体验(并且肯定会失去您的客户) - 您生成多个表单,但您只能提交一个表单。
  • 使用for 循环或自定义EditorTemplate(参考this answer)但在一个&lt;form&gt; 元素内并将方法更改为`public ActionResult AddDetails(List model) 以便所有更改都在一个操作中提交。

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


【解决方案1】:

一般来说,将表单发布到与表单视图组成不同的模型是不好的。它使很多事情变得困难,其中最重要的是从验证错误中恢复。

您在这里所做的是循环遍历Foo 的列表并创建多个表单,每个表单将只提交一个Foo 到一个只需要一个Foo 的操作。虽然帖子本身很好,但在与您发布的模型不同的模型上使用 *For 助手可能不会生成模型绑定器将发布的值绑定到其他模型所需的正确输入名称。至少,如果您因为验证错误需要返回此视图,您将无法保留用户发布的数据,从而迫使他们完全重复他们的努力。

理想情况下,您应该发布Foo 的整个列表,并且只使用一个包含迭代的表单(在这种情况下,您需要使用for 而不是foreach)。或者,您应该简单地列出 Foos 并附上一个链接以编辑特定的 Foo,在其中您将有一个只有一个 Foo 的表单。

【讨论】:

    【解决方案2】:

    尝试这样做。可能的问题

    表格应该在表格之外 整个表格的单一表格

    将您的列编辑器包装在 tbody 而不是 thead

    @using (Html.BeginForm("AddDetails", "MyController", FormMethod.Post))
    {
    //thead and tbody
        }
    

    【讨论】:

    • 对不起,我需要把它放在里面,这样行就有表格了。
    • 每一行都有一列可编辑,对吧?
    猜你喜欢
    • 1970-01-01
    • 2018-01-06
    • 1970-01-01
    • 1970-01-01
    • 2014-08-08
    • 1970-01-01
    • 2013-10-09
    • 1970-01-01
    • 2014-01-25
    相关资源
    最近更新 更多