Допустим, вы создаете форму с помощью ASP.NET MVC, которая имеет динамическое количество элементов формы.
Например, вам нужен флажок для каждого продукта, а количество продуктов меняется день ото дня.
Как бы вы поступили с отправкой данных формы обратно контроллеру? Вы не можете настроить параметры для метода действия, потому что не знаете, сколько значений формы будет возвращено.





В зависимости от ваших данных вы можете либо вывести «CheckboxList» (что больше невозможно в более новых версиях) и использовать параметр string[], либо вы можете настроить несколько форм и просто изменить действие.
Просто дайте каждому флажку уникальное значение имени:
<input class = "approveCheck" id = "<%= "approveCheck" + recordId %>"
name = "<%= "approveCheck" + recordId %>" type = "checkbox" />
Затем проанализируйте список значений формы в Action после отправки:
foreach (var key in Request.Form.Keys)
{
string keyString = key.ToString();
if (keyString.StartsWith("approveCheck", StringComparison.OrdinalIgnoreCase))
{
string recNum = keyString.Substring(12, keyString.Length - 12);
string approvedKey = Request.Form["approveCheck" + recNum];
bool approved = !String.IsNullOrEmpty(approvedKey);
// ...
Вам не нужно передавать значения формы в качестве аргументов; вы можете просто получить их из Request.Form.
Еще один вариант: напишите подшивку модели, чтобы преобразовать список в настраиваемый тип для отправки формы.
Ответ Пера Крейга ... так безопаснее. Есть причуды публикации нескольких элементов формы с одним и тем же именем. Я бы добавил, что было бы разумно обернуть логику, которая делает «коллекцию» элементов управления похожей на WebForms. Веб-формы добавляют имя элемента управления контейнера и добавляют индекс. Например, в Repeater элементы формы внутри будут называться (что-то вроде) RepeaterName_Element1, RepeaterName_Element2. Когда вы собираетесь извлечь элементы, вы должны использовать FindControl или что-то в этом роде.
В зависимости от используемых вами подшивок это должно работать:
<%var i = 0;
foreach (var product (IList<ProductSelection>)ViewData["products"]) {%>
<%=Html.Hidden(string.Format("products[{0}].Id", i), product.Id)%>
<%=Html.Checkbox(string.Format("products[{0}].Selected", i))%>
<%=product.Name%><br/>
<%}%>
... что приведет к тому, что HTML будет примерно таким (обратите внимание на обозначение массива в именах):
<input name = "products[0].Id" type = "hidden" value = "123">
<input name = "products[0].Selected" type = "checkbox">
Widget
<input name = "products[1].Id" type = "hidden" value = "987">
<input name = "products[1].Selected" type = "checkbox">
Gadget
... и метод контроллера, который обрабатывает сообщение:
public ActionResult SelectProducts(IList<ProductSelection> products)
{
...
}
После привязки параметр products будет содержать два экземпляра ProductSelection.
Одно предостережение: я не использовал новую привязку по умолчанию для сложных объектов. Скорее я использую либо NameValueDeserializer, либо CastleBind, оба из MvcContrib. Они оба так себя ведут. Я предполагаю, что привязка в бета-версии будет работать так же.