views:

330

answers:

2

So I have this LINQ query that ends in a custom select kinda like this:

select new { this1 = table.this1, this2 = othertable.this2 }

The call to that query from the Controller looks something like this:

ViewData["these"] = theRepo.GetAllThese(someVar, anotherVar);

Now when I pass this on to my view since it is not strongly typed how can I iterate through it with a foreach, how can I cast it as an IQueryable or a List if I don't know what's in it?

...is it something like this?

IQueryable<???> these = ViewData["These"];
foreach (var this in these) {...

Just need to know what to put for '???' I think.

+2  A: 

You cannot use an anonymous type (select new { Property = value }) outside the scope in which it is defined. So you should use foreach(var x in {yourQueryHere}) from within the method you defined the query in.

Example: This is possible:

    public void myMethod() {
        var x = from c in IEnumerable select new { Prop = value };
        foreach (var y in x) {
        }
    }

This is impossible:

    public void myMethod() {
        foreach (var y in myMethod2()) {
        }
    }

    public IQueryable<???> myMethod2() {
        return from c in IEnumerable select new { Prop = value };
    }
Webleeuw
+1  A: 

Your linq query returns a collection of anonymously typed objects. Being anonymous, there is no way to "call their name" when declaring an explicitly typed variable. Thus, the true type/shape of the objects is only known within the action method where the objects are defined.

The indexed getter of the ViewData object has a return type of object, and without knowing the type name, you want be able to cast the return value of ViewData["these"] to anything useful.

What you might want to do instead, is to create a model - more specifically a "view model" - which defines the structure of the objects you are selecting using LINQ:

public class FoobarViewModel
{
    public string Foo { get; set; }
    public string Bar { get; set; }
}

and redefine your query to do a select like this:

select new FoobarViewModel { foo = table.this1, bar = othertable.this2 }

Your objects now share a common named class, and your collection can be easily casted to the proper type in the view.

Jørn Schou-Rode