【问题标题】:Controller returns value that not match with view?控制器返回的值与视图不匹配?
【发布时间】:2015-03-02 20:15:51
【问题描述】:

我有两个类,第一个是基类,第二个是从第一个继承的。

public class hgm
{ 
}

public class Laboratory : hgm
{
}

我使用 EF Code First 来生成数据库。另外,我使用默认的 Scaffold 来生成控制器和视图。

我可以使用编辑、创建、详细信息页面,但是对于索引(实例列表),出现错误:

传入字典的模型项的类型是'System.Collections.Generic.List'1[armnab.Models.hgm]',但是这个字典需要一个'System.Collections.Generic.IEnumerable'1[armnab.Models.Laboratory]'类型的模型项

这是我的控制器:

public class LaboratoriesController : Controller
{
    private hgmContext db = new hgmContext();

    // GET: Laboratories
    public ActionResult Index()
    {
        return View(db.hgms.ToList());
    }
}

和视图:

@model IEnumerable<armnab.Models.Laboratory>

<h2>Index</h2>

为什么会出现这个错误?

【问题讨论】:

  • 您的操作返回一个List&lt;armnab.Models.hgm&gt;,但您的视图需要一个IEnumerable&lt;armnab.Models.Laboratory&gt;Laboratory 是您的 hgm 的属性吗?
  • 您是否要过滤可能包含非实验室 hgms 的集合,或者 db.hgms 是否保证仅包含实验室实例?

标签: c# asp.net-mvc asp.net-mvc-5


【解决方案1】:

如果 Lab 继承自 hgm,您应该在控制器中传递实验室列表或更改此列表 IEnumerable&lt;armnab.Models.Laboratory&gt;到这个 IEnumerable&lt;armnab.Models.hgm&gt;.

除非您明确对其进行类型转换,否则 Laboratory 是 hgm,而 hgm 不一定是实验室,因此您不能只分配它。

【讨论】:

    【解决方案2】:

    由于您的 DbContext 返回 hgm 实例,并且您希望填充为实验室实现的视图,因此您需要将值转换为实验室类型。由于您不能保证 DbContext 只会返回实验室实例(鉴于您的问题范围),Cast 运算符可能会引发异常。

    鉴于问题中的信息,最佳选择是OfType,它不会返回不正确类型的值。

    public ActionResult Index()
    {
        return View(db.hgms.OfType<Laboratory>());
    }
    

    【讨论】:

      【解决方案3】:

      您的视图期望实验室的 IEnumerable。你正在返回一个

      List<hgm> 
      

      而不是一个

      List<Laboratory>
      

      您可能真的想返回 db.Laboratories.ToList() 或者如果 hgm 对象具有 Laboraties 作为属性,您需要选择 hgm 符合条件并从这里返回 Laboratories,例如

      var result = db.hgm.Where(x => x.someProperty == someValue).ToList();
      if(result.Count > 0)
      {
         return hgm.Laboratories;
      }
      

      【讨论】:

      • Laboratories 不是 hgm 的属性,laboratory 类派生自 hgm。
      • 好的,那么只需 db.hgms.Cast() 无需先将其放入列表中,因为 Cast 返回一个 IEnumerable
      【解决方案4】:

      泛型类中没有继承 (read this for additional details)
      如果您从 DB 中选择的所有对象都是 laboratory 对象,那么您可以使用 Cast&lt;Laboratory&gt; linq 方法。如果您希望所有 hgm 对象都被视为 laboratory 对象,那么您需要为从 db 获得的每个 hgm 创建新的 laboratory 对象并映射所有属性(您可以为此使用一些库比如AutoMapperValueInjecter)

      public ActionResult Index()
          {
              return View(db.hgms.Select(x => GetLaboratoryFromHgm(x));
          }
      
      private Laboratory GetLaboratoryFromHgm(Hgm obj) 
      {
            var lab = new Laboratory();
            //map all the properties here
      }
      

      【讨论】:

      • 如果您假设 db.hgms 返回一个hgm,则转换会以另一种方式进行,这似乎是从错误消息中得出的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-18
      • 1970-01-01
      • 2012-11-07
      • 2020-06-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多