ian486 ian486 - 2 months ago 16
C# Question

MVC 5 Build a dynamic anonymous object

I am working on an MVC 5 application and trying to allow the user to write their own query and display the results in Jquery DataTables. I am having a hard time figuring out how to dynamically build an Anonymous JSON object depending on the users input.

In theory the user would send over a list of columns and a where clause to build a SQL query.
I would run the SQL query like this, and build out my object.

How do I dynamically build out this "select new { DT_RowId = a.id, name = a.name, number = a.number }" depending on what the user inputs.

var v = (from a in dc.Products.SqlQuery(querystring) select new { DT_RowId = a.id, name = a.name, number = a.number }).ToList();


Ultimately the JSON reponse is

data":[{"id":56,"name":"Product 55","number":"55"}]

It works fine when hard coded. Otherwise I will have to Select * from products and then show/hide columns on the client side, thus making my Data Payload very large if all columns are coming back from server.

Is there a way to loop through the requested properties to build this anonymous object? I tried to use a Dictionary however the Json returned was very different, it had Key and Value in it, and that is not what DataTables is expecting.

Thanks!

FULL CONTROLLER CODE

using (DataTableExampleContext dc = new DataTableExampleContext())
{
var v = (from a in dc.Products.SqlQuery(querystring) select new { DT_RowId = a.id, name = a.name, number = a.number }).ToList();

recordsTotal = v.Count();
var data = v.Skip(skip).Take(pageSize).ToList();


return Json(new { draw = draw, recordsFiltered = recordsTotal, recordsTotal = recordsTotal, data = data }, JsonRequestBehavior.AllowGet);
}


Solution Thanks to Phillipe

using (DataTableExampleContext dc = new DataTableExampleContext())
{
var v = (from a in dc.Products.SqlQuery(querystring) select GetResult(a, ColumnNames)).ToList();

recordsTotal = v.Count();
var data = v.Skip(skip).Take(pageSize).ToList();

return Json(new { draw = draw, recordsFiltered = recordsTotal, recordsTotal = recordsTotal, data = data }, JsonRequestBehavior.AllowGet);
}
}

public Dictionary<string,object> GetResult(Product p, List<string> columnNames)
{
var properties = TypeDescriptor.GetProperties(typeof(Product));
var dict = new Dictionary<string, object>();

foreach (var x in columnNames)
{
if (x == "id")
{
dict["DT_RowId"] = properties[x].GetValue(p);
}
else
{
dict[x] = properties[x].GetValue(p);
}

}
return dict;
}

Answer

1/ To get the values of the properties from their name, you can use property descriptors:

var properties = TypeDescriptor.GetProperties(typeof(Product));
var value = properties[name].GetValue(product);

2/ To build the answer, you can create a dynamic object:

dynamic result = new ExpandoObject();
var dict = (IDictionary<string,object>)result;
dict[name] = value;

The result can then be converted to JSON.

Comments