ASP.NET Web API POST基类参数跨项目调用payload为null如何解决
问题产生原因
核心原因是你开启了Json.NET的TypeNameHandling.All配置,序列化时会自动在JSON中插入$type元数据字段,该字段的值是类型全限定名+所属程序集名称,服务端反序列化时会严格按照这个元数据去加载对应类型。
- 当你在API所在解决方案内发起调用时,客户端代码引用的
NbRequestConcrete类就是API项目本身定义的类型,序列化生成的$type值和服务端加载的类型信息完全匹配,反序列化可以正常执行,因此能拿到正确的派生类实例。 - 当你在独立解决方案/控制台项目中调用时,你在新项目中重复声明了同名同命名空间的类,但这个类属于控制台项目自身的程序集,序列化生成的
$type值会带上控制台项目的程序集名。服务端运行时根本找不到控制台程序集中的类型,反序列化直接失败,因此接口收到的payload为null。
额外注意:你当前的写法本身存在反序列化安全风险,TypeNameHandling.All配置会允许客户端指定任意反序列化类型,很容易触发远程代码执行漏洞,生产环境禁止直接无校验使用。
修复方案
- 方案1(推荐,最安全):移除对客户端传入
$type元数据的依赖,在基类中增加显式的类型判别字段(比如RequestType枚举),服务端实现自定义JsonConverter,根据请求中传入的类型判别字段,主动选择反序列化为对应的派生类,完全不信任客户端传入的类型元数据。 - 方案2(快速修复):抽离单独的共享类库项目,把
NbRequestBase、NbRequestConcrete等所有请求/响应类都放到这个共享类库中,API服务端和所有客户端都统一引用这个共享类库,不要在各项目中重复声明同名类。这种方式下序列化生成的$type元数据会和服务端加载的类型完全匹配,反序列化可以正常执行。如果采用这个方案,必须在服务端配置自定义SerializationBinder,限制仅允许反序列化你指定的请求类类型,封堵反序列化漏洞。 - 额外配置检查:确认服务端的Json序列化全局配置也开启了对应的
TypeNameHandling选项,否则即使$type值正确,服务端默认也只会反序列化为基类实例,后续强转会直接报错。
Postman调用方法
根据你选择的实现方案不同,调用方式分两种:
- 如果你采用
$type元数据的方案:
新建POST请求,填写接口地址,请求头添加Content-Type: application/json,请求体填写JSON结构。注意将$type值替换为你服务端实际的类型全限定名+API项目程序集名,你可以在API项目中通过typeof(NbRequestConcrete).AssemblyQualifiedName拿到准确的$type值直接复制使用,示例如下:{ "$type": "Nb.NbRequestConcrete, Nb.Api", "BaseProp": "BaseProp", "ConcreteProp": "ConcreteProp" } - 如果你采用自定义类型判别字段的方案:
按照你自定义的字段规则,在请求体中传入对应的类型标识和属性值即可,不需要携带$type字段。
内容的提问来源于stack exchange,提问作者imsuktoday
相关产品推荐
相关产品推荐

