Я относительно новичок в .NET MVC и борюсь с веб-приложением, над которым работаю. В общем, это приложение состоит из формы, основная часть которой вводит имя клиента, а затем есть кнопка для добавления дочернего элемента. При нажатии этой кнопки в частичном представлении появляется подчиненная форма. Я еще не уверен, что делать с данными, когда нажата кнопка сохранения в подформе (но подформа рухнет, стиль аккордеона на стороне HTML), но суть в том, что клиент может добавить один или многие дочерние подформы для ввода имен и возраста своих детей (детей).
Каков наилучший способ обработки входных данных в этих формах? Я говорил с некоторыми коллегами, и они казались неуверенными. Один из них предложил сначала сохранить «родительскую» форму в базе данных, а затем в каждой подформе (дочерней) при нажатии кнопки «Сохранить» отправить их также в базу данных, используя родительский идентификатор для их подключения. Кто-то еще предложил использовать для этого Vue. Что бы ВЫ предложили с точки зрения привязки модели или отправки данных обратно в контроллер?
Сначала модель представления для формы выглядит так:
namespace ModelBindingObjects.ViewModel
{
public class ParentVM
{
public string Name { get; set; }
public List<ChildVM> Children { get; set; }
}
public class ChildVM
{
public string Name { get; set; }
public int Age { get; set; }
}
}
Для стороны db модели выглядят так:
public partial class Parent
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
}
public partial class Child
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public int ParentId { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
public int Age { get; set; }
Вид выглядит так
@model ModelBindingObjects.ViewModel.ParentVM
<h3>A Sample Form</h3>
@using (Html.BeginForm())
{
<div class = "container">
<div class = "row">
<div class = "form-row">
<div class = "form-group col-md-6">
@Html.LabelFor(x => x.Name, new { @class = "required" })
@Html.TextBoxFor(x => x.Name, new { @class = "form-control" })
</div>
<div class = "col-md-6">
</div>
</div>
</div>
<div class = "row">
<div class = "form-group col-md-6">
<div class = "addChildren">
<h5 class = "topspacing-med btmspacing-med">Your Child(ren) Details</h5>
<div class = "displayChildForm">
@*@Html.Partial("_AddChild", new ViewDataDictionary()
{
TemplateInfo = new TemplateInfo()
{ HtmlFieldPrefix = "Test" }
})*@
</div>
<button type = "button" class = "btn btn-outline-secondary btn-sm btn-block btmspacing-med" id = "addChild">Add New Child</button>
</div>
</div>
<div class = "form-group col-md-6"></div>
</div>
</div>
}
@section scripts {
<script type = "text/javascript">
var hideButtons = function () {
$("#addChild").hide();
};
$("#saveChild").click(function () {
console.info("testing");
$(".panel-body").hide();
});
$("#addChild").click(function () {
$.ajax({
url: '@Url.Action("RenderAddChildForm", "Home")',
dataType: "html",
type: 'GET',
success: function (result) {
$('.displayChildForm').append(result);
hideButtons();
},
error: function (xhr, ajaxOptions, thrownError) {
console.info(xhr.status);
console.info(thrownError);
},
});
});
</script>
Потом частичный вид...
@model ModelBindingObjects.ViewModel.ChildVM
<div class = "panel panel-primary">
<div class = "panel-heading"><h5>Add A Child</h5></div>
<div class = "panel-body">
<div class = "form-group row">
<div class = "col-md-12">
<input type = "hidden" name = "products.Index" value = "test" />
@*@Html.LabelFor(x => x.Name)
@Html.TextBoxFor(x => x.Name, new { @class = "form-control" })*@
<input type = "text" name = "[test].Name" value = "Delaney" />
</div>
</div>
<div class = "form-group row">
<div class = "col-md-12">
<input type = "text" name = "[test].Age" value = "12" />
</div>
</div>
<div class = "btn-group float-right mt-2" role = "group">
<button class = "btn btn-primary btn-sm btn-block" type = "submit" id = "saveChild">Save</button>
</div>
</div>
</div>
и, наконец, старый добрый контроллер:
namespace ModelBindingObjects.Controllers
{
public class HomeController : Controller
{
private string PartialViewPath(string name)
{
return $"~/Views/Partials/{name}.cshtml";
}
// GET: Home
public ActionResult Index()
{
return View();
}
public ActionResult RenderAddChildForm()
{
return PartialView(PartialViewPath("_AddChild"));
}
}
}





Это зависит от сложности потока страниц, от того, насколько вы знакомы с Vue, и есть ли отдельная страница редактирования или вы хотите поддерживать редактирование/удаление на той же странице. Если все, что он делает, это спасает детей, то вы можете легко сделать это с запросами AJAX, не вводя Vue.
Один из подходов состоит в том, чтобы разделить две операции, чтобы пользователь не мог добавить дочернюю операцию, если он не добавил и не сохранил родительские данные. В родительской форме сохраните успех, верните сохраненный parentId и отключите кнопку. Для каждой подформы, когда пользователь нажимает «сохранить дочернюю», отправьте {parentId, childVm}.
Другой подход состоит в том, чтобы иметь только одну кнопку сохранения для всей страницы, т. е. каждый ребенок не получает свою собственную кнопку сохранения. Элемент div displayChildForm действует как набор входных данных с одной кнопкой «Добавить дочерний элемент», которая создает дополнительные частичные представления дочерних элементов и добавляет их к себе. Когда пользователь нажимает кнопку сохранения страницы, вы отправляете {parentVm, childVmCollection[]}.
Вы можете смешивать оба подхода, так что в итоге вы получите кнопку «сохранить родительский элемент» и одну кнопку «сохранить/редактировать дочерние элементы» в displayChildForm div. При нажатии кнопки «Сохранить дочерние элементы» вы отправляете {parentId, childVmCollection[]}.
Вы можете просто привязать модель к свойству ICollection в модели.
старая, но золотая: https://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/
Вы также можете найти некоторые мои библиотеки полезными для такого рода вещей.
https://github.com/mcintyre321/FormFactoryhttps://github.com/mcintyre321/AspNetCoreJTokenModelBinder
Спасибо! Комбинация взломанной ссылки, которую вы разместили в дополнение к этой binintellect.net/articles/…, помогла мне запустить этот код. Гораздо проще, чем я предполагал.
Спасибо! Я получил это и работал, используя набор входов с одной кнопкой. Эта ссылка помогла мне представить, как должен выглядеть код: binintellect.net/articles/…, хотя я могу представить, что с Vue это будет гораздо более простая задача.