WellThisIsAkward
WellThisIsAkward

Reputation: 51

Displaying data from multiple models on one view (images and text)

Hi everyone so I am trying to create an application using asp.net mvc with a code first database that allows the users to be able to create a blog post with as many images as they wish.I have the data stored in the database but I I am currently trying to have the the head, body and images displaying in the display view this is what I would like it to look like : https://i.sstatic.net/xFfyI.jpg but I am not sure how to accomplish this. I am able to display the head and body but cannot get the images from the image table here is the database diagram: https://i.sstatic.net/P2z4o.jpg

Currently this is the error I get when i add this to the view @Html.DisplayFor(modelItem => item.Images)

An exception of type 'System.Data.Entity.Core.EntityCommandExecutionException' occurred in EntityFramework.SqlServer.dll but was not handled in user code

Additional information: An error occurred while executing the command definition. See the inner exception for details.

Model

public partial class PostModel
{
    public PostModel()
    {
        Images = new List<ImageModel>();
    }
    [Key]
    [HiddenInput(DisplayValue = false)]
    public int ID { get; set; }
    [Required(ErrorMessage = "Heading is Required")]
    [Display(Name = "Heading")]
    public string Heading { get; set; }
    [Required(ErrorMessage = "Body is Required")]
    [DataType(DataType.MultilineText)]
    [Display(Name = "Body")]
    public string Body { get; set; }
    public virtual ICollection<ImageModel> Images { get; set; }
    public IEnumerable<HttpPostedFileBase> File { get; set; }
}

public class ImageModel
{
    [Key]
    public int ID { get; set; }
    public string Path { get; set; }
    public virtual PostModel Post { get; set; }
    public string DisplayName { get; set; }
}
public class ImageVM
{
    public int? ID { get; set; }
    public string Path { get; set; }
    public string DisplayName { get; set; }
    public bool IsDeleted { get; set; }
}
public partial class PostVM
{
    public PostVM()
    {
       Images = new List<ImageVM>();
    }

    public int? ID { get; set; }
    public string Heading { get; set; }
    public string Body { get; set; }
    public IEnumerable<HttpPostedFileBase> Files { get; set; }
    public List<ImageVM> Images { get; set; }

}

DbContext

public class EFDbContext : DbContext
{    
    public DbSet<PostModel> Posts { get; set; }
    public DbSet<PostVM> PostVMs { get; set; }
    public DbSet<ImageModel> Images { get; set; }
    public DbSet<ImageVM> ImageVMs { get; set; }
}

Controller

 public ViewResult Display()
 {
        return View(repository.Posts) 
  }

View

@model IEnumerable<Crud.Models.PostModel>
@{
    ViewBag.Title = "Index";
}


    @foreach (var item in Model)
    {
     <div>
        @Html.DisplayFor(modelItem => item.Heading)
    </div>
    <div>
        @Html.DisplayFor(modelItem => item.Body)
    </div>
    <div>
        @Html.DisplayFor(modelItem => item.Images)
        @*<img class="img-thumbnail" width="150" height="150" src="/Img/@item.Images" />*@
    </div>

}

Here is alternative controller I tried but am not using as I got this error when i tried let Images = i.Path and wasn't really sure if this was meant to be how it was done

Cannot implicity convert typeCrud 'string' to 'System.Collections.Generic.List Crud.Models.ImageVm '

  public ViewResult Display()
        {

            IEnumerable<PostVM> model = null;
            model = (from p in db.Posts
                     join i in db.Images on p.ID equals i.Post
                     select new PostVM
                     {
                         ID = p.ID,
                         Heading = p.Heading,
                         Body = p.Body,
                         Images = i.Path
                     });
            return View(model);
        }

Upvotes: 0

Views: 222

Answers (1)

Shyju
Shyju

Reputation: 218852

item.Images is a collection. So loop through that and display the images.

<div>
    @foreach(var image in item.Images)
    {
       <img src="@image.Path" />
    }       
</div>

You need to make changes to the src property depending on what value you store in the Path property of image.

You can correct your other action method like this

public ViewResult Display()
{
    var posts = db.Posts.Select(d => new PostVM()
    {
        ID = d.ID ,
        Heading  = d.Heading,
        Body = d.Body,
        Images = d.Images.Select(i => new ImageVM() { Path = i.Path, 
                                                      DisplayName = i.DisplayName }
                                ).ToList()
    }).ToList();
    return View(posts);
}

Now since you are returning a list of PostVM, make sure your Display view is strongly typed to that.

@model List<PostVM>
<h1>Posts</h1>
@foreach(var p in Model)
{
  <h3>@p.Heading</h3>
  <p>@p.Body</p>
  @foreach(var image in item.Images)
  {
    <img src="@image.Path" />
  }
}

Also, there is no point in keeping the view model classes on your db context. Keep only your entity models. View models are only for the use of UI layer.

public class EFDbContext : DbContext
{    
    public DbSet<PostModel> Posts { get; set; }   
    public DbSet<ImageModel> Images { get; set; }
}

Upvotes: 0

Related Questions