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