ASP.Net MVC从复选框列表返回值

时间:2011-01-19 04:38:54

标签: asp.net-mvc

我有一个带有List属性的模型。 MyObjects只有一个id,一个描述和一个选定的布尔属性。

我已设法在我的视图中将项目显示为复选框。我这样做是通过:

 <%foreach (var cat in Model.DefaultCategories)
      {%>
    <tr>
        <td>
        <%=cat.Category %>

        </td>
        <td>
           <%=Html.CheckBoxFor(x=>cat.Selected) %>
        </td>
    </tr>
    <%
        }%>
</table>

然而,有一个问题。当渲染时,它们都以相同的名称结束。这是我列表的一部分:

        <tr>
        <td>
        Medical

        </td>
        <td>
           <input id="cat_Selected" name="cat.Selected" type="checkbox" value="true" /><input name="cat.Selected" type="hidden" value="false" />
        </td>

    </tr>

    <tr>
        <td>
        Salary

        </td>
        <td>
           <input checked="checked" id="cat_Selected" name="cat.Selected" type="checkbox" value="true" /><input name="cat.Selected" type="hidden" value="false" />
        </td>
    </tr>

他们都被命名为“cat.Selected”。

我该如何解决这个问题?

然后,当我提交时,我需要迭代它们。使用不同的名称,我假设我可以使用我的HttpPost方法获取它们:

        [HttpPost]
    public ActionResult Modify(int id, FormCollection formValues)
    {
        PayeeDto p = new PayeeDto { Name = Request.Form["name"], PayeeId = id };

        Services.PayeeServices.Save(p);
        return RedirectToAction("Index");
    }

FormCollection会有不同的名字吗?目前,它只有一个'cat.selected'项目。

3 个答案:

答案 0 :(得分:3)

有一种方法可以使用[]的名称为您的操作提交集合。如此处所述http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

<% for (int i = 0; i < Model.DefaultCategories.Count; i++) { %>
<td>
   <input type="checkbox" name="[<%= i %>].Selected" <% Model.DefaultCategories[i].Selected ? "checked=\"checked\"" : string.Empty %>/>
</td>
<% }%>

然后你的行动可以采取像这样的模型集合

public ActionResult Modify(int id, ICollection<UpdateModel> updates)
{}

答案 1 :(得分:2)

我建议您使用编辑器模板并停止在视图中编写循环。他们将负责生成正确的名称,以便绑定工作。例如:

在主视图中:

<table>
    <thead>
        <tr>
            <th>Name</th>
            <th>Selected</th>
        </tr>
    </thead>
    <tbody>
        <%: Html.EditorFor(x => x.DefaultCategories) %>
    </tbody>
</table>

然后在强烈键入类别(~/Views/Home/EditorTemplates/Category.ascx)的编辑器模板中。此外,如果您想在控制器操作中获取相应的名称,则需要将其包含在内(可能是隐藏字段)。另一种技术涉及只添加id,然后在控制器操作中从数据库中获取相关信息:

<%@ Control 
    Language="C#" 
    Inherits="System.Web.Mvc.ViewUserControl<AppName.Models.Category>" %>

<tr>
    <td><%: Model.Name %></td>
    <td>
        <!-- include the category name as hidden field so that 
             we can fetch it back in the controller action
        -->
        <%: Html.HiddenFor(x => x.Name) %>
        <%: Html.CheckBoxListFor(x => x.Selected) %>
    </td>
</tr>

现在命名约定在这里很重要。如果视图模型上的DefaultCategories属性是IEnumerable<Category>,那么编辑器模板需要被称为Category.ascx并放在~/Views/Home/EditorTemplates/Category.ascx中,或者它是否会在~/Views/Shared/EditorTemplates/Category.ascx中的多个控制器之间重用

您提交的控制器操作也应使用视图模型作为参数:

[HttpPost]
public ActionResult Modify(MyViewModel model)
{
    PayeeDto = Mapper.Map<MyViewModel, PayeeDto>(model);
    Services.PayeeServices.Save(p);
    return RedirectToAction("Index");
}

答案 2 :(得分:1)

这可能不是最佳答案,但我尽量不在MVC中使用生成的复选框。

我会改变

<td>
   <%=Html.CheckBoxFor(x=>cat.Selected) %>
</td>

<td>
   <input type="checkbox" name="<%: cat.value %>" id="<%: cat.value %>" <% cat.Selected ? " checked=\"checked\" " : ""; %> />
</td>