В MVC/Razor, как мне получить значения нескольких флажков и передать их всем контроллеру?

У меня есть представление со списком элементов из модели. Мне нужно добавить флажок в каждую строку, задать пользователю несколько флажков и передать некоторый идентификатор того, какая строка была выбрана контроллеру. Я знаю, как передать одно значение через ссылку действия, но я не уверен, как передать несколько значений через ссылку действия или как "собрать", какие строки были выбраны. Ниже я расскажу о некоторых моих попытках с кодом. Может кто-нибудь помочь мне разобраться, почему я не могу получить значения всех флажков, переданных контроллеру?

Здесь моя страница

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

Мне нужно, чтобы пользователь должен был выбрать строки 1 и 3 (например) и передать эти идентификаторы приложения контроллеру.

Я начал перечислять различные попытки, но решил просто показать свою текущую попытку и посмотреть, может ли кто-нибудь указать, что я делаю неправильно. Основное различие, которое я вижу в примерах онлайн и моих, заключается в том, что моя использует 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");
    }

Изменить: Это было отмечено как дубликат другого вопроса. Вопрос в том, можно ли использовать непоследовательные имена. Моя проблема в том, что я использую входные данные, которые не являются последовательными, но они все еще не работают. Я понимаю концепцию, я просто не могу понять, почему мой конкретный код не работает. Я потратил много времени на это и не могу найти ответ на свой конкретный код. Спасибо!

Ответ 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 с значением bool либо true, либо false. Таким образом, вы можете проверить, правда ли это, и просто захватить AppId оттуда.

Ответ 2

Не используйте foreach в mvc, всегда итерации с помощью for и переменной индексации.

Вам также понадобится bool для отслеживания статуса выбора.

Этот пример кода работает для меня:

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

Ответ 3

@CBauer и @NickYoung получили ответ. Ключом было (1) убедиться, что мои флажки имеют идентификатор, записанный с последовательным номером в скобках с тем же суффиксом, (2) с использованием кнопки отправки вместо ссылки на действие и (3) правильной записи контроллера для приема идентификаторов из флажков. Думал, что я бы опубликовал часть своего кода, чтобы дать вам представление о том, что я должен работать:

Просмотр (частичный):

@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 за вашу помощь!