简体   繁体   中英

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

If you're using JSON.NET, a dictionary should serialize with the value of the Key as the property name and the value associated with the key as the property value.

If you're using the DataContractJsonSerializer, you will want to provide the setting UseSimpleDictionaryFormat as true.

You would then build your dictionary with the name of the property as a key, and the value as the value. If the user selects that they want the name, you would do something like outputDict.Add(nameof(x.Name), x.Name); then return the dictionary to be serialized by your serialization library.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM