1

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.)

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Carel
  • 2,063
  • 8
  • 39
  • 65
  • You can use `Convert.ChangeType`. The question is why would you want to do that? You're already using `dynamic`, are you trying to have it passed in place of an interface or what? – Luaan Apr 13 '15 at 14:55
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Apr 13 '15 at 14:56

2 Answers2

1

As Luaan already commented, Convert.ChangeType is the answer to your question.

However, using this won't help you any moment. Why? Since casting an object value will only help if you want to assign it to a variable of a specific type (opposed to object).

The underlying type of property.GetValue(item, null) will never change, so trying to cast it doesn't help.

Also, why not just use a List<Dictionary<string, object>> or even a List<object[]> (which I often use for data transfer purposes. There is no point in using dynamic or ExpandoObject here.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
1

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);
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • This seems to return an object in the following format: `[ {"Key":"LogId","Value":1509}, {"Key":"LogDate","Value":"\/Date(1428904824960)\/"}, {"Key":"LogLevel","Value":"Information"}, {"Key":"LogSource","Value":"EmailNotification"}, {"Key":"LogText","Value":"Notification Process stopped"} ]` as apposed to the format: `[ LogId:1509, LogDate:"\/Date(1428904824960)\/", LogLevel:"Information", LogSource:"EmailNotification", LogText:"Notification Process stopped" ]` – Carel Apr 13 '15 at 16:33
  • That is correct. That is how a dictionary is serialized into JSON. – Patrick Hofman Apr 14 '15 at 07:20