8

I'm trying to pass dynamic results to View from Controller, method ShowColor returns dynamic results. In View I try to loop through the collection but I'm getting error

'object' does not contain a definition for 'ColorID'.

I have the following code in Controller and View

public class myColor
{
    public int ID { get; set; }
    public string  Name { get; set; }
    public string Like { get; set; }
}

public dynamic ShowColor()
{
    IList<myColor> color = new List<myColor>();
    color.Add(new myColor { ID = 1, Name = "Red", Like = "***" });
    color.Add(new myColor { ID = 2, Name = "Green", Like = "*****" });
    color.Add(new myColor { ID = 3, Name = "Blue", Like = "**" });
    color.Add(new myColor { ID = 4, Name = "Yellow", Like = "*" });

    var select = (from c in color
                  select new
                  {                     
                      ColorID = c.ID,
                      ColorName = c.Name
                  }).ToList();

    return select;
}
public ActionResult DBDynamic()
{
    return View(ShowColor());
}

View

@model dynamic

@{
    ViewBag.Title = "DBDynamic";
}

<h2>DBDynamic</h2>

<p>
    <ul>
        @foreach (var m in Model)
        {
            <li> @m.ColorID</li>            
        }
    </ul>

</p>

Error

Debug Image

Found the solution here and a nice blog here:

public static ExpandoObject ToExpando(this object anonymousObject)
{
    IDictionary<string, object> expando = new ExpandoObject();
    foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(anonymousObject))
    {
        var obj = propertyDescriptor.GetValue(anonymousObject);
        expando.Add(propertyDescriptor.Name, obj);
    }

    return (ExpandoObject)expando;
}

And call it like this

    var select = (from c in color
                select new
                {
                    ColorID = c.ID,
                    ColorName = c.Name
                })
                .AsEnumerable()
                .Select(x => x.ToExpando());

return View(select);
sairfan
  • 970
  • 2
  • 12
  • 20

1 Answers1

6

An anonymous object is not the same thing as a dynamic. If you want to use it like a dynamic then cast it to that:

@foreach (dynamic m in Model)

However, dynamics are best avoided if at all possible. You lose all compile-time checking and even intellisense. You won't know if you fat-fingered a property name until runtime or even if you've accidentally used the wrong type of thing the wrong way until runtime. If something is broken, you want to know about it at compile-time, not when it's already live and affecting users, when you may not even know that an error has occurred unless a user notifies you. That's a horrible situation for your app to be in.

Long and short, use strong types. If you want something with properties, ColorID and ColorName, create a view model with those properties and select your query into instances of that type. Then, everything will be nice and strongly-typed and you'll know well in advance if there's some error or problem with your code.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • getting same error message. – sairfan Dec 08 '14 at 21:44
  • perhaps the problem is that your model itself is dynamic. Change it to `List` or `IEnumerable` and see what happens. – Chris Pratt Dec 08 '14 at 21:46
  • IEnumerable, List do not work, same error report – sairfan Dec 09 '14 at 15:27
  • "dynamics are best avoided" is not true. When you use dynamics you want to use variables at runtime so compile time checking is not needed. You want to create objects on-the-fly. You create strong types if you want to use those multiple times. Best said with dynamics you want to mimic Javascript behavior and sometimes that can be good. – Herman Van Der Blom Jul 05 '17 at 08:12
  • @HermanVanDerBlom: Dynamics are *easier* sure, but as with most things in life, that ease is a tradeoff. Here, you're introducing a potential vector for errors in your application. If you're doing something like `ViewBag.Title = "Foo"`, it's highly unlikely you'll mess that up, so you're probably fine. However, the more complex you go, the more chance something will break. Runtime errors are the bane of a successful app. – Chris Pratt Jul 05 '17 at 12:48