MVC BeginCollectionItem
У меня возникли проблемы с получением моего частичного представления BeginCollectionItem для сохранения в базе данных. У меня есть форма с динамическим числом "разделов", которые можно добавить на страницу, и внутри каждого из этих полей есть текстовое поле, в котором пользователь может ввести имя раздела.
Насколько я могу сказать, BeginCollectionItem в частичном представлении работает правильно, однако я не могу опубликовать информацию в базе данных. В других моих формах я использовал [bind()] для отправки данных в базу данных, возможно ли поместить их в список, а затем опубликовать это через bind?
Я включил мой код ниже:Модель:
namespace project.Models.SetupViewModels
{
public class SOPTopTemplateBuilderViewModel
{
public List<Section> Section { get; set; }
}
public class Section {
public int SectionId { get; set; }
public string SectionText { get; set; }
public string TopTempId { get; set; }
}
}
cshtml:
@model IEnumerable<project.Models.SetupViewModels.Section>
@using (Html.BeginForm("SOPTopTemplateBuilder", "Setup", FormMethod.Post))
{
<div class="main-holder" id="theform">
@foreach(var item in Model)
{
@Html.Partial("_SectionCreator", item)
}
</div>
<button id="add" type="button">Add</button>
<div class="form-group submit-row">
<div class="col-12 float-to-right">
<input type="submit" class="btn btn-default" value="continue" />
</div>
</div>
}
@section Scripts {
<script>
$(document).ready(function () {
var url = '@Url.Action("AddSection")';
var form = $('form');
var recipients = $('#theform');
$('#add').click(function() {
$.post(url, function(response) {
recipients.append(response);
// Reparse the validator for client side validation
form.data('validator', null);
$.validator.unobtrusive.parse(form);
});
});
});
</script>
}
Частичный вид:
@model project.Models.SetupViewModels.Section
@using HtmlHelpers.BeginCollectionItemCore
@using (Html.BeginCollectionItem("Section"))
{
<div class="new-section">
<div>
<p>New Section</p>
@Html.HiddenFor(m => m.SectionId, new { @class="id" })
@Html.EditorFor(m => m.SectionText, new { @class = "form-control limit-form"})
</div>
</div>
}
контроллер:
[HttpPost]
public PartialViewResult AddSection()
{
return PartialView("_SectionCreator", new Section());
}
[HttpGet]
public ActionResult SOPTopTemplateBuilder(){
List<Section> model = new List<Section>();
return View(model);
}
[HttpPost]
public ActionResult SOPTopTemplateBuilder(IEnumerable<Section> soptop)
{
if (ModelState.IsValid)
{}
return View(soptop);
}
1 ответ
Ваше использование Html.BeginCollectionItem("Section")
perpends Section[xxxx]
к атрибуту имени (где xxxx
это Guid
) так что вы генерируете входы с
<input name="Section[xxxx].SectionId" .... />
который отправляет обратно в модель, содержащую свойство коллекции с именем Sections
,
Поскольку у вас уже есть модель с этим свойством, вы можете изменить метод POST на
[HttpPost]
public ActionResult SOPTopTemplateBuilder(SOPTopTemplateBuilderViewModel soptop)
другие варианты включают
- Использование существующего метода POST и пропуск префикса "Section" с помощью
Html.BeginCollectionItem("")
который будет генерироватьname="[xxxx].SectionId"
- Изменение подписи метода POST на
public ActionResult SOPTopTemplateBuilder(IEnumerable<Section> section)
(где имя параметра совпадает с именем префикса) - Используя
BindAttribute
убрать префикс из значений формыpublic ActionResult SOPTopTemplateBuilder([Bind(Prefix = "Section")]IEnumerable<Section> soptop)
Как примечание, ваши данные редактирования, поэтому вы всегда должны использовать модель представления (скажем, public class SectionViewModel
) вместо использования моделей данных в вашем представлении. Что такое ViewModel в MVC?