I am running in to a problem where I have made the following query in my controller:
var query = from pmt in db.ProjectHasTags
join project in db.Projects on pmt.ProjectId equals project.ID
join tag in db.ProjectTags
on pmt.TagId equals tag.ID
group pmt by pmt.Project into pmtGroup
select new
{
Project = pmtGroup.Key,
Tags = pmtGroup.Select(project => project.ProjectTag)
};
I want to return this query to a view using:
return View(query.ToList());
In the view file I have the following code:
@model IEnumerable<portfolio.Models.ProjectHasTag>
@foreach (var p in Model)
{
@p.Project.Title
foreach (var tag in p.Tags)
{
@tag.title
}
}
I get the following error:
The model item passed into the dictionary is of type 'System.Collections.Generic.List
1[<>f__AnonymousType6
2[portfolio.Models.Project,System.Collections.Generic.IEnumerable1[portfolio.Models.ProjectTag]]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable
1[portfolio.Models.ProjectHasTag]'.
The ProjectHasTag model code:
public class ProjectHasTag
{
public int ID { get; set; }
public int? ProjectId { get; set; }
[ForeignKey("ProjectId")]
[DisplayName("Project")]
public virtual Project Project { get; set; }
public int? TagId { get; set; }
[ForeignKey("TagId")]
[DisplayName("Tag")]
public virtual ProjectTag ProjectTag { get; set; }
public virtual ICollection<ProjectTag> Tags { get; set; }
}
This is what I want to achieve: http://i.stack.imgur.com/DAZ5n.png (I cant post images yet)
thanks for taking the time, English is not my first language.
The problem is this part of your query:
select new
{
Project = pmtGroup.Key,
Tags = pmtGroup.Select(project => project.ProjectTag)
};
You're not specifying the type that should be instantiated, so it's creating an anonymous type, which is then being passed to your view. You probably want something like this:
select new ProjectHasTag
{
Project = pmtGroup.Key,
Tags = pmtGroup.Select(project => project.ProjectTag)
};
Update
Just as the error is telling you, ProjectHasTag
does not have a Tags
property. It looks like what you want is really this:
select new ProjectHasTag
{
Project = pmtGroup.Key,
ProjectTag = pmtGroup.Select(project => project.ProjectTag)
};
However, it's a little unclear what you're trying to do because in your view it looks as though you have multiple tags for each project, in which case it should really be a collection. Something like:
public virtual ICollection<ProjectTag> Tags { get; set; }
Update Two
I forgot the Entity Framework (EF) is picky when it comes to directly instantiating entity types. For a quick fix, you should be able to map from an anonymous type to the entity type (as described here ).
However, EF doing this is actually a good thing because it's forcing you to adopt a design strategy that will allow you to leverage more power from MVC. In particular, this would be a good time to learn about ViewModels (see: ASP.NET MVC - How exactly to use View Models and http://geekswithblogs.net/michelotti/archive/2009/10/25/asp.net-mvc-view-model-patterns.aspx ).
In the select part of your query, you create an anonymous object, and your model requires objects form type ProjectHasTag
. So this should look like (look at the select new ProjectHasTag
):
var query = from pmt in db.ProjectHasTags
join project in db.Projects on pmt.ProjectId equals project.ID
join tag in db.ProjectTags
on pmt.TagId equals tag.ID
group pmt by pmt.Project into pmtGroup
select new ProjectHasTag
{
Project = pmtGroup.Key,
Tags = pmtGroup.Select(project => project.ProjectTag)
};
Since you have an ICollection , you are telling Linq, that you want your ProjectTags to be lazy loaded. Like @John H said above, since you have added the Tags property to your ProjectHasTag class, you can populate it such:
select new ProjectHasTag
{
Project = pmtGroup.Key,
Tags = pmtGroup.Select(project => project.ProjectTag)
};
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.