在 MVC/Razor 中,如何获取多个复选框的值并将它们全部传递给控制器​​?

Posted

技术标签:

【中文标题】在 MVC/Razor 中,如何获取多个复选框的值并将它们全部传递给控制器​​?【英文标题】:In MVC/Razor, how do I get the values of multiple checkboxes and pass them all to the controller? 【发布时间】:2015-07-23 20:12:58 【问题描述】:

我有一个包含模型项目列表的视图。我需要为每一行添加一个复选框,让用户选择多个复选框,并将选择的行的一些标识符传递给控制器​​。我知道如何通过操作链接传递单个值,但我不确定如何通过操作链接传递多个值或如何“收集”选择了哪些行。我将在下面展示我的一些代码尝试。有人可以帮我弄清楚为什么我无法获取传递给控制器​​的所有复选框的值吗?

这是我的页面

Checkbox     App ID     Date     Name
   []          1        5/10     Bob
   []          2        5/10     Ted
   []          3        5/11     Alice

我需要用户做的是选择第 1 行和第 3 行(例如)并将这些 App ID 传递给控制器​​。

我开始列出各种尝试,但决定只展示我当前的尝试,看看是否有人能指出我做错了什么。我看到的在线示例和我的示例之间的主要区别是我使用 PagedList 并在 foreach 循环中创建表的行。

当它到达控制器时,参数 ints 是空白的。如何从复选框中获取值?我使用此站点的基本思想是,将所有复选框命名为相同并通过操作链接传递 ICollection: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

查看:

@model PagedList.IPagedList<CarmelFinancialWeb.Models.ModelMerchantSummary>
<div class="block" style="width: 100%; float: left">
<p class="block-heading"> 
Merchant Application Report
</p>
<div class="table-holder">
    <table class="table" style="margin-bottom: 0px">
            <tbody>
                @foreach (var item in Model)
                
                    <tr>
                        <td>
                            <input type="checkbox" name="ints" value=item.ApplicationID />
                        </td>
                    <td>
                        @html.ActionLink(item.ApplicationID.ToString(), "ViewApplication", new  ID = item.ApplicationID, edit = 1 , new AjaxOptions  HttpMethod = "GET" )
                    </td>
                    <td>
                        @Convert.ToDateTime(item.ApplicationDate).ToString("M/d/yy")
                    </td>
                    <td>
                        @item.ApplicantName
                    </td>
        </tbody>
    </table>
</div>
</div>
@Html.ActionLink("Print Application", "PrintApplication", "CreateContract", new  @class = "btn btn-primary" )

控制器:

    [AuthorizeAdmin]
    public ActionResult PrintApplication(ICollection<int> ints, string ID)
    
        Contracts_Create contract = new Contracts_Create();
        ModelApplication currentApplication = new ModelApplication();
        currentApplication.contract = new ModelContract();
        return File(contract.CreatePDF_PrintedApplication_English(currentApplication.contract.location, currentApplication.contract), "application/pdf");
    

编辑: 这被标记为另一个问题的副本。问题在于是否可以使用非顺序输入名称。我的问题是我使用的输入不是非顺序的,但它仍然不起作用。我理解这个概念,我只是无法弄清楚为什么我的特定代码不起作用。我已经为此投入了大量时间,但找不到我的特定代码的答案。谢谢!

【问题讨论】:

How does MVC 4 List Model Binding work?的可能重复 您是否尝试过将 PrintApplication 操作方法签名上的 ICollection 更改为 string[] 并查看是否可行?如果您绑定到数组或集合,我相信它必须是顺序的。 @br4d.net 尝试了 string [] ,我得到了同样的结果;整数为空。感谢您的建议。 我没有在您的视图中看到表单(并且缺少 )。你是在做 GET 还是 POST? ModelMerchantSummary 是数据库实体还是 ViewModel? 这是部分视图。该视图实际上很长(表中有很多列),因此我将其缩短以将其发布在这里;可能丢失的 来自哪里。没有 GET 或 POST;只是一个动作链接。 ModelMerchantSummary 是一个 ViewModel。 【参考方案1】:

尝试将 ViewModel 传递到您的页面,并使用模型绑定器将相同的视图模型发布回您的控制器

型号:

public class MerchantModel

    public int AppId  get; set; 
    public string Name  get; set; 
    public bool IsSelected  get; set; 


public class MerchantViewModel

    public List<MerchantModel> Merchants  get; set; 

控制器:

public class DefaultController : Controller

    // GET: Default
    public ActionResult Index()
    
        var merchant1 = new MerchantModel
        
            AppId = 1,
            Name = "Bob"
        ;
        var merchant2 = new MerchantModel
        
            AppId = 2,
            Name = "Ted"
        ;
        var merchant3 = new MerchantModel
        
            AppId = 3,
            Name = "Alice"
        ;

        List<MerchantModel> list = new List<MerchantModel>();
        list.Add(merchant1);
        list.Add(merchant2);
        list.Add(merchant3);

        var model = new MerchantViewModel
        
            Merchants = list
        ;

        return View(model);
    

    [HttpPost]
    public ActionResult Index(MerchantViewModel model)
    
        return View(model);
    

查看:

 @model TestCheckBoxes.Models.MerchantViewModel

    @
        Layout = null;
    

    <!DOCTYPE html>

    <html>
    <head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div> 
        <form action="/default/index" method="post">
            <table>
                @for (int i = 0; i < Model.Merchants.Count; i++)
                
                    <tr>
                        <td>
                            @Html.CheckBoxFor(x => x.Merchants[i].IsSelected)
                        </td>
                        <td>
                            @Html.HiddenFor(x => x.Merchants[i].AppId)
                            @Model.Merchants[i].AppId
                        </td>
                        <td>
                            @Html.HiddenFor(x => x.Merchants[i].Name)
                            @Model.Merchants[i].Name
                        </td>
                    </tr>
                
            </table>

            <button type="submit">Submit</button>
        </form>



    </div>
</body>
</html>

返回到控制器中的 [HttpPost] 方法,您将获得一个 MerchantModel 列表,其布尔值为 true 或 false。这样您就可以检查它是否为真,然后从那里获取 AppId。

【讨论】:

有没有办法为所有复选框应用“模型验证的数据注释”?【参考方案2】:

不要在 mvc 中使用 foreach,始终使用 for 和索引变量进行迭代。

您还需要一个布尔值来跟踪选择状态。

此示例代码适用于我:

public class AModel

    public List<AnotherModel> Items  get; set; 


public class AnotherModel

    public int ApplicationId  get;set; 
    public DateTime ApplicationDate  get; set; 
    public string ApplicantName  get; set; 
    public bool Selected  get; set; 

Page.cshtml

@using (Html.BeginForm("PostIndex", "Home", FormMethod.Post))

    <table class="table" style="margin-bottom: 0px">
        <tbody>
        @for (var i = 0; i < Model.Items.Count(); i++)
        
            <tr>
                <td>
                    <label>@Html.CheckBoxFor(model => model.Items[i].Selected) @Html.DisplayFor(model => model.Items[i].ApplicantName)</label>
                </td>
                <td>
                    @Html.ActionLink(Model.Items[i].ApplicationId.ToString(), "ViewApplication", new ID = Model.Items[i].ApplicationId, edit = 1, new AjaxOptions HttpMethod = "GET")
                </td>
                <td>
                    @Html.DisplayFor(model => model.Items[i].ApplicationDate)
                </td>
                <td>
                    @Html.DisplayFor(model => model.Items[i].ApplicationId)
                </td>
            </tr>
        
        </tbody>
    </table>
    <input type="submit"/>

【讨论】:

谢谢@CBauer。这似乎用 AModel 类代替了我需要的 PagedList。我将使用模型的 pagedlist 类尝试您的 for 语句。我没有创建这个视图;只是试图修改它。之前写过它的人使用了分页列表(以及 foreach,这就是它存在的原因);我正在尝试修改视图而不破坏其他任何内容。我会回信告诉你进展如何。 @boilers222 是的,我在您的 OP 中找不到示例模型,所以我只是替换了一个示例。您真正需要做的就是将 'selected' bool 添加到您的 pagedlist 类中,并用 mvc 元素替换呈现代码。 或者不要使用 for 循环并明确命名对象,而是尝试使用模板:codeguru.com/csharp/.net/net_asp/mvc/… 我不是模板的忠实粉丝,但在复杂的场景中使用过它们。但是,我相信你最终还是要使用for 语法生成编辑器。 为什么必须使用 for 而不是 foreach?【参考方案3】:

@CBauer 和@NickYoung 基本上有答案。关键是 (1) 确保我的复选框的 ID 用括号中的序列号写入,后缀相同,(2) 使用提交按钮而不是操作链接,以及 (3) 正确编写控制器以接受 ID从复选框。以为我会发布一些代码,让您了解我要做什么:

查看(部分):

@model PagedList.IPagedList<CarmelFinancialWeb.Models.ModelMerchantSummary>

...

@var i = 0;
@foreach (var item in Model)

  var tmp = "[" + i + "].ints";
  <tr>
      <td>
          <input name="ints" type="checkbox" id="@tmp" class="chkclass" value="@item.ApplicationID" />
      </td>

...

<input id="Submit" type="submit" class="btn btn-primary" value="Print Application(s)" />

...

控制器:

[AuthorizeAdmin]
[HttpPost]
public ActionResult MerchantApplicationSummary(string[] ints, FormCollection form, int? page)


...

感谢@CBauer 和@NickYoung 的帮助!

【讨论】:

复选框中不需要@var i = 0;var tmp = "[" + i + "].ints";id="@tmp"id 属性与回发的内容无关 - 只有一个控件namevalue值作为名称/值对发布)

以上是关于在 MVC/Razor 中,如何获取多个复选框的值并将它们全部传递给控制器​​?的主要内容,如果未能解决你的问题,请参考以下文章

如何在php中获取多个选定(动态)复选框的值?

如何从 MVC Razor 标记中获取查询字符串参数?

如何通过 MVC Razor 代码获取枚举成员的显示名称属性?

在 MVC4 razor 中使用“远程”验证处理多个提交按钮

c# 复选框如何获取内容,我在复选框中有多个勾选项,怎么去循环读取它的内容呢?

MVC3 razor 获取视图中的浏览器屏幕宽度和高度