Search code examples
c#asp.net-mvcreflectionexpandoobjectdynamicobject

Create dynamic object with unknown property types


I want to create a generic server-side DataTable solution on a ASP.NET MVC application. What I have on each Index view would be a JQuery datatable with a AJAX call to the controller to retrieve the paged data result. The operations performed are as follows:

public JsonResult GetNewRequests([ModelBinder(typeof(DataTablesModelBinder))] DataTablesPageRequest pageRequest)
{
    var page = RequestsQuery(pageRequest); // Retrieves page of result from db and does any filtering + sorting
    var pageResponse = DataTablesFormat.PageResponse(pageRequest, page); // Formats response for jQuery DataTable to use
    return Json(pageResponse, JsonRequestBehavior.AllowGet); // Returns result
}

The response returned to the jQuery DataTable control is in the following format:

return new
{
    sEcho = pageRequest.Echo,
    iTotalRecords = report.TotalItems,
    iTotalDisplayRecords = report.TotalItems,
    sColumns = pageRequest.ColumnNames,
    aaData = results
};

The part I'm working on is formulating the list of model items to return ie:

aaData = results

results should be a list of any model object including all its relevant properties. I've been trying to use reflection together with ExpandoObject to complete this solution but cannot figure out the mechanics:

public static object PageResponse(DataTablesPageRequest pageRequest, Page<object> report)
{
    List<object> results = new List<object>();

    foreach(var item in report.Items)
    {
        dynamic dynamicObject = new ExpandoObject();
        Type type = item.GetType();
        PropertyInfo[] properties = type.GetProperties();

        foreach(PropertyInfo property in properties)
        {
            Type propertyType = property.PropertyType;
            // Here is where I want to add a property with the correct name of the required type to the dynamic object
            dynamicObject[property.Name] = property.GetValue(item, null) as propertyType;
        }

        results.Add(dynamicObject);
    }

    return new
    {
        sEcho = pageRequest.Echo,
        iTotalRecords = report.TotalItems,
        iTotalDisplayRecords = report.TotalItems,
        sColumns = pageRequest.ColumnNames,
        aaData = results
    };
}

I've figured out a few things even while typing this. The part I cannot figure out:

dynamicObject[property.Name] = property.GetValue(item, null) as propertyType;

That is, setting property type eg: DateTime.

Let me repeat. I want to construct a list of model items. This can be any model type with any number of properties that each can be of any type (int, string, bool, DateTime, etc.)


Solution

  • You need to cast your expando to an IDictionary<string, object> if you want to be able to add properties dynamically:

    foreach(var item in report.Items)
    {
        dynamic dynamicObject = new ExpandoObject();
        var dic = dynamicObject as IDictionary<string, object>;
        var properties = item.GetType().GetProperties();
    
        foreach(PropertyInfo property in properties)
        {
            dic[property.Name] = property.GetValue(item, null);
        }
    
        // At this stage the dynamicObject will contain properties with correct
        // names and types
    
        results.Add(dynamicObject);
    }