ovatsug25
ovatsug25

Reputation: 8596

Nested collection view partial in ASP MVC

I'm trying to pass a Kids collection from my main view to a partial. This main view is strongly typed and the Kids attribute is a has_many association for the MainModel.

I have my default details view where my @model MyApp.Models.MainModel.

Inside this view, I want to show its children,

@Html.Partial("_KidsView", Model.Kids)

which is configured like this in my MainModel.cs:

public ICollection<Kid> Kids { get; set; }

and is specified in my parital _KidsView as such:

@model ICollection<MyApp.Models.Kid>

I am getting an InvalidOperationException where it says

The model passed into this the dictionary if of type
'System.Data.Entity.DyanmicProxies.MainModel_#WHOLE_BUNCH_OF_NUMBERS'
but this dictionary requires a model item of type 
'System.Collections.Genereic.ICollection[MyApp.Models.Kid]

I have tried not using a partial and calling the foreach loop directly on @foreach (var item in Model.Kids) but that hasn't worked either.

How can I properley pass this in?

I feel like I may be doing something obviously wrong but I can't see it.

EDIT:

Ok, so the solution isn't working. I figure it's something in one of my models that's not right.

Here is Kid.cs:

[Column("main_model_id")]
public int MainModelID { get; set; }
public virtual MainModel MainModel {get; set; }

and MainModel.cs

public ICollection<Kid> Kids { get; set; }

Upvotes: 0

Views: 501

Answers (2)

Chris Pratt
Chris Pratt

Reputation: 239260

The error you're getting is explicit and can really only be caused by two things:

  1. Your model specification in your partial view is incorrect, which you say it's not.

  2. You're passing in the wrong thing to the call to Partial or RenderPartial. Specifically, if you do not specify the model argument, it's filled with the main view's model by default (which seems to be happening based on the error, but the call you have in your question is correct).

Since it seems neither of those is the case, I can only assume there's some kind of caching going on or some other "stickiness" that causing your current code to not actually be the code that's running. Stop and restart debugging, and maybe even close Visual Studio and try again, after the confirm that your code is indeed correct.

An alternative solution is to use a display template instead - it's pretty much like a partial view, but a little cleaner in situations like this.

  1. In your "Views" folder, create a new folder called "DisplayTemplates". In that folder, create a partial view called "Kid.cshtml". Strongly-type that view to your Kid model (not an enumerable, just Kid). Add the HTML that should be rendered for one instance of a Kid.

  2. In your main view add the following:

    @Html.DisplayFor(m => m.Kids)
    
  3. Party!

Upvotes: 1

ataravati
ataravati

Reputation: 9155

Here is how you should do it; let's say this is your main Model:

public class MainModel
{
  public IEnumerable<Kid> Kids { get; set; }
  // Other properties
}

Do this in your main View:

@model MyApp.Models.MainModel

@Html.EditorFor(model => model.Kids)

Then, create a partial view like below, name it Kid.cshtml, and place it under Views/Shared/EditorTemplates:

@model MyApps.Models.Kid

@* Your html helpers (input fields) *@

Upvotes: 0

Related Questions