2

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?

1
  • I side with Mark and Will. Using actual model classes to encapsulate the model data and business logic makes the code more legible and easier to maintain for the very minor cost of creating the class (a necessity anyways with a domain driven design). Commented Jun 2, 2009 at 16:40

3 Answers 3

5

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.

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

2 Comments

Thanks for your reply Will. I can see your point, I was kind of hoping I would be able to use anon types in my front end code somehow, but I guess not without it being too clean. I detest making display classes :)
Your display classes should encapsulate the loading logic for those classes. You shouldn't be loading data in your controllers; that's not in their job description. So you don't have to consider them as trash...
1

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

Comments

0

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

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.