Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RuntimeBinderException when accessing dynamic anonymous type in view

I've encountered a strange anomaly while learning/tinkering with asp.net.

I'm trying to show a partial view like this:

@Html.Partial("_PartialView", new { Action = "Foo" })

When I'm trying to access Action with

// Throws Microsoft.Csharp.RuntimeBinder.RuntimeBinderException
string throwsException = Model.Action; 

a RuntimeBinderExceptionis with the message

'object' does not contain a definition for 'Action'

is thrown.
The strange thing is that this line works fine:

// This line works fine
string works = ((Type)Model.GetType()).GetProperty("Action").GetValue(Model);

This behavior puzzles me quite a bit and I'd rather avoid using this workaround. Also I don't think the problem is anonymous types being internal because the MVC template for ASP.NET Project in VS2013 does this successfully:

enter image description here

So what happened here?

like image 661
Kabbalah Avatar asked Nov 12 '13 17:11

Kabbalah


People also ask

Do anonymous types work with Linq?

Use anonymous types with LINQThe Select clause in LINQ creates and returns an anonymous type as a result. The following code snippet illustrates this.

What keyword do you use to declare an anonymous type?

The anonymous type declaration starts with the new keyword. The declaration initializes a new type that uses only two properties from Product .

What is anonymous data type in C#?

Anonymous types in C# are the types which do not have a name or you can say the creation of new types without defining them. It is introduced in C# 3.0. It is a temporary data type which is inferred based on the data that you insert in an object initializer.

What is runtime binder exception?

RuntimeBinderException(SerializationInfo, StreamingContext) Initializes a new instance of the RuntimeBinderException class that has serialized data. RuntimeBinderException(String) Initializes a new instance of the RuntimeBinderException class that has a specified error message. RuntimeBinderException(String, Exception)


2 Answers

The answer to this question can be found here: http://www.heartysoft.com/ashic/blog/2010/5/anonymous-types-c-sharp-4-dynamic

Pulling from the excellent blog post:

Anonymous Types are Internal

The reason the call to Model.Action fails is that the type information of Model is not available at runtime. The reason it's not available is because anonymous types are not public. When the method is returning an instance of that anonymous type, it's returning a System.Object which references an instance of an anonymous type - a type who's info isn't available to the main program. The dynamic runtime tries to find a property called Action on the object, but can't resolve it from the type information it has. As such, it throws an exception.

like image 189
Paul Avatar answered Oct 16 '22 21:10

Paul


So what happened here?

Your partial view is weakly typed. You do not have a @model definition for it. So by default it is object which obviously doesn't have an Action property.

The correct way to solve this is to define a view model:

public class MyViewModel
{
    public string Action { get; set; }
}

that your partial view will be strongly typed to:

@model MyViewModel
@{
    string throwsException = Model.Action; 
}

and which will be passed by the main view:

@Html.Partial("_PartialView", new MyViewModel { Action = "Foo" })

Another possibility (which personally I don't like as it relies on runtime binding) is to use a dynamic model in the partial view:

@model dynamic
@{
    string throwsException = Model.Action; 
}

and then you will be able to pass an anonymous object when calling it:

@Html.Partial("_PartialView", new { Action = "Foo" })
like image 3
Darin Dimitrov Avatar answered Oct 16 '22 21:10

Darin Dimitrov