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

时间:2023-01-24 11:00:47

I have a view with a list of items from a model. I need to add a checkbox to each row, have the user select multiple check boxes, and pass some identifier of what row was selected to the controller. I know how to pass a single value through an action link, but I'm not sure how to pass multiple values through an action link or how to "collect" which rows were selected. I'll show some of my code attempts below. Can someone help me sort out why I can't get the values of all the checkboxes passed to the controller?

我有一个视图,其中有一个模型的项目列表。我需要向每一行添加一个复选框,让用户选择多个复选框,并将选定的行的一些标识符传递给控制器。我知道如何通过操作链接传递单个值,但我不知道如何通过操作链接传递多个值,也不知道如何“收集”所选择的行。我将在下面展示我的一些代码尝试。有人能帮我找出为什么我不能将所有复选框的值传递给控制器吗?

Here's my page

这是我的页面

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

What I need the user to do is select rows 1 & 3 (for example) and have those App ID's passed to the controller.

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

I started listing various attempts, but decided just to show my current attempt and see if anyone could point out what I'm doing wrong. The main difference I see between examples online and mine is that mine uses a PagedList and creates the rows of the table in a foreach loop.

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

The parameter ints is blank when it hits the controller. How do I get the values from the checkboxes into it? I used this site for the basic idea of naming all the checkboxes the same and passing a ICollection through the action link: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

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

View:

观点:

@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" })

Controller:

控制器:

    [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");
    }

Edit: This got tagged as a duplicate of another question. The question there was about whether non-sequential input names could be used. My problem is that I'm using inputs that are not non-sequential, but it is still not working. I understand the concept, I just can't figure out why my specific code is not working. I've put a lot of time into this and can't find the answer to my specific code. Thanks!

编辑:这被标记为另一个问题的重复。问题是是否可以使用非顺序输入名称。我的问题是,我使用的输入不是非连续的,但它仍然不起作用。我理解这个概念,我只是不明白为什么我的特定代码不能工作。我在这上面花了很多时间,却找不到具体代码的答案。谢谢!

3 个解决方案

#1


7  

Try passing a ViewModel into your page, and using the model binder to post the same view model back into your controller

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

Models:

模型:

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; }
}

Controller:

控制器:

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);
    }
}

View:

观点:

 @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>

Back in your [HttpPost] method in your controller, you will have a list of MerchantModel's with the bool value either true or false. This way you can check if it's true and just grab the AppId from there.

回到您的控制器中的[HttpPost]方法中,您将有一个商船模型的列表,其中bool值为真或假。这样您就可以检查它是否正确,并从那里获取AppId。

#2


8  

Don't use foreach in mvc, always iterate using for and an indexing variable.

不要在mvc中使用foreach,总是使用for和索引变量。

You'll also need a bool to track the selection status.

您还需要一个bool来跟踪选择状态。

This example code works for me:

这个示例代码适用于我:

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

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"/>
}

#3


0  

@CBauer and @NickYoung essentially had the answer. The keys were (1) making sure my checkboxes had the ID written with a sequential number in brackets with the same suffix, (2) using a submit button instead of an action link, and (3) correctly writing the controller to accept the IDs from the checkboxes. Thought I'd post some of my code to give you an idea of what I got to work:

@CBauer和@NickYoung基本上得到了答案。键是(1)确保我的复选框的ID在括号中以相同后缀的顺序数字写入,(2)使用提交按钮而不是操作链接,(3)正确地编写控制器以接受复选框中的ID。我想我会发布一些代码让你知道我的工作内容:

View (partial):

视图(部分):

@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)" />

...

Controller:

控制器:

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

...

Thanks @CBauer and @NickYoung for your help!

感谢@CBauer和@NickYoung的帮助!

#1


7  

Try passing a ViewModel into your page, and using the model binder to post the same view model back into your controller

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

Models:

模型:

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; }
}

Controller:

控制器:

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);
    }
}

View:

观点:

 @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>

Back in your [HttpPost] method in your controller, you will have a list of MerchantModel's with the bool value either true or false. This way you can check if it's true and just grab the AppId from there.

回到您的控制器中的[HttpPost]方法中,您将有一个商船模型的列表,其中bool值为真或假。这样您就可以检查它是否正确,并从那里获取AppId。

#2


8  

Don't use foreach in mvc, always iterate using for and an indexing variable.

不要在mvc中使用foreach,总是使用for和索引变量。

You'll also need a bool to track the selection status.

您还需要一个bool来跟踪选择状态。

This example code works for me:

这个示例代码适用于我:

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

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"/>
}

#3


0  

@CBauer and @NickYoung essentially had the answer. The keys were (1) making sure my checkboxes had the ID written with a sequential number in brackets with the same suffix, (2) using a submit button instead of an action link, and (3) correctly writing the controller to accept the IDs from the checkboxes. Thought I'd post some of my code to give you an idea of what I got to work:

@CBauer和@NickYoung基本上得到了答案。键是(1)确保我的复选框的ID在括号中以相同后缀的顺序数字写入,(2)使用提交按钮而不是操作链接,(3)正确地编写控制器以接受复选框中的ID。我想我会发布一些代码让你知道我的工作内容:

View (partial):

视图(部分):

@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)" />

...

Controller:

控制器:

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

...

Thanks @CBauer and @NickYoung for your help!

感谢@CBauer和@NickYoung的帮助!