5

In my MVC Application:

In the controller I created a list of dynamic type, which is stored in the session. The view then attempts to access the objects but it throws an exception : 'object' does not contain a definition for 'a'

The code :

// Controller 

List<dynamic> myLists = new List<dynamic>();
for(int i=0; i<3; i++){
    var ano = new { a='a' , b = i };
    myLists.Add(ano);
}

Session["rows"] = myLists;

In my view

// My View
foreach( dynamic row in (Session["rows"] as List<dynamic>)){
    <div>@row</div> // output {a:'a', b :1}
    <div>@row.a</div> // throw the error.
}

Note

  1. At the debug time, in the watch view I can see the properties/values
  2. I can't store the list in the ViewBag in my case because I used ajax to call the method
  3. I tried to use var, object instead of dynamic => the same result
  4. I think this is not related to MVC or Razor engine
  5. I tried to use a aspx view (not the razor one) and the same result

Why I can't access the property, if the debugger can see it, and how can I solve this problem ?

amd
  • 20,637
  • 6
  • 49
  • 67
  • Can you post exactly what type of result your controller action is returning please? I am wondering if it is a JsonResult. – Justin Harvey Aug 13 '12 at 07:57
  • See, I think your "4" is incorrect; I remember hitting *exactly* this problem with MVC/Razor - it went away with service packs. My guess is that the razor view compilation process needed to be told "and by the way, you need to pretend you're part of this dll over here" – Marc Gravell Aug 13 '12 at 08:01
  • @JustinHarvey, Yes currently the return type is JsonResult, but I dont care about it in this situation – amd Aug 13 '12 at 08:06
  • Hi Marc, while you may well be right, I am wondering if this were the case, how the ViewBag, which is itself a dynamic, would ever work? – Justin Harvey Aug 13 '12 at 08:08
  • 1
    @JustinHarvey ViewBag is not a regular type - accessibility only applies to reflection access. ViewBag is essentially a wrapper around a dictionary. Different rules. Specifically, ViewBag implements `IDynamicMetaObjectProvider` – Marc Gravell Aug 13 '12 at 08:10
  • @Ahmad, the reason I was asking is that I am trying to understand the way you are making this call. Could you post the code in the view you use to make this call and receive the result please? – Justin Harvey Aug 13 '12 at 08:12
  • Take a look at this: http://stackoverflow.com/questions/5120317/dynamic-anonymous-type-in-razor-causes-runtimebinderexception – Charlie Aug 13 '12 at 08:17
  • @JustinHarvey, I am using jquery to post to the controller, I edited my code above. – amd Aug 13 '12 at 08:32
  • That jquery just shows an alert, I don't quite understand how that relates to the code you have accessing the dynamic. – Justin Harvey Aug 13 '12 at 08:35
  • when the user click on a anchor, it will post to the controller, then the controller will add the object to the session, then a message appear for the visitor that the operation is done. in another pages ( view ) I want to display the values stored in the session, (like a shopping cart the user will add products, then in another page he will see the list of products) – amd Aug 13 '12 at 08:45

1 Answers1

4

Anonymous types are internal to the assembly that declares them. The dynamic API respects accessibility. Since the value is there (from "// output..."), I must conclude this is an accessibility issue. IIRC early builds of razor/MVC3 had an issue with exactly this scenario, although from memory that problem went away with one of the service packs - you might want to check you are up-to-date with razor / MVC3 / .NET / VS patches. However, the easiest fix here will be to declare a proper POCO class:

public class MyViewModelType {
    public char A {get;set;}
    public int B {get;set;}
}

and use that instead of an anonymous type. This will also mean you don't need to use dynamic, which is unnecessary and overkill here.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Nice answer Marc. But I wonder how `ViewBag` work then? `ViewBag` is also dynamic right? – Mohayemin Aug 13 '12 at 08:09
  • 1
    @Mohayemin ViewBag is not a regular type - accessibility only applies to reflection access. ViewBag is essentially a wrapper around a dictionary. Different rules. Specifically, ViewBag implements `IDynamicMetaObjectProvider` – Marc Gravell Aug 13 '12 at 08:12
  • Thanks Mark, in the real case, the type is more complicated and I have many types, and i am wondering if i can solve this without using predifened classes – amd Aug 13 '12 at 08:15
  • I remember, once I read that `ViewBag` actually wraps `ViewData`. – Mohayemin Aug 13 '12 at 08:17
  • @Ahmad have you tried updating to the latest versions of Razor, MVC, VS, .NET ? – Marc Gravell Aug 13 '12 at 08:24
  • @Mohayemin exactly, which is a dictionary – Marc Gravell Aug 13 '12 at 08:24
  • @Marc, No, I will try tonight, hope this fix the problem – amd Aug 13 '12 at 08:27
  • @MarcGravell Hi, can you explain plz more about `Since the value is there (from "// output...")` or send me a link to know more about this – amd Nov 12 '12 at 08:14
  • @Ahmad the `@row` usage is going to call `@row.ToString()`, which is a virtual method which (for anon types) simply writes the member-contents - the key point of that, though, is that it shows the data is there. If it isn't available, then it must be an accessibility issue. – Marc Gravell Nov 12 '12 at 08:32