#asp.net #asp.net-mvc #asp.net-core
#asp.net #asp.net-mvc #asp.net-core
Вопрос:
Существует контроллер индекса, в нем я связываю данные из базы данных с modelview, и мое представление собирает пользовательские данные и отображает их. И соответственно ниже я прикреплю PartialView
public class CustomerController : Controller
{
private ICustomerRepository _customerRepository;
public CustomerController(ICustomerRepository customerRepository)
{
_customerRepository = customerRepository;
}
[HttpGet]
public IActionResult Index()
{
IEnumerable<CustomerViewModel> customers =
_customerRepository.GetAllCustomers().Select(s => new
CustomerViewModel
{
CustomerId = s.CustomerId,
Name = s.Name,
Adress = s.Adress
});
return View("Index", customers);
}
[HttpGet]
public IActionResult Create()
{
return Redirect("Index");
}
}
@model IEnumerable<CustomerViewModel>
<h2>Create Customer</h2>
@{
await Html.RenderPartialAsync("Create");
}
<table class="table">
@Html.DisplayNameFor(model => model.Name)
@foreach (var item in Model)
{
@Html.DisplayFor(modelItem => item.Name)
}
</table>
Это сам PartialView:
@model CustomerViewModel
<div class="col-md-4">
<form asp-action="Create" asp-controller="Customer">
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input type="text" asp-for="Name" class="form-control" />
</div>
При запуске приложения возникает ошибка:
Исключение InvalidOperationException: элемент модели, переданный в ViewDataDictionary, имеет тип ‘System.Linq.Enumerable SelectEnumerableIterator` 2[Store.DAL.Entity.Клиент, Store.Web.ViewModels.CustomerViewModel]’, но для этого экземпляра ViewDataDictionary требуется элемент модели типа ‘Store.Web.ViewModels. CustomerViewModel
Если PartialView поместить на отдельную страницу, просто чтобы создать ссылку на представление, все будет отображаться, и ошибки не будет. Может быть, все дело в том, как я переопределяю данные в контроллере для CustomerViewModel? Кто занимался этим?
Ответ №1:
Что происходит
В вашем коде вы не предоставляете своему представлению модель, которую оно ожидает.
Если вы используете Html.RenderPartialAsync(viewName)
, вы автоматически передаете всю модель из основного представления в частичное. Поскольку основное представление имеет тип модели IEnumerable<CustomerViewModel>
— это то, что передается вашему частичному представлению.
Решения
- Используйте отдельную страницу для создания объектов вместо повторного использования той же страницы для отображения существующих
- Сделайте вашу модель более сложной, чтобы ее можно было использовать для обоих представлений, и используйте перегрузку
Html.RenderPartialAsync(string viewName, object model)
для правильной передачи модели.
Для решения # 2 пример кода может быть:
Новый класс
public class CustomerListViewModel
{
IEnumerable<CustomerViewModel> existingCustomers;
CustomerViewModel newCustomer;
}
Контроллер
[HttpGet]
public IActionResult Index()
{
IEnumerable<CustomerViewModel> customers =
_customerRepository.GetAllCustomers().Select(s => new
CustomerViewModel
{
CustomerId = s.CustomerId,
Name = s.Name,
Adress = s.Adress
});
CustomerListViewModel model = new CustomerListViewModel
{
existingCustomers = customers.AsEnumerable();
newCustomer = new CustomerViewModel();
}
return View("Index", model);
}
Основной вид
@model CustomerListViewModel
<h2>Create Customer</h2>
@{
await Html.RenderPartialAsync("Create", Model.newCustomer);
}
<table class="table">
@foreach (var item in Model.existingCustomers)
{
<tr>
<td>@Html.DisplayFor(item => item.Name)</td>
</tr>
}
</table>