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

2
  • 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? Commented Apr 13, 2015 at 14:55
  • I have edited your title. Please see, "Should questions include “tags” in their titles?", where the consensus is "no, they should not". Commented Apr 13, 2015 at 14:56

2 Answers 2

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);
}
Sign up to request clarification or add additional context in comments.

2 Comments

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" ]
That is correct. That is how a dictionary is serialized into JSON.
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.