为啥将 ViewModel 传递给 View 时会出现此错误?
Posted
技术标签:
【中文标题】为啥将 ViewModel 传递给 View 时会出现此错误?【英文标题】:Why do I get this error when passing ViewModel to View?为什么将 ViewModel 传递给 View 时会出现此错误? 【发布时间】:2021-06-09 09:43:34 【问题描述】:将 ViewModel 传递给 View 时出现错误
传入 ViewDataDictionary 的模型项是类型 'System.Collections.Generic.List'1[TraficAlert.Models.TaBarHeader]', 但是这个 ViewDataDictionary 实例需要一个类型的模型项 'System.Collections.Generic.IEnumerable'1[TraficAlert.Models.ViewModels.HeaderTelegramaViewModel]'。
我尝试在Index.cshtml
中使用@model IEnumerable<TraficAlert.Models.ViewModels.HeaderTelegramaViewModel>
,它可以工作,但我需要从HeaderTelegramaViewModel
访问属性。
Index.cshtml:
@model IEnumerable<TraficAlert.Models.ViewModels.HeaderTelegramaViewModel>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.TaBarHeader.Id)
</th>
<th>
@Html.DisplayNameFor(model => model.TaBarHeader.ParentId)
</th>
<th>
@Html.DisplayNameFor(model => model.TaBarHeader.TStamp)
</th>
(...)
</thead>
<tbody>
@foreach (var item in Model)
<tr>
<td>
@Html.DisplayFor(modelItem => item.TaBarHeader.Id)
</td>
<td>
@Html.DisplayFor(modelItem => item.TaBarHeader.ParentId)
</td>
<td>
@Html.DisplayFor(modelItem => item.TaBarHeader.TStamp)
</td>
(...)
<td>
<a asp-action="Edit" asp-route-id="@item.TaBarHeader.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.TaBarHeader.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.TaBarHeader.Id">Delete</a>
</td>
</tr>
</tbody>
</table>
HeaderTelegramaController:
(...)
public IActionResult Index()
var applicationDbContext = _unitofwork.BarHeader.GetAllBarH().ToList();
return View(applicationDbContext);
TaBarHeaderRepository:
public IEnumerable<TaBarHeader> GetAllBarH()
return _db.TaBarHeaders
.Include(t => t.CategoriaFk)
.Include(t => t.CauzaFk)
.Include(t => t.ClasaFk)
.Include(t => t.LucrareFk)
.Include(t => t.RegionalaFk)
.Include(t => t.UserFk);
HeaderTelegramaViewModel:
public TaBarHeader TaBarHeader get; set;
public IEnumerable<SelectListItem> Categoria get; set;
public IEnumerable<ViewOtf> ViewOTFCollection get; set;
(...)
为什么会出现上述错误?
谢谢。
【问题讨论】:
正如错误消息所说,它预期HeaderTelegramaViewModel
的集合,但您已经传递了 TaBarHeader
的集合。您必须将 TaBarHeader
的集合映射到 HeaderTelegramaViewModel
的集合,或者更改视图的 @model
我在HeaderTelegramaViewModel
中创建了public IEnumerable<TaBarHeader> TaBarHeaders get; set;
,并在没有IEnumerable 的情况下更改了@model
,但不起作用。
GetAllBarH
返回 TypeA 并且您的视图需要 TypeB。根据提供的代码,两者之间没有隐式转换。因此,问题与List
或IEnumerable
无关,而是与它们的参数化类型有关。
现在我明白了。但是,我对如何在方法GetAllBarH()
中使用HeaderTelegramaViewModel
以及这样做的良好做法有点困惑。
您不应该在您的GetAllBarH
中使用HeaderTelegramaViewModel
。映射应该在 Controller 的 Action 内完成。您可以手动完成,也可以使用 3rd 方库,例如 AutoMapper
【参考方案1】:
在cshtml中使用下面的模型。
@model TraficAlert.Models.ViewModels.HeaderTelegramaViewModel
并在 Index() 中创建 HeaderTelegramaViewModel 的实例:
var _HeaderTelegramaViewModel = new HeaderTelegramaViewModel();
_HeaderTelegramaViewModel.TaBarHeader = TaBarHeader;
而且 HeaderTelegramaViewModel 类必须有:
public IEnumerable<TaBarHeader> TaBarHeader get; set;
public IEnumerable<SelectListItem> Categoria get; set;
public IEnumerable<ViewOtf> ViewOTFCollection get; set;
【讨论】:
如果我使用 @model TraficAlert.Models.ViewModels.HeaderTelegramaViewModel 我收到此错误 > foreach 语句无法对“HeaderTelegramaViewModel”类型的变量进行操作,因为“HeaderTelegramaViewModel”不包含公共实例或扩展定义'GetEnumerator' 在 cshtml 中使用它来访问元素列表:@foreach(Model.TaBarHeader 中的变量项) 我改了,原来的错误> 模型项传入ViewDataDictionary... 我认为这可能与IEnumerable<TaBarHeader> GetAllBarH()
的方法有关。
谢谢!我解决了这个问题,你的答案是最接近的。我在 Index.cshtml 中使用了@model HeaderTelegramaViewModel
;在 HeaderTelegramaViewModel 中声明属性 IEnumerable<TaBarHeader> taBarHeader get; set;
;在 HeaderTelegramaController 中更改:HeaderTelegramaViewModel headerTelegramaViewModel = new HeaderTelegramaViewModel(); headerTelegramaViewModel.taBarHeader = _unitofwork.BarHeader.GetAllBarH().ToList();
;并更改了 Index.cstml 中的 for:@foreach (var item in Model.taBarHeader)
.【参考方案2】:
使用 :: @model TraficAlert.Models.ViewModels.HeaderTelegramaViewModel
而不是 ::@model IEnumerable
在 index.cshtml 页面的顶部
【讨论】:
【参考方案3】:查看模型的类型 IEnumerable
public IActionResult Index()
var applicationDbContext = _unitofwork.BarHeader.GetAllBarH();
return View(applicationDbContext);
【讨论】:
【参考方案4】:错误消息相当清楚地解释了问题:您传递的类型与视图预期的不同。
具体来说,您调用GetAllBarH()
来获取视图的数据,它会返回IEnumerable<TaBarHeader>
。因此页面的model
声明应该是:
@model IEnumerable<TraficAlert.Models.TaBarHeader>
如果你真的想要HeaderTelegramaViewModel
,那么你将不得不以某种方式转换IEnumerable<TaBarHeader>
。我假设你错过了控制器中的那一步。
【讨论】:
【参考方案5】:为什么会出现上述错误?
因为您的操作中返回的数据类型与视图所需的数据类型不同。
您可以像这样修改您的 HeaderTelegramaController:
public IActionResult Index()
var applicationDbContext = _unitofwork.BarHeader.GetAllBarH().Select(m => new HeaderTelegramaViewModel TaBarHeader = m ).ToList();
return View(applicationDbContext);
【讨论】:
【参考方案6】:我认为可能来自您的表头的错误
考虑到您的模型是IEnumerable
,请尝试指定索引。
所以改变
@Html.DisplayFor(modelItem => item.TaBarHeader.Id)
这样的事情
@Html.DisplayFor(modelItem => item[0].TaBarHeader.Id)
【讨论】:
以上是关于为啥将 ViewModel 传递给 View 时会出现此错误?的主要内容,如果未能解决你的问题,请参考以下文章
为啥传递给函数的协议默认值不会改变,即使函数在子类化时会改变?