2011-10-20 86 views
2

所有,请清除了我的困惑是如何模型结合与IEnumerables和编辑模板的作品。ASP.Net MVC3模型绑定的IEnumerable <T>与编辑模板

我有一个观点,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回到我的控制器,但如果我这样做,我怎么能知道哪个项目是一个我点击批准按钮(提交)呢?

编辑: 所以我已经修改了代码,使我有我的周围整个视图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排回保存到数据库的能力,无论如果用户输入信息放入其他行。它是更好的做法来包装它自己的模型(即AllApprovals)我的IEnumerable内,然后辅助属性添加到父模型(SelectedIndex的,等等)?如果这是要采取的方法,那么在点击批准按钮后,如何设置SelectedIndex?这仍然是jQuery魔术还是有一个正确的MVC方式来实现这一点? jquery的魔法对我来说似乎很ha??

编辑:基于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! 
} 

回答

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) 
+1

之间的映射。我将其标记为正确答案,因为它工作正常。然而,这是做到这一点的“正确”方式吗?我在其他地方读过,如果你在视图中使用了Foreach,那么你做错了什么。此外,我需要在我的控制器中使用绑定前缀来工作[绑定(前缀=“批准”)] – firetoast

+1

这听起来像是适合你,现在。你从现在开始回过头来看看代码,提供更多关于你正在构建的系统的经验和知识,并认为“wtf是我的想法”。不用担心它是否是“正确的”,但是完成任务也很好。正如所有事情一样,适度是关键。 –

+0

偶然发现了这个问题,但是上面的内容并不正确,因为它会产生无效的标记 - 除了​​(或th等),在表格中的任何位置放置表单元素都是无效的。它可能“工作”,但它很冒险。 – smdrager

0

你绑定到单独审批类,你应该绑定到IEnumerable<Approve>

+0

跟进,如果我绑定到了IEnumerable ,我怎么能知道哪些的形式发布?我本质上是用它自己的形式来包装每个Approve(EditorTemplate)。在该表单中,我有一个EditorFor字段,在其中输入一个值(用户或管理员),然后将每个行作为自己的Approve模型提交给控制器。我猜测有更好的方法来做我想做的事.. – firetoast

+0

你不需要每行一个新的表单,只需在批准的模型上创建一个名为id的属性并使用@ Html.Hidden来渲染它。通过这种方式,您可以计算批准修改模型和新值 –

0

马丁是正确的我只是想添加更多的信息。您使用[0]呈现的HTML是模型联编程序查看的特殊语法,并且假定您正在使用列表(如果有对象)。由于您的操作方法只有一个Approve类而不是kist,因此您遇到此问题。