Binding views with Anonymous type collection in ASP.NET MVC

Sheonarayan
Posted by in ASP.NET MVC category on for Advance level | Points: 250 | Views : 48083 red flag
Rating: 4.33 out of 5  
 3 vote(s)

In this article, I am going to explain how to bind ASP.NET MVC views with anonymous type collection objects.
Recommendation
Read Difference between var and let keywords in JavaScript before this article.

Introduction


In general for every view in ASP.NET MVC, there is a dedicated Model that is specified as @model in the views file that is used to bind data to the Views. If not, we sometimes create a ViewModel that is basically properties of one or more model as per the need of the data that a view has to display.

In a scenario, where we are returning LINQ anonymous type object collection to the Views by joining more than one object collection, its impossible to bind to the views unless you have some workaround.


Objective


After spending couple of hours googling for the solution of binding anonymous type to the views and finally came up with this solution. The objective of this article is to demonstrate how to bind anonymous type collection to the ASP.NET MVC views in a pretty simple and straight forward way.


Some error you may get while binding Anonymous type to the Views


In general you may come across below errors when you are trying to bind anonymous type objects to the view (depending on which approach you are following)

  • The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[<>f__AnonymousType7`9[System.Int32,System.String, System.Int32,System.Int32,System.DateTime,System.String,System.String,System.String,System.String]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[xxxModel]'.

  • The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[<>f__AnonymousType7`9[System.Int32,System.String, System.Int32,System.Int32,System.DateTime,System.String,System.String,System.String,System.String]]', but this dictionary requires a model item of type 'System.Collections.Generic.List`1[System.Object]'. 

  • System.NotSupportedException: LINQ to Entities does not recognize the method 'System.Dynamic.ExpandoObject ToExpando(System.Object)' method, and this method cannot be translated into a store expression.

Lets see how to bind Anonymous type collections to the ASP.NET MVC Views


In my case my modified ASP.NET MVC view is below, notice lines that are in bold.

@model IEnumerable<dynamic>

<div class="leftPanel">
    <div class="spacerBody">
        <div class="table">
            @foreach (dynamic item in Model)
            {    
                <div class="tr">
                    <div class="td">
                        <span class="listTitle"><a href="@Url.RouteUrl("Default", new { controller = "Chart", action = "DesignChart", id = item.AutoId, title = item.NameOfTheChart">@item.NameOfTheChart</a></span><br />
                        <div class="desc">@Html.Raw(item.CategoryName) </div>
</div> </div> } </div> </div> </div>
Code Snippet - 1 (View)

Notice the first line of code, its @model IEnumerable<dynamic> (dynamic, not a model class), this is very important as we are going to bind the anonymous type object.

Again notice the @foreach, here also we are using dynamic keyword instead of var.

Now, lets see the Controller method


        public ActionResult Index()
        {
            dynamic charts = (from ch in db.ChartModels
                             join
                             ca in db.CategoryModels
                             on ch.CategoryId equals ca.CategoryId
                             where ch.Active == true && ch.IsPublished == true && ch.IsPublic == true
                             select new
                {
                    ch.AutoId,
                    ch.NameOfTheChart,
                    ca.CategoryName
                }).AsEnumerable().Select(c => c.ToExpando());

            return View(charts);
        }

Important:
 Make sure that you are using the namespace of the ToExpando() method (declared in the last code snippet of this article) in this controller otherwise c.ToExpando() method will not appear.

Notice that the return result of the LINQ query is also dynamic

In the above method, we are returning fields from two Model collections by joining both on CategoryId.

ToExpando() method

Also notice the ToExpando() extension method at the last of the LINQ query. ToExpando is an extension method defined by me in a new static class file in my project. You can define this extension method in any static class file into your Project.

The namespace to be used into this static class is following.

using System.Dynamic;
using System.Web.Mvc;
using System.Collections.Generic;

    public static class impFunctions
    {
        public static ExpandoObject ToExpando(this object anonymousObject)
        {
            IDictionary<string, object> anonymousDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(anonymousObject);
            IDictionary<string, object> expando = new ExpandoObject();
            foreach (var item in anonymousDictionary)
                expando.Add(item);
            return (ExpandoObject)expando;
        }
   }
What is ExpandoObject?
ExpandoObject is an object whose members can be dynamically added and removed at run time. This ExpandoObject is very helpful in our case when we have to return the anonymous type collection to the view as we are going to add our anonymous type objects as the collection of ExpandoObjects. ExpandoObject  is very flexible and dynamic in nature. To know more about it read here.

The above extension method "ToExpando" is self explanatory however to sum up its basically creating a Dictionary of objects based on the objects being passed to this method and then adding those objects into a dictionary of ExpandoObject type and returning it. 

Once you have returned the ToExpando() from the Controller method, you are done as everything is already setup in the our Views (see above).  

The Code Snippet - 1 (View) is looping through the Model (in this case ExpandoObject that is basically a collection of Anonymous type objects) and accessing its properties to list  the data.

Conclusion


Returning anonymous type object collection to the views and binding them is not straight forward in ASP.NET MVC, so the ExpandoObject comes to the rescue and helps us to bind as if we are returning ViewModel object.

Hope this solution will be helpful for people looking for the solution. Should you have any question or facing any problem while working on this, let me know by responding to this article. 

Do share this article to your friends and colleague to help them.

Recommendation
Read Single Page Application example download after this article.
Page copy protected against web site content infringement by Copyscape

About the Author

Sheonarayan
Full Name: Sheo Narayan
Member Level: HonoraryPlatinum
Member Status: Administrator
Member Since: 7/8/2008 6:32:14 PM
Country: India
Regards, Sheo Narayan http://www.dotnetfunda.com

Ex-Microsoft MVP, Author, Writer, Mentor & architecting applications since year 2001. Connect me on http://www.facebook.com/sheo.narayan | https://twitter.com/sheonarayan | http://www.linkedin.com/in/sheonarayan

Login to vote for this post.

Comments or Responses

Posted by: rajeshgajra19889-26855 on: 9/16/2014 | Points: 25
hello sir, great solution with simple explaination...

Login to post response

Comment using Facebook(Author doesn't get notification)