103

This question and community wiki answer has been added to assist in closing out numerous unanswered questions as discussed in this meta post.


I have some code and when it executes, it throws an exception saying:

The model item passed into the dictionary is of type Bar but this dictionary requires a model item of type Foo

What does this mean, and how do I fix it?

Community
  • 1
  • 1

7 Answers7

111

The error means that you're navigating to a view whose model is declared as typeof Foo (by using @model Foo), but you actually passed it a model which is typeof Bar (note the term dictionary is used because a model is passed to the view via a ViewDataDictionary).

The error can be caused by

Passing the wrong model from a controller method to a view (or partial view)

Common examples include using a query that creates an anonymous object (or collection of anonymous objects) and passing it to the view

var model = db.Foos.Select(x => new
{
    ID = x.ID,
    Name = x.Name
};
return View(model); // passes an anonymous object to a view declared with @model Foo

or passing a collection of objects to a view that expect a single object

var model = db.Foos.Where(x => x.ID == id);
return View(model); // passes IEnumerable<Foo> to a view declared with @model Foo

The error can be easily identified at compile time by explicitly declaring the model type in the controller to match the model in the view rather than using var.

Passing the wrong model from a view to a partial view

Given the following model

public class Foo
{
    public Bar MyBar { get; set; }
}

and a main view declared with @model Foo and a partial view declared with @model Bar, then

Foo model = db.Foos.Where(x => x.ID == id).Include(x => x.Bar).FirstOrDefault();
return View(model);

will return the correct model to the main view. However the exception will be thrown if the view includes

@Html.Partial("_Bar") // or @{ Html.RenderPartial("_Bar"); }

By default, the model passed to the partial view is the model declared in the main view and you need to use

@Html.Partial("_Bar", Model.MyBar) // or @{ Html.RenderPartial("_Bar", Model.MyBar); }

to pass the instance of Bar to the partial view. Note also that if the value of MyBar is null (has not been initialized), then by default Foo will be passed to the partial, in which case, it needs to be

@Html.Partial("_Bar", new Bar())

Declaring a model in a layout

If a layout file includes a model declaration, then all views that use that layout must declare the same model, or a model that derives from that model.

If you want to include the html for a separate model in a Layout, then in the Layout, use @Html.Action(...) to call a [ChildActionOnly] method initializes that model and returns a partial view for it.

  • 32
    +1 for "Note also that if the value of MyBar is null (has not been initialized), then by default Foo will be passed to the partial, in which case, it needs to be". Very important note. – Smix Mar 08 '18 at 06:48
  • I'm getting the same error by having a Partial View within a Layout, with no model type defined. The Partial View crashes because it receives the model from the index page when none is defined nor needed, and if I set the partial model to IndexModel, then the ViewData property is null!?? How to fix this scenario? Moving the partial into the layout does work but I want to understand how it works. – Etienne Charland Mar 04 '19 at 07:59
  • I ran into the same error when my partial view had "@page" at the top without "@model". removing "@page" solved the problem. – EKanadily Jun 07 '19 at 14:07
  • 1
    If you want to intentionally send a null model to the partial view when `Model.MyBar` is null, you can do this: `@Html.Partial("_Bar", Model.MyBar, new System.Web.Mvc.ViewDataDictionary())` Source: [https://stackoverflow.com/a/713921/4888725](https://stackoverflow.com/a/713921/4888725) – Kirk Grover Jul 09 '19 at 19:21
  • @Smix this is a VERY helpful comment. Just ran into this. – contactmatt Nov 20 '20 at 03:13
  • @Stephen Muecke, having a similar problem here... https://stackoverflow.com/questions/65114330/calling-a-partial-view – IrishChieftain Dec 04 '20 at 07:49
10

This question already has a great answer, but I ran into the same error, in a different scenario: displaying a List in an EditorTemplate.

I have a model like this:

public class Foo
{
    public string FooName { get; set; }
    public List<Bar> Bars { get; set; }
}

public class Bar
{
    public string BarName { get; set; }
}

And this is my main view:

@model Foo

@Html.TextBoxFor(m => m.Name, new { @class = "form-control" })  
@Html.EditorFor(m => m.Bars)

And this is my Bar EditorTemplate (Bar.cshtml)

@model List<Bar>

<div class="some-style">
    @foreach (var item in Model)
    {
        <label>@item.BarName</label>
    }
</div>

And I got this error:

The model item passed into the dictionary is of type 'Bar', but this dictionary requires a model item of type 'System.Collections.Generic.List`1[Bar]


The reason for this error is that EditorFor already iterates the List for you, so if you pass a collection to it, it would display the editor template once for each item in the collection.

This is how I fixed this problem:

Brought the styles outside of the editor template, and into the main view:

@model Foo

@Html.TextBoxFor(m => m.Name, new { @class = "form-control" })  
<div class="some-style">
    @Html.EditorFor(m => m.Bars)
</div>

And changed the EditorTemplate (Bar.cshtml) to this:

@model Bar

<label>@Model.BarName</label>
Hooman Bahreini
  • 14,480
  • 11
  • 70
  • 137
  • 2
    Awesome, you just saved me after half an hour scratching my head. Works for ASP.NET Core 3.1 MVC, too. – Uwe Keim Apr 16 '20 at 11:35
  • I know this is from a while ago, but could you take this a little farther? What does your post look like? Are you posting the list or a single item. If I try to accept a list, it always comes through as null. – littleGreenDude Jun 07 '23 at 17:13
7

Observe if the view has the model required:

View

@model IEnumerable<WFAccess.Models.ViewModels.SiteViewModel>

<div class="row">
    <table class="table table-striped table-hover table-width-custom">
        <thead>
            <tr>
....

Controller

[HttpGet]
public ActionResult ListItems()
{
    SiteStore site = new SiteStore();
    site.GetSites();

    IEnumerable<SiteViewModel> sites =
        site.SitesList.Select(s => new SiteViewModel
        {
            Id = s.Id,
            Type = s.Type
        });

    return PartialView("_ListItems", sites);
}

In my case I Use a partial view but runs in normal views

Banana
  • 2,435
  • 7
  • 34
  • 60
CelzioBR
  • 126
  • 1
  • 10
  • 1
    What does this have to do with the question? –  Nov 17 '17 at 20:45
  • 2
    @StephenMuecke this champs - The model item passed into the dictionary is of type Bar but this dictionary requires a model item of type Foo – CelzioBR Nov 21 '17 at 13:37
4

Consider the partial map.cshtml at Partials/Map.cshtml. This can be called from the Page where the partial is to be rendered, simply by using the <partial> tag:

<partial name="Partials/Map" model="new Pages.Partials.MapModel()" />

This is one of the easiest methods I encountered (although I am using razor pages, I am sure same is for MVC too)

kesarling He-Him
  • 1,944
  • 3
  • 14
  • 39
0

First you need to return an IEnumerable version of your model to the list view.

@model IEnumerable<IdentityManager.Models.MerchantDetail>

Second, you need to return a list from the database. I am doing it via SQL Server, so this is code I got working.

    public IActionResult Merchant_Boarding_List()
        List<MerchantDetail> merchList = new List<MerchantDetail>();
        var model = new MerchantDetail();

        try
        {
            using (var con = new SqlConnection(Common.DB_CONNECTION_STRING_BOARDING))
            {
                con.Open();
                using (var command = new SqlCommand("select * from MerchantDetail md where md.UserGUID = '" + UserGUID + "'", con))
                {
                    using (SqlDataReader reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            model.biz_dbaBusinessName = reader["biz_dbaBusinessName"].ToString();
                            merchList.Add(model);
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
        }

        return View(merchList);
0

Passing the model value that is populated from a controller method to a view

 public async Task<IActionResult> Index()
 {
   //Getting Data from Database
   var model= await _context.GetData();

   //Selecting Populated Data from the Model and passing to view
   return View(model.Value);
 }
0

one more thing. if your view is a partial/sub page and the model for that partial view is null for some reason (e.g no data) you will get this error. Just need to handle the null partial view model

Jay
  • 687
  • 2
  • 7
  • 18