Search code examples
c#asp.net-mvcinheritanceasp.net-mvc-layout

'The model item passed into the dictionary is of type' for inherited model class


I know this question has been asked numerous times, but I haven't found an already-asked question that addresses my problem exactly. My problem is that, for some reason, I am unable to use as a model a type that inherits from the expected type.

The exact error I am getting is:

The model item passed into the dictionary is of type 'ShoppingDealsClient.Models.ListViewModel`1[ShoppingDealsClient.Models.Deal]', but this dictionary requires a model item of type 'ShoppingDealsClient.Models.ListViewModel`1[ShoppingDealsClient.Models.BaseResponseModel]'.

and I get this error whenever I try to access the page http://localhost:50548/Home/Deal.

Let's look at the Deal.cshtml page:

@{
    ViewBag.Title = "Deals";
    Layout = "~/Views/Shared/_ListLayout.cshtml";
}

All it has is a reference to _ListLayout.cshtml:

<!DOCTYPE html>
@{
    Layout = "~/Views/Shared/_MenuedLayout.cshtml";
}
@model ShoppingDealsClient.Models.ListViewModel<ShoppingDealsClient.Models.BaseResponseModel>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
</head>
<body>

    <h1>
        <span>@ViewBag.Title</span>
        <button class='btn btn-primary pull-right'>+ Add New</button>
    </h1>
    <div>
        @RenderBody()
    </div>
</body>
</html>

As you can see, the _ListLayout.cshtml page is expecting a ListViewModel<BaseResponseModel> object as its model.

Below is the code where I return the view:

public ActionResult Deal()
{
    return View(new ListViewModel<Deal>());
}

where Deal inherits from BaseResponseModel.

As you can see, I am returning the correct type in the Deal() method, but I am still getting this type of error. Could there be a problem with my use of Layout views? Is there a better way to use partial views that can accept models?

EDIT On My Inheritance

I am intending for this same _ListLayout to be reused to eventually display lists of a wide range of different models that all inherit from BaseResponseModel. That is why the inheritance I have is necessary.

I am new to MVC development, so if anyone knows of a better way to accomplish, a comment would be helpful :)


Solution

  • There are lots of questions that address your problem. Either you just don't recognize it as the same or those answers aren't what you want to hear.

    A ListViewModel<Deal> is NOT a ListViewModel<BaseResponseModel> because BaseResponseModel is not covariant. In the same way, a Cage<Tiger> is not a Cage<Animal> because you can add a Rabbit to a Cage<Animal> but not o a Cage<Tiger> (at least without horrific results).

    Do some research on covariance to see if you need to create a covariant interface or find some other solution to your problem.

    An exmnaple of a covariant interface would be something like:

    public interface IBaseModel<out TModel> where TModel : TBaseResponseModel
    

    the constraint is that the interface can only output TModel objects - it cannot accept any as input (and cannot have any properties that are covariant, like a List<TModel>.

    So an interface with get-only properties and/or properties that return covariant interfaces (like IEnumerable<TModel>) an likely be made covariant.