2

I have an ASP.NET MVC app. I am using the ExpandoObject in my app. Currently, I have the following block in my .cshtml file:

foreach (System.Dynamic.ExpandoObject expo in ViewBag.ExpandoObjects)
{
  <div>@filter.GetType().FullName</div>
}  

This code works fine. In fact, it prints out System.Dynamic.ExpandoObject onto the screen like I'd expect. However, when I update the code to the following, I get an error.

foreach (System.Dynamic.ExpandoObject expo in ViewBag.ExpandoObjects)
{
  foreach (var key in expo.Keys) 
  {
    <div>@key</div>
  }
}                  

The error says:

CS1061: 'System.Dynamic.ExpandoObject' does not contain a definition for 'Keys' and no extension method 'Keys' accepting a first argument of type 'System.Dynamic.ExpandoObject' could be found (are you missing a using directive or an assembly reference?)      

I do not understand why I'm getting this error. According to the documentation, there is a Keys property. What am I missing?

xam developer
  • 1,923
  • 5
  • 27
  • 39

1 Answers1

3

The Keys property is explicitly implemented for the IDictionary interface. This, for example, won't compile:

Console.WriteLine(new ExpandoObject().Keys);

If you want to use Keys you'll have to cast it as an IDictionary.

foreach (System.Dynamic.ExpandoObject expo in ViewBag.ExpandoObjects)
{
  foreach (var key in ((IDictionary<string, object>)expo).Keys) 
  {
    <div>@key</div>
  }
}  

If you want to access a key by a name you know at compile-time, you can either use a dictionary indexer or cast the object as dynamic.

foreach (IDictionary<string, object> expo in ViewBag.ExpandoObjects)
{
    <div>@expo["name"]</div>

or

foreach (dynamic expo in ViewBag.ExpandoObjects)
{
    <div>@expo.name</div>

Here's a brief code snippet to give you an idea of how to work with an ExpandoObject cast as an ExpandoObject, dynamic, or IDictionary<string, object>:

var obj = new ExpandoObject();
var dict = ((IDictionary<string, object>)obj);
var dyn = (dynamic) obj;
dyn.name = "Fred";
Console.WriteLine(dyn.name);  // "Fred"
var key = dict.Keys.Single();
Console.WriteLine(key);       // "name"
Console.WriteLine(dict[key]); // "Fred"

Note that I strongly advise you use strongly-typed view models if at all possible. dynamic typing is good for what it's made for, but will kill maintainability if overused.

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
  • When I do this, I see "name" in the list. But, if I say `
    @expo.name
    ` I get an error that says `CS1061: 'System.Dynamic.ExpandoObject' does not contain a definition for 'name' and no extension method 'name' accepting a first argument of type 'System.Dynamic.ExpandoObject' could be found`. I don't get it. How do I get a property value out of an `ExpandoObject`.
    – xam developer Jan 19 '15 at 20:09
  • @xamdeveloper: If you want to treat it as a dynamic object, you need to cast it as `dynamic`. – StriplingWarrior Jan 19 '15 at 20:15