WebApi传递动态参数的最佳实践 如何解决Dictionary反序列化类型问题
方案1:使用JsonNode/JToken作为Dictionary的值类型(最推荐)
这是修改成本最低的方案,完全适配现有代码结构,同时解决object类型丢失类型信息的问题:
- .NET 6及以上版本可以直接用自带的
System.Text.Json.Nodes.JsonNode - 用Newtonsoft.Json的场景可以替换为
JToken
修改后的代码示例:
[HttpPost] void Foo(Dictionary<string, JsonNode> prm) { var sql = "whatever"; var sqlPrms = new List<SqlParameter>(); if (prm.TryGetValue("Condition1",out var c1)) { sql += " and Condition1=@c1"; // 可显式转换为目标类型,也可以直接调用GetValue<object>()获取保留原始类型的装箱值 sqlPrms.Add(new SqlParameter("c1", c1.GetValue<object>())); } if (prm.TryGetValue("Condition2", out var c2)) { sql += " and Condition2=@c2"; sqlPrms.Add(new SqlParameter("c2", c2.GetValue<object>())); } ExecuteSql(sql, sqlPrms); }
JsonNode在反序列化阶段会完整保留JSON原始值的类型信息,不会出现普通Dictionary<string, object>反序列化时数字默认转成long、类型不匹配的问题。
方案2:自定义动态参数结构(适合需要强类型约束的场景)
如果需要前端明确指定参数类型避免歧义,可以自定义轻量级参数包装类:
public class DynamicQueryParam { public object Value { get; set; } // 存储参数的实际类型,比如TypeCode.Int32、TypeCode.String等 public TypeCode ValueType { get; set; } } // Action签名修改为 [HttpPost] void Foo(Dictionary<string, DynamicQueryParam> prm)
取值时可以根据ValueType做显式类型转换,完全避免类型匹配错误,适合对数据精度要求高的场景。
方案3:直接读取请求JSON体
如果查询条件的灵活性要求极高,也可以直接把请求体读取为JsonDocument自行解析,不需要依赖模型绑定:
[HttpPost] void Foo([FromBody] JsonDocument doc) { var root = doc.RootElement; // 自行遍历属性、提取值和类型 }
所有方案都保留了参数化查询的逻辑,不会引入SQL注入风险。
内容的提问来源于stack exchange,提问作者ahdung
相关产品推荐
相关产品推荐

