tags:

views:

1792

answers:

7

I've just started working with ASP.NET MVC now that it's in beta. In my code, I'm running a simple LINQ to SQL query to get a list of results and passing that to my view. This sort of thing:

var ords = from o in db.Orders
           where o.OrderDate == DateTime.Today
           select o;

return View(ords);

However, in my View, I realised that I'd need to access the customer's name for each order. I started using o.Customer.Name but I'm fairly certain that this is executing a separate query for each order (because of LINQ's lazy loading).

The logical way to cut down the number of queries would be to select the customer name at the same time. Something like:

var ords = from o in db.Orders
           from c in db.Customers
           where o.OrderDate == DateTime.Today
               and o.CustomerID == c.CustomerID
           select new { o.OrderID, /* ... */, c.CustomerName };

return View(ords);

Except now my "ords" variable is an IEnumerable of an anonymous type.

Is it possible to declare an ASP.NET MVC View in such a way that it accepts an IEnumerable as its view data where T is defined by what gets passed from the controller, or will I have to define a concrete type to populate from my query?

A: 

you may be able to pass an Object and use reflection to get your desired results. Have a look at ObjectDumper.cs (included in csharpexamples.zip) for an example of this.

John Boker
Yeah, I was thinking that using reflection to crack the anonymous type open and treat it as a Dictionary<string, object> might be the only solution. Bit of a bummer if that's the case.
Matt Hamilton
A: 

If I'm not mistaken, anonymous types are converted into strongly typed objects at compile time. Whether the strongly typed object is valid for view data is another question though.

Mitch
+1  A: 

This post shows how you can return an anonymous type from a method, but it is not going to suit your requirements.

Another option may be to instead convert the anonymous type into JSON (JavaScriptSerializer will do it) and then return that JSON to the view, you would then need some jQuery etc to do what you like with it.

I have been using Linq to 'shape' my data into a JSON format that my view needs with great success.

zadam
The JSON idea sounds intriguing, but if I'm going to add code to do it then I might as well define a class that has my order and customer properties in it and abandon the anonymous type idea. +1 anyway though.
Matt Hamilton
Agreed. My primary JSON usage scenario has been returning a JSON object from an ajax call that is used to populate a grid (eg Flexigrid), the grid requires the data in a particular format, Linq rocks at helping me shape the data into that format.
zadam
+9  A: 

You can pass it to the view, but your view won't be strongly typed. But the helpers will work. For example:

public ActionResult Foo() {
  return View(new {Something="Hey, it worked!"});
}

//Using a normal ViewPage

<%= Html.TextBox("Something") %>

That textbox should render "Hey, it worked!" as the value.

Haacked
If anyone knows it'd be you, Phil. Thanks for being so accessible to plebs like me!
Matt Hamilton
Did this answer the question? I have this exact problem and this answer does not help. Could you maybe show how we can loop through ords and display in a view?
KP
It does not answer the question! Surprisingly it works for the textbox, but if I wanted just to render this value, how do I do it? <%= Model.Something %> doesn't work, you'll get 'object' does not contain a definition for 'Something' exception.
PawelRoman
+1  A: 

For what it's worth, tonight I discovered the DataLoadOptions class and its LoadWith method. I was able to tell my LINQ to SQL DataContext to always load a Customers row whenever an Orders row is retrieved, so the original query now gets everything I need in one hit.

Matt Hamilton
Wow... Huge thanks -- I've been looking frantically for this for the last several hours. I knew it must exist but wasn't sure where to look. Thanks man!
Andrew Flanagan
+1  A: 

You can write a class with the same properties of your anonymous type's, and you can cast your anonymous type to your hand-written type. The drawback is you have to update the class when you make projection changes in your linq query.

Alper Ozcetin
A: 

I'm with the same problem... after thinking a bit, I came to the conclusion that the most correct and most scalable solution, its to serialize this anonymous type before sending to the View. So, you can use the same method to fill the page using the View code behind and to populate your page using JSON