1

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.List1[<>f__AnonymousType62[portfolio.Models.Project,System.Collections.Generic.IEnumerable1[portfolio.Models.ProjectTag]]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[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: https://i.sstatic.net/DAZ5n.png (I cant post images yet)

thanks for taking the time, English is not my first language.

1

3 Answers 3

4

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).

Sign up to request clarification or add additional context in comments.

13 Comments

I get the following error: 'portfolio.Models.ProjectHasTag' does not contain a definition for 'Tags', I my model ProjectHasTag missing something?
It would be helpful if you could edit your question to include the code for ProjectHasTag.
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; } } I added this code to the question.
I added the last line ( public virtual ICollection<ProjectTag> Tags { get; set; } ) to the Model: ProjectHasTag and it gives me the an error when I try to run it: Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<portfolio.Models.ProjectTag>' to 'portfolio.Models.ProjectTag'. An explicit conversion exists (are you missing a cast?)
It seems like projects can have multiple tags, since he is narrowing ProjectHasTags by ProjectId, and then finding the actual Tags by joining with Projects for every TagId in ProjectHasTags. I was thinking that he might be wanting to bind the Tags to dropdownlist, and then ProjectTag is the selected value from the list, but that does seem to be the case :)
|
0

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)
                    };

Comments

0

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)
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.