Модель, связывающая компонент вида на страницах бритвы
Я использую ASP.NET Core 2.1, Razor Pages и View View (хотя я еще не продал, если View Components еще нужны)
У меня есть родительская модель, Organization
, который содержит список дочерних моделей, Contacts
:
организация
public Guid Id { get; set; }
public string OrganizationName { get; set; }
public ICollection<Contact> Contacts { get; set; }
контакт
public Guid Id { get; set; }
public string ContactName { get; set; }
public Guid OrganizationId { get; set; }
То, что я пытаюсь сделать, это иметь список из n номеров контактов в организации, которые я могу добавлять и удалять из представления, и это отражается, когда я нажимаю OnPost()
Метод модели страницы
В моем предыдущем проекте веб-приложение MVC5:
- Я использовал Ajax для добавления частичных видов в представление: Обновление DIV с частичным видом при нажатии кнопки (динамически)
- И я смог получить по крайней мере один уровень глубоких списков, чтобы вернуться к контроллеру: C# MVC, связать вместе вложенные частичные представления
Комбинация этих двух выглядит примерно так: MVC 5 BeginCollectionItem с частичным CRUD
Текущее состояние
В ~/ViewComponents/Contact.cs
Я имею:
public class Contact : ViewComponent
{
private readonly ApplicationDbContext _context;
public Contact(ApplicationDbContext context)
{
_context = context;
}
public async Task<IViewComponentResult> InvokeAsync(Guid organizationId, Guid contactId)
{
var contact = new Models.Contact { Id = contactId, OrganizationId = organizationId };
return View(contact);
}
}
Который вызывает ~/Pages/Shared/Components/Contact/Default.cshtml
, использует портированную версию BeginCollectionItem:
@model Models.Contact
@using (Html.BeginCollectionItem("Contacts"))
{
<div class="row">
<input asp-for="Id" type="hidden" />
<input asp-for="OrganizationId" type="hidden"/>
<input asp-for="ContactName" class="form-control"/>
</div>
}
Я тогда непосредственно загружаю это в Организации ~/Pages/Organizations/Create.cshtml
:
@page
@using System.Linq
@using ViewComponents
@model CreateModel
@{
ViewData["Title"] = "Create";
}
<h2>Create</h2>
<h4>Organization</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div class="form-group">
<input asp-for="Organization.OrganizationName" class="form-control" />
</div>
<div class="form-group">
<label asp-for="OrganizationContacts" class="col-form-label"></label>
<!-- HERE --> @await Component.InvokeAsync(nameof(ViewComponents.Contact), new { organizationId = Model.Organization.Id, contactId = Guid.NewGuid() })
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
Когда я нажимаю кнопку "Отправить", OnPostAsync()
метод в Create.cshtml.cs
:
public class CreateModel : PageModel
{
private readonly ApplicationDbContext _context;
[BindProperty]
public Organization Organization { get; set; }
public CreateModel(ApplicationDbContext context, IMapper mapper)
{
_context = context;
}
public IActionResult OnGet()
{
Organization = new Organization{ Contacts = new List<Contact>() };
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
_context.Organizations.Add(Organization); // <--- Always has an empty Contacts list
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
Когда я ударил OnPostAsync
, связанный Organization
Модель имеет это OrganizationName
значение просто отлично, но Contacts
список всегда пуст.
Как я могу добавить контакт в организации Contacts
список, зная, что позже я хочу, чтобы количество контактов было добавлено или удалено?
Большинство ответов, которые я видел на этот вопрос, имеют for
циклы, но они требуют, чтобы я знал заранее, сколько Контактов есть или будет в Организации, и это просто не тот случай для меня.
1 ответ
Для разрешения пустых Contacts
попробуйте поменять Html.BeginCollectionItem("Contacts")
в Html.BeginCollectionItem("Organization.Contacts")
,
поскольку Contacts
это коллекция Organization
нужно пройти Organization.Contacts[index].Property
в противном случае он не сможет привязать запрос к модели.