【问题标题】: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&lt;TaBarHeader&gt; TaBarHeaders { get; set; },并在没有IEnumerable 的情况下更改了@model,但不起作用。
  • GetAllBarH 返回 TypeA 并且您的视图需要 TypeB。根据提供的代码,两者之间没有隐式转换。因此,问题与ListIEnumerable 无关,而是与它们的参数化类型有关。
  • 现在我明白了。但是,我对如何在方法GetAllBarH() 中使用HeaderTelegramaViewModel 以及这样做的良好做法有点困惑。
  • 您不应该在您的GetAllBarH 中使用HeaderTelegramaViewModel。映射应该在 Controller 的 Action 内完成。您可以手动完成,也可以使用 3rd 方库,例如 AutoMapper

标签: c# asp.net-mvc asp.net-core view viewmodel


【解决方案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&lt;TaBarHeader&gt; GetAllBarH()的方法有关。
  • 谢谢!我解决了这个问题,你的答案是最接近的。我在 Index.cshtml 中使用了@model HeaderTelegramaViewModel;在 HeaderTelegramaViewModel 中声明属性 IEnumerable&lt;TaBarHeader&gt; 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&lt;TaBarHeader&gt;。因此页面的model 声明应该是:

      @model IEnumerable<TraficAlert.Models.TaBarHeader>
      

      如果你真的想要HeaderTelegramaViewModel,那么你将不得不以某种方式转换IEnumerable&lt;TaBarHeader&gt;。我假设你错过了控制器中的那一步。

      【讨论】:

        【解决方案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)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-05-13
            • 2017-01-01
            • 1970-01-01
            • 2021-08-04
            • 2019-11-03
            • 2012-03-09
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多