Question

Into some view data i have put the result of an anonymous type:

            var projectData = from p in db.Projects
                          orderby p.title
                          select new
                          {
                              Title = p.title,
                              DevURL = p.devURL ?? "N/A",
                              QAURL = p.qaURL ?? "N/A",
                              LiveURL = p.liveURL ?? "N/A",
                              Users = p.GetUsers().MakeUserList()
                          };

        ViewData["ProjectSummary"] = projectData;

How do I iterate through this view data in the MVC view on the front end to say, make a table of results?

Was it helpful?

Solution

In your case it would be much simpler to create a model to hold your data rather than using an anonymous type.

The issue you're having is that your anonymous type is cast to an object when its stored within the ViewData. On the UI side, when you get that object out, the only way to access its properties is to use reflection. You do NOT want to do this in your UI. It will be highly ugly. Instead, just add the following class to your Models:

public class Project{

public string Title {get;set;}
public string DevUrl {get;set;}
public string QAUrl {get;set;}
public string LiveUrl {get;set;}
public IEnumerable<User> Users {get;set;}

public static IEnumerable<Project> RetrieveAllProjects()
{
  return from p in db.Projects
           orderby p.title
           select new Project
             {
                Title = p.title,
                DevURL = p.devURL ?? "N/A",
                QAURL = p.qaURL ?? "N/A",
                LiveURL = p.liveURL ?? "N/A",
                Users = p.GetUsers().MakeUserList()
             };
}

In your controller do this:

public ActionResult Index()
{
  return View("Index", Project.RetrieveAllProjects());
}

and in your view's codebehind, strongly type it thusly:

//snip
public partial class Index : ViewPage<IEnumerable<Project>>
{
//snip

You might think its a bit wasteful to have all these models laying around, but its much easier to understand, and makes your UI code much slimmer, if you use your models wisely.

Also, a model is a great place (and, in fact, should be where you do it) to place the logic for loading your data and constructing the models themselves. Think ActiveRecord. And, while you're coding all this, realize that projects like SubSonic create your models for you without any muss or fuss.

OTHER TIPS

Not tried this with an anonymous type but this is how i do it by passing a List<T> object to ViewData

<% foreach (Project p in (IEnumerable<Project>)ViewData["ProjectSummary"]) { %>
     <%= Html.Encode(p.Title) %>
<% } %>

Hope this is what your looking for.

Mark

The problem is not that it's an anonymous type. The problem is that it's merely a lazy-evaluated IQueryable<> object, and it hasn't been evaluated yet.

I can't answer for ASP.NET MVC, but in the very similar Monorail, you would have to convert it from an iterator into an actual collection:

        var projectData = (from p in db.Projects
                      orderby p.title
                      select new
                      {
                          Title = p.title,
                          DevURL = p.devURL ?? "N/A",
                          QAURL = p.qaURL ?? "N/A",
                          LiveURL = p.liveURL ?? "N/A",
                          Users = p.GetUsers().MakeUserList()
                      }).ToList();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top