【问题标题】:ASP.Net MVC3 Model Binding IEnumerable<T> with Editor Template [duplicate]ASP.Net MVC3 模型绑定 IEnumerable<T> 与编辑器模板 [重复]
【发布时间】:2011-10-20 05:31:52
【问题描述】:

所有,请澄清我对模型绑定如何与 IEnumerables 和编辑器模板一起使用的困惑。

我有一个看法,Approve.cshtml

@model IEnumerable<MvcWebsite.Models.Approve>
<table>
    <tr>
        <th>
            Name
        </th>
    </tr>
    @Html.EditorForModel()
</table>

模型,Approve.cs

public class Approve
{
  public string Name { get;set;}
  public string Role { get; set; }
}

还有一个编辑器模板

@model MvcWebsite.Models.Approve

@using (Html.BeginForm("Approve", "Registration", FormMethod.Post))
{
<tr>
    <td>
        @Html.HiddenFor(m => m.Name)
        @Html.EditorFor(m => m.Role)
    </td>
    <td>
        <input type="submit" value="Approve" class="submit-button" />            
    </td>
</tr>

}

这一切都很好。它呈现以下输出。

        <input name="[0].Name" type="hidden" value="" />
        ....

但是,在我的控制器中,我似乎无法接收模型返回的值(绑定)。

[HttpPost]
public ActionResult Approve(Approve approveModel)
{
    .... approveModel has all default values
}

有人可以阐明我在这里做错了什么吗?我缩写了代码,我将编辑器模板与模型中的其他 EditorFor 和 HiddenFor 字段一起使用...

已编辑:我基本上有一个表格布局,每个都有用户名,一个文本框,我可以在其中输入他们的角色(用户或管理员),然后是一个提交给我的控制器的批准按钮。因此,我只想返回一个 Approve 对象。我可以将整个 IEnumerable 返回给我的 Controller,但如果这样做,我如何知道哪些项目是我单击“批准”按钮(提交)的项目?

编辑: 所以我修改了代码,以便我有一个围绕整个 View Approve.cshtml 的表单

@model IEnumerable<MvcWebsite.Models.Approve>
@using (Html.BeginForm("Approve", "Program", FormMethod.Post))
{
<table>
    <tr>
        <th>
            Name
        </th>
    </tr>
    @Html.EditorForModel()
</table>
}

然后把控制器改成

[HttpPost]
public ActionResult Approve(IEnumerable<Approve> approvals)
{
    // ???????????????????????
}

现在我仍然不清楚如何知道我为哪一行点击了批准。我知道还有其他方法可以完成此任务(为批准创建一个复选框,并批准任何已检查的内容等)但是,我需要能够单击一个按钮并且只将 1 行保存回数据库,无论用户是否输入信息到其他行。将我的 IEnumerable 包装在它自己的模型(即 AllApprovals)中,然后将辅助属性添加到该父模型(SelectedIndex 等)是更好的做法吗?如果这是要采取的方法,那么在单击“批准”按钮后如何设置 SelectedIndex?那仍然是 jquery 魔术还是有正确的 MVC 方法来实现这一点? Jquery 魔法对我来说似乎很 hackish?

编辑:根据 Brian 的回复,这是我的最终结果。仍然感觉不太对劲,但它确实有效!

查看

@model IEnumerable<MvcWebsite.Models.Approve>
<table>
    <tr>
        <th>
            Name
        </th>
    </tr>
    @Html.EditorForModel()
</table>

编辑器模板

@using (Html.BeginForm("Approve", "Registration", FormMethod.Post))
{
<tr>
    <td>
        @Html.HiddenFor(m => m.Name)
        @Html.EditorFor(m => m.Role)
    </td>
    <td>
        <input type="submit" value="Approve" class="submit-button" />            
    </td>
</tr>
}

控制器

[HttpPost]
public ActionResult Approve([Bind(Prefix="approval")]Approve approval)    {
    // WORKS!
}

【问题讨论】:

    标签: c# asp.net-mvc-3 binding model controller


    【解决方案1】:

    由于您一次只更改一个,我认为以下操作比尝试在控制器中找出更改了哪些值,或者添加更改的属性并通过 javascript 设置它更容易。

    将 Approve.cshtml 更改为

    @model IEnumerable<MvcWebsite.Models.Approve> 
    <table> 
        <tr> 
            <th colspan=2> 
                Name 
            </th> 
        </tr> 
    @foreach(var user in Model){
        @using (Html.BeginForm("Approve", "Registration", FormMethod.Post))         { 
        <tr> 
            <td> 
                @Html.EditorFor(m => user) 
            </td> 
            <td> 
                <input type="submit" value="Approve" class="submit-button" />             
            </td> 
        </tr> 
        }
    }
    </table> 
    

    Approve编辑器模板更改为

    @Html.HiddenFor(m => m.Name) 
    @Html.EditorFor(m => m.Role) 
    

    【讨论】:

    • 我将此标记为正确答案,因为它有效。但是,这是执行此操作的“正确”方式吗?我在其他地方读到,如果您在视图中使用 Foreach,那么您做错了什么。此外,我需要在我的控制器中使用绑定前缀才能工作 [Bind(Prefix = "approval")]
    • 目前看来它适合您。一年后,您回来查看代码,对您正在构建的系统有更多的经验和知识,并认为“我在想什么”。担心它是否“正确”是件好事,但把事情做好也是件好事。与所有事情一样,适度是关键。
    • 偶然发现了这个问题,但上面的内容是不正确的,因为它会产生无效的标记——将表单元素放在除了 (或 th 等)之外的表格中的任何位置都是无效的。它可能“工作”,但它是 hacky。
    【解决方案2】:

    您正在绑定到单个 Approve 类,您应该绑定到 IEnumerable&lt;Approve&gt;

    【讨论】:

    • 跟进,如果我绑定到 IEnumerable,我如何知道哪些表单已发布?我基本上用它自己的形式包装了每个 Approve (EditorTemplate)。在该表单中,我有一个 EditorFor 字段,我在其中输入一个值(用户或管理员),然后将每个单独的行作为它自己的 Approve 模型提交回控制器。我猜有更好的方法来做我想做的事情..
    • 您不需要每行一个新表单,只需在名为 id 的批准模型上创建一个属性并使用 @Html.Hidden 来呈现它。这样你就可以计算出批准模型修改和新值之间的映射
    【解决方案3】:

    Martin 是正确的,我只是想添加更多信息。您使用 [0] 呈现的 HTML 是模型绑定器查看的特殊语法,并假设您正在使用列表 if 对象。由于您的操作方法只有一个 Approve 类而不是 kist,因此您遇到了这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-03
      • 2011-09-27
      • 1970-01-01
      相关资源
      最近更新 更多