1

I have two classes, the first one is base class and second one is inherited from first.

public class hgm
{ 
}

public class Laboratory : hgm
{
}

I used EF Code First to generate the database. Also, I used the default Scaffold to generate controllers and views.

I can use edit, create, details pages but for index(the list of instances), there is an error:

The model item passed into the dictionary is of type 'System.Collections.Generic.List'1[armnab.Models.hgm]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable'1[armnab.Models.Laboratory]'

Here is my controller:

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

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

and the view:

@model IEnumerable<armnab.Models.Laboratory>

<h2>Index</h2>

Why is this error occuring?

Steve Mitcham
  • 5,268
  • 1
  • 28
  • 56
  • 3
    You action returns a `List` but your view expects a `IEnumerable`. Is `Laboratory` a property of your `hgm`? – Jasen Mar 02 '15 at 20:20
  • 1
    Suggested reading: http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx – yoozer8 Mar 02 '15 at 20:25
  • Are you trying to filter a collection that might contain hgms that aren't Laboratories, or is db.hgms guaranteed to contain only Laboratory instances? – Steve Mitcham Mar 02 '15 at 20:27

4 Answers4

2

If Lab inherits from hgm you should either pass a list of laboratories in your controller or change this IEnumerable<armnab.Models.Laboratory> to this IEnumerable<armnab.Models.hgm>.

Unless you typecast it explicitly, while a Laboratory is an hgm an hgm is not necessarily a laboratory so you cannot just assign it.

Jonny
  • 2,787
  • 10
  • 40
  • 62
1

Since your DbContext is returning hgm instances and you are looking to populate a view implemented for Laboratories, you need to cast the value to the Laboratory type. Since you can't guarantee that the DbContext will only return Laboratory instances (given the scope of your question), the Cast operator may throw an exception.

Given the information in the question, the best choice is OfType which will not return values that aren't the correct type.

public ActionResult Index()
{
    return View(db.hgms.OfType<Laboratory>());
}
Steve Mitcham
  • 5,268
  • 1
  • 28
  • 56
0

Your view is expecting an IEnumerable of Laboratory. You are returning a

List<hgm> 

instead of a

List<Laboratory>

You probably really want to return db.Laboratories.ToList() or if hgm object has Laboraties as a property you need to select the hgm meets criteria and return Laboratories from this e.g

var result = db.hgm.Where(x => x.someProperty == someValue).ToList();
if(result.Count > 0)
{
   return hgm.Laboratories;
}
Luthervd
  • 1,388
  • 2
  • 14
  • 25
0

There is no inheritance in generic classes (read this for additional details)
If all the objects that you select from DB are laboratory objects, then you can use Cast<Laboratory> linq method. If you want all you hgm objects to be treated as laboratory objects than you need to create new laboratory object for each hgm that you get from db and map all the properties (you can use some library for this like AutoMapper or ValueInjecter)

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
}
Community
  • 1
  • 1
Alex Art.
  • 8,711
  • 3
  • 29
  • 47
  • The conversion goes the other way if you assume that db.hgms returns an `hgm`, which seems to follow from the error message. – Steve Mitcham Mar 02 '15 at 20:28