2
votes

I am sure this is relatively simple, I just keep running into brick walls. I have two entity classes set up like so:

public class Post
{
    public int Id { get; set; }
    public string Title { get; set; }
    public DateTime CreatedDate { get; set; }
    public string Content { get; set; }
    public string Tags { get; set; }
    public ICollection<Comment> Comments { get; set; }
}

public class Comment
{
    public int Id { get; set; }
    public string DisplayName { get; set; }
    public string Email { get; set; }
    public DateTime DateCreated { get; set; }
    public string Content { get; set; }
    public int PostId { get; set; }
    public Post Post { get; set; }
}

And I set up my ViewModel like this:

public class PostCommentViewModel
{
    public Post Post { get; set; }
    public IQueryable<Comment> Comment { get; set; }

    public PostCommentViewModel(int postId)
    {
        var db = new BlogContext();

        Post = db.Posts.First(x => x.Id == postId);
        Comment = db.Comments;
    }
}

And I have my Controller doing this:

public ActionResult Details(int id = 0)
    {
        var viewModel = new PostCommentViewModel(id);
        return View(viewModel);
    }

And then the view looks like this:

@model CodeFirstBlog.ViewModels.PostCommentViewModel


<fieldset>
<legend>PostCommentViewModel</legend>
@Html.DisplayFor(x => x.Post.Title)
<br />
@Html.DisplayFor(x => x.Post.Content)
<br />
@Html.DisplayFor(x => x.Post.CreatedDate)
<hr />    
@Html.DisplayFor(x => x.Comment)
</fieldset>

The result IS displaying data, but not quite what I want for the comments.

enter image description here

You see that the comments (There are two of them) and just showing the id property on each one "12"

How can I get it to go into and display the comment details specific to this particular post? I imagine a foreach loop is in order, but i cant figure out how to drill into the Model.Comment property correctly.

I tried this:

@foreach(var item in Model.Comment)
{
@Html.DisplayFor(item.DisplayName)
@Html.DisplayFor(item.Content)
@Html.DisplayFor(item.DateCreated)
}

But the error I get is "The type arguments for method 'System.Web.Mvc.Html.DisplayExtensions.DisplayFor(System.Web.Mvc.HtmlHelper, System.Linq.Expressions.Expression>)' cannot be inferred from the usage. Try specifying the type arguments explicitly."

Not sure what I am supposed to do here..

3

3 Answers

3
votes

Loop around the comments model:

@model CodeFirstBlog.ViewModels.PostCommentViewModel


<fieldset>
<legend>PostCommentViewModel</legend>
@Html.DisplayFor(x => x.Post.Title)
<br />
@Html.DisplayFor(x => x.Post.Content)
<br />
@Html.DisplayFor(x => x.Post.CreatedDate)
<hr />    
@foreach(var comment in Model.Comment) {
    @Html.DisplayFor(x => comment)
}
</fieldset>
0
votes
public class PostCommentViewModel 
{ 
    public Post Post { get; set; } 
    public IQueryable<Comment> Comment { get; set; } 

    public PostCommentViewModel(int postId) 
    { 
        var db = new BlogContext(); 

        Post = db.Posts.First(x => x.Id == postId); 
        Comment = Post.Comments; 
    } 
} 

And did you make Html helper method for Comment class?

0
votes

Create a DisplayTemplate for your Comment class and it should work, there is no need to iterate over the collection the view engine does it for you.

As per my comment, this is all you need to do to create a display template for your Comment class:

Create a DisplayTemplates subfolder inside your view folder and inside this create a new partial view called Comment.cshtml. Your template could look like this:

@model CodeFirstBlog.ViewModels.Comment

<div class="comment">
    @Html.DisplayFor(m => m.DisplayName)
    ....
</div>

And that's it! If you need more control over how your comment is displayed then you can simple tweak the template to suit.