简体   繁体   中英

Dictionary requires a model item of type System.Collections.Generic.List

I have a layout.csthml which contains a sidebar and also contains a @Renderbody. Both the @Renderbody and the sidebar use the following in their individual views.

@model List<appstowindows.Models.apps>
@foreach (var item in  Model){...}

Both views render the list fine, but when I try to open the edit URL in the view I keep getting the error:

The model item passed into the dictionary is of type System.Data.Entity.DynamicProxies, Dictionary requires a model item of type System.Collections.Generic.List

Edit url

@Html.ActionLink("Edit", "Edit", new { id = item.app_key }) 

Index

    public ActionResult Index()
    {
        var applist = db.apps.Include(a => a.appgroups);
        applist = db.apps.Include(a => a.appstatus);

        return View(applist.ToList());
    }

Edit

    public ActionResult Edit(int? id)
    {
        apps apps = db.apps.Find(id);
        return View(apps);
    }

Important Note: If I would remove either one of the lists in one of the views the edit URL works fine.

What is causing this error and how to resolve?

update:

@model myproject.Models.apps
@{
    ViewBag.Title = "Edit";
}
<h2>Edit</h2>

@using (Html.BeginForm("Edit", "Apps", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()

<div class="form-horizontal">
    <h4>apps</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    @Html.HiddenFor(model => model.app_key)

</div>
}

You are passing model of wrong type to your view. Passed object is of type System.Data.Entity.DynamicProxies while System.Collections.Generic.List is required. Check which object is provided as an argument to it.

UPDATED: And the problem is with model specified at your layout page. Edit view is based on layout page, so it requires a model of type List<apps> to be able to render. But Edit view requires apps as model on the opposite side. And while there is no type, which is List<apps> and apps at the same time, your code won't work.

Generally, you should avoid layout page typing, because all your views, based on that layout, will require the same or descendant type of model. If all of your pages should really share some information, you could solve this problem with multiple options:

  1. First one (and the worst) - base viewmodel type, which will be used as model for layout. In this solution all of views (which are based on this layout) should have models of base viewmodel descendant type, ie all actions have to get data for base viewmodel as well as for view model itself.
  2. Second one (I will go with it for simple cases) - child action, invoked inside your layout. It's better than previous, because data for shared view part should be retrieved only once in child action, there are no restrictions for views model type and your layout could stay without model. It uses composition instead of inheritance, which is simpler for supporting and is a preferable way of making things (you will be able to easily add multiple blocks of shared information with this approach, try to achieve it with first one). But child actions are restricted in MVC, they cannot be async (there are some hacks to make them async , but it's not a case)
  3. Third one (I will go with it, if multiple blocks of shared information should be displayed) - using js for deferred loading of content blocks. Has the same advantages as previous, but actions can be async by default. Also those blocks will not delay page loading and could be decorated with spinners or something in that way.

In your case error is caused by @model List<appstowindows.Models.apps> . While Edit view is executed, it renders layout page markup first, so object of type apps , provided as model to Edit view, is not suitable. I suppose, you specified a type at your layout, because some markup is shared between all of your pages (if I'm wrong, just delete @model from your layout, and everything will be okay) and this sharing could be implemented by one of methods I've proposed earlier.

If you go with the second one, you should add an action to your controller (don't know what information you are rendering, so I will call it Foo )

public ActionResult Foo()
{
    /*get data for your shared content part*/

    return PartialView(/*provide data here*/);
}

Then create View for it with markup, which should be shared. (The one from your layout, which causes issue)

@model List<appstowindows.Models.apps>
@foreach (var item in  Model){...}

Then remove that markup from your layout and call @Html.Action("Foo") instead.

Btw, I suppose you should learn some information about layout pages and models in ASP.MVC, official website is a good starting point.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM