Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic Anonymous type in Razor causes RuntimeBinderException

People also ask

What are difference between anonymous and dynamic types?

Anonymous type is a class type that contain one or more read only properties whereas dynamic can be any type it may be any type integer, string, object or class. Anonymous types are assigned types by the compiler. Anonymous type is directly derived from System.

What is difference between regular and anonymous data type in C#?

The compiler gives them a name although your application cannot access it. From the perspective of the common language runtime, an anonymous type is no different from any other reference type, except that it cannot be cast to any type except for object.

What is the use of anonymous type in C#?

Anonymous types typically are used in the select clause of a query expression to return a subset of the properties from each object in the source sequence. For more information about queries, see LINQ in C#. Anonymous types contain one or more public read-only properties.

Does ASP NET MVC use razor?

Razor has no ties to ASP.NET MVC because Razor is a general-purpose templating engine. You can use it anywhere to generate output like HTML. It's just that ASP.NET MVC has implemented a view engine that allows us to use Razor inside of an MVC application to produce HTML.


Anonymous types having internal properties is a poor .NET framework design decision, in my opinion.

Here is a quick and nice extension to fix this problem i.e. by converting the anonymous object into an ExpandoObject right away.

public static ExpandoObject ToExpando(this object anonymousObject)
{
    IDictionary<string, object> anonymousDictionary =  new RouteValueDictionary(anonymousObject);
    IDictionary<string, object> expando = new ExpandoObject();
    foreach (var item in anonymousDictionary)
        expando.Add(item);
    return (ExpandoObject)expando;
}

It's very easy to use:

return View("ViewName", someLinq.Select(new { x=1, y=2}.ToExpando());

Of course in your view:

@foreach (var item in Model) {
     <div>x = @item.x, y = @item.y</div>
}

I found the answer in a related question. The answer is specified on David Ebbo's blog post Passing anonymous objects to MVC views and accessing them using dynamic

The reason for this is that the anonymous type being passed in the controller in internal, so it can only be accessed from within the assembly in which it’s declared. Since views get compiled separately, the dynamic binder complains that it can’t go over that assembly boundary.

But if you think about it, this restriction from the dynamic binder is actually quite artificial, because if you use private reflection, nothing is stopping you from accessing those internal members (yes, it even work in Medium trust). So the default dynamic binder is going out of its way to enforce C# compilation rules (where you can’t access internal members), instead of letting you do what the CLR runtime allows.


Using ToExpando method is the best solution.

Here is the version that doesn't require System.Web assembly:

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;
}

Instead of creating a model from an anonymous type and then trying to convert the anonymous object to an ExpandoObject like this ...

var model = new 
{
    Profile = profile,
    Foo = foo
};

return View(model.ToExpando());  // not a framework method (see other answers)

You can just create the ExpandoObject directly:

dynamic model = new ExpandoObject();
model.Profile = profile;
model.Foo = foo;

return View(model);

Then in your view you set the model type as dynamic @model dynamic and you can access the properties directly :

@Model.Profile.Name
@Model.Foo

I'd normally recommend strongly typed view models for most views, but sometimes this flexibility is handy.


You can use the framework impromptu interface to wrap an anonymous type in an interface.

You'd just return an IEnumerable<IMadeUpInterface> and at the end of your Linq use .AllActLike<IMadeUpInterface>(); this works because it calls the anonymous property using the DLR with a context of the assembly that declared the anonymous type.