1

I'm still learning the MVC way of doing web development.

I have a partial view that renders information for a single photo (picture, username, f-stop, other info)

I have several pages where I want to display lists of photos. For example, on my homepage, I want to display the most recent photos to be added to the site.

My current approach to doing this is that I have added a GetNewestPhotos() function to my PhotoController that goes to the database to get the most recent photo records, and, for each one, renders the partialview and concatenates it to the result string (using the nasty-looking RenderPartialViewToString found here). Then client side, I request this string via AJAX and populate a div with the result.

I'm almost sure that this is wrong. How should I do it?

John Shedletsky
  • 7,110
  • 12
  • 38
  • 63

2 Answers2

2

In your controller method, return a partial view and inject your compound object into the view

public class CompoundType
{
    public List<Photo> Photos { get; set; }
}

public ActionResult GetNewestPhotos()
{
    CompoundType model = provider.GetPhotosFromDbAsCompoundObject();
    return PartialView("ViewName", model);
}

In your view, specify that your view's model should be your compound object.

@model CompoundType

At that point, simply iterate over the properties and/or collections in your object to render them into html.

@foreach (var photo in Model.Photos) 
{
    @Html.Raw(photo.Name).
    ...
}

There are a number of reasons why this is preferable over your current approach.

  1. Razor gives you strong typing. You can see what your types are and you get vastly more useful runtime exceptions, allowing you to troubleshoot issues more easily.

  2. In your current paradigm, you are actually doing work twice. You are creating the partial views, but then you are taking them and splicing them together on the client. This is redundant work.

  3. Maintainability. Other devs expect to see the pattern I've outlined. By being consistent, you'll find more useful information online and be able to solve problems more quickly when you encounter them. In addition, you can more easily hand over your project with less knowledge transfer.

David L
  • 32,885
  • 8
  • 62
  • 93
0

You have a view model for the page that contains a list of the photo view models. This page view model contains a list of viewmodels for the photos. In the View for the main page call:

@Html.DisplayFor(m => m.PhotosView)

This will render each view model using the default view you defined.

edit

class MainPageController
{
  ActionResult Index()
  {
   var model = new MainPageViewModel
   {
    Photos = GetListOfPhotoViewModelsOrderedByAge(SomeDataSource),  
  }
  return View(model)
}

class MainPageViewModel
{
 // various other properties
 IList<PhotoViewModels> Photos {get; set;}
}

class PhotoViewModel
{
 // properties to display about the photo (including hte path to the actual image)
}

The Razor views (mainpage)

@model MainPageViewModel
@Html.DisplayFor(m =>m.Photos)
@* other things on the page *@

Photo view (in the shared/display directory)

@model PhotoViewModel
<img url="@Model.PathToImage" />

I haven't tried this and it's mostly from ther top of my head, there may be slight syntax errors.

THBBFT
  • 1,161
  • 1
  • 13
  • 29