#c# #asp.net #asp.net-core #asp.net-core-mvc
#c# #asp.net #asp.net-core #asp.net-core-mvc
Вопрос:
Я пытаюсь создать простое приложение для чата, с которым можно начать ASP.NET и мое частичное представление, похоже, получает тип данных, переданный в Index.cshtml вместо данных, которые я намеревался передать в PersistantMessagesPartial.cshtml.
Ошибка:
Исключение InvalidOperationException: элемент модели, переданный в ViewDataDictionary, имеет тип ‘System.Коллекции.Generic.List
1[WebChat.Areas.Identity.Data.AppUser]', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.List
1[Веб-чат.Модели.MessageModel]’.***
В HomeController.cs:
public async Task<IActionResult> Index()
{
Debug.WriteLine("debug1");
return View(await _AppUserDBContext.userList.ToListAsync());
}
public async Task<IActionResult> _PersistantMessagesPartial()
{
Debug.WriteLine("debug2");
return PartialView("_PersistantMessagesPartial", await _MessageModelDBContext.messageList.ToListAsync());
}
В _PersistantMessagesPartial.cshtml:
@model List<WebChat.Models.MessageModel>
<script>
console.log("test");
</script>
@foreach(var item in Model)
{
<script>
console.log("MessagePartial");
console.log(@item.Contents);
</script>
}
Как я могу отобразить частичное представление в _Layout.cshtml:
<partial name="_PersistantMessagesPartial" />
Index.cshtml получает список AppUser, и это работает правильно. Я не уверен, как заставить _PersistantMessagesPartial получать список MessageModel вместо списка AppUser.
Комментарии:
1. Вы должны добавить
model
в свой тег частичного просмотра. Вот так:<partial name="_PersistantMessagesPartial" model="@Model.GoesHere" />
. Я думаю, что он получает модель из вашего индексного представления, переданную ему. Это не вызывает ваш_PersistantMessagesPartial
в вашем контроллере, возможно, вам потребуется создать модель представления или превратить частичное представление и действие в компонент представления2. @zgood предложение компонента view является допустимым и предпочтительным. Однако информация здесь: learn.microsoft.com/en-us/aspnet/core/mvc/views /… может помочь вам передать модель, отличную от родительской
ViewDataDictionary
..
Ответ №1:
Вместо передачи списка объектов я бы создал класс:
public class PersistantMessagesPartialModel{
public List<WebChat.Models.MessageModel> Messages{get;set;}
}
и передайте объект, используя атрибут for, вот так:
@model IndexViewModel
<partial name="_PersistantMessagesPartial.cshtml" for="PersistantMessagesPartialModel" />
Тогда ваше частичное представление будет выглядеть:
@model PersistantMessagesPartialModel
@foreach(var item in Model.Messages)
{
<script>
console.log("MessagePartial");
console.log(@item.Contents);
</script>
}
Контроллер будет выглядеть следующим образом:
[HttpGet]
public async Task<IActionResult> Index()
{
var viewModel = new IndexViewModel(){
PersistantMessagesPartialModel = new
PersistantMessagesPartialModel(){
Messages = await
_AppUserDBContext.userList.ToListAsync()
};
return View(viewModel);
}
IndexViewModel
Будет выглядеть так:
public class IndexViewModel{
public PersistantMessagesPartialModel
PersistantMessagesPartialModel {get;set;}
}
Я знаю, что ASP.NET MVC позволяет вам определять модель данной страницы в виде списка объектов, однако я верю в правило, согласно которому каждая страница .cshtml должна иметь один класс модели. Это дает вам огромную гибкость, когда вы хотите добавить какую-то новую логику в представление. Просто представьте простой случай, когда вы хотите добавить в свое частичное представление некоторый оператор if, который будет работать на основе некоторого значения, установленного в серверной части вашего приложения. В таком случае вам нужно будет использовать ViewBag, ViewData objects для передачи его в представление, и это немного сложнее поддерживать, особенно если ваше приложение большое.
В моем решении вы бы просто добавили это дополнительное поле в PersistantMessagesPartialModel
, и даже в том случае, когда вы хотите выполнить некоторое переименование и т.д. это просто быстрее и безопаснее.
Комментарии:
1. Извините, я в замешательстве. Откуда частичное получит экземпляр PersistantMessagesPartialModel? Тот же вопрос, другая формулировка: откуда атрибут for получил бы модель, если бы не передавался с использованием представлений?
2. Например. у вас есть представление Home.cshtml. Это представление
@model
будет HomeViewModel . Это выглядело бы какpublic class HomeViewModel { public PersistantMessagesPartialModel PersistantMessagesPartialModel {get; set;} // and some other properties}
. Когда вы добавляете<partial name="_PersistantMessagesPartial.cshtml" for="PersistantMessagesPartialModel" />
в Home.cshtml,for
атрибут будет принимать значение из свойстваHomeViewModel
3. В другом случае, например, если вы хотите добавить свое частичное представление в _layout.cshtml, я бы использовал
ViewBag
в действии контроллера для установки частичной модели и передачи значения с помощьюmodel
атрибута, например<partial name="_PersistantMessagesPartial" model="@ViewBag['PersistantMessagesPartialModel']" />
4. Если вы все еще чего-то не понимаете, не стесняйтесь задавать вопросы, я постараюсь объяснить вам все более подробно, если это необходимо
![]()
5. О, так у вас HomeViewModel действует как оболочка данных. Теперь у меня все работает нормально, большое вам спасибо!
![]()