【问题标题】:MVC 5 Build a dynamic anonymous objectMVC 5 构建动态匿名对象
【发布时间】:2016-09-27 23:17:24
【问题描述】:

我正在开发一个 MVC 5 应用程序,并试图让用户编写自己的查询并在 Jquery DataTables 中显示结果。我很难弄清楚如何根据用户输入动态构建匿名 JSON 对象。

理论上,用户会发送列列表和 where 子句来构建 SQL 查询。 我会像这样运行 SQL 查询,然后构建我的对象。

如何根据用户输入的内容动态构建“select new { DT_RowId = a.id, name = a.name, number = a.number }”。

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

最终的 JSON 响应是

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

硬编码时效果很好。否则,我将不得不从产品中选择 *,然后在客户端显示/隐藏列,因此如果所有列都从服务器返回,则我的数据有效负载非常大。

有没有办法遍历请求的属性来构建这个匿名对象?我尝试使用字典,但是返回的 Json 非常不同,其中包含 Key 和 Value,这不是 DataTables 所期望的。

谢谢!

完整的控制器代码

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

感谢菲利普的解决方案

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

【问题讨论】:

  • 你使用的是什么 JSON 序列化器?
  • 在编辑中查看我上面的完整控制器代码。我将 JSON 从控制器返回到 JQuery DataTables。但是,作为数据传回的是我在查询语句中选择的内容。这就是我想要动态定义的,这样我就不必返回 DBSet Products 中的所有列。

标签: c# jquery asp.net-mvc


【解决方案1】:

1/ 要从名称中获取属性的值,可以使用属性描述符:

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

2/ 要构建答案,您可以创建一个dynamic 对象:

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

result 然后可以转换为 JSON。

【讨论】:

  • 如何在上面的示例中将值设置为“a.name”或“a.number”?
  • 我想重新创建这一行“select new { DT_RowId = a.id, name = a.name, number = a.number }”
  • dict["DT_RowId"] = properties["id"].GetValue(a); 等在构建了propertiesdict 之后。 result 然后具有与您的示例相同的属性(但在动态对象而不是静态对象中)。
  • 嗨菲利普,感谢您的帮助,但我不知道我是否正确。如何在我的 Using 语句 var v = (from a in dc.Products.SqlQuery(querystring) select result) 中使用结果 ExpandoObject?
  • var v = (from a in dc.Products.SqlQuery(querystring) select GetResult(a, columnNames)。构建方法dynamic GetResult(Product p, IEnumerable&lt;string&gt; columnNames).
【解决方案2】:

如果您使用的是 JSON.NET,则字典应使用 Key 的值作为属性名称并将与该键关联的值作为属性值进行序列化。

如果您使用 DataContractJsonSerializer,您需要将设置 UseSimpleDictionaryFormat 设置为 true。

然后,您将使用属性名称作为键、值作为值来构建字典。如果用户选择他们想要的名称,您可以执行outputDict.Add(nameof(x.Name), x.Name); 之类的操作,然后返回要由您的序列化库序列化的字典。

【讨论】:

  • 您能解释一下如何使用您的方法重新创建此 select new { DT_RowId = a.id, name = a.name, number = a.number } 吗?另外,我正在使用 JSONResult
猜你喜欢
  • 2019-04-15
  • 2023-03-05
  • 1970-01-01
  • 2014-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-21
  • 2019-11-15
相关资源
最近更新 更多