c# - .NET Core 3.1 API 接受复杂的 XML 对象
问题描述
编辑
XML 输入看起来像这样
<?xml version="1.0" encoding="UTF-8"?>
<Object1>
<field1>Hello</field1>
<field2>
<field3>World</field3>
<field4>
<field5>Test</field5>
<field6>Test2</field6>
</field4>
</field2>
</Object1>
我对如何让我的 API 接受复杂的 XML 对象有点困惑
例如,我有一个像这样的类
public class Object1
{
public string field1 {get; set;}
public Object2 field2 {get; set;}
}
public class Object2
{
public string field3 {get; set;}
public Object3 field4 {get; set;}
}
public class Object3
{
public string field5 {get; set;}
public string field6 {get; set;}
}
在我的 startup.cs 文件中,我添加了这个
services.AddControllers().AddXmlDataContractSerializerFormatters()
.AddXmlSerializerFormatters();
然后我得到了它无法反序列化输入的错误。
所以我将这些属性添加到对象中
[DataContract(Namespace = "")]
[XmlRoot]
public class Object1
{
[DataMember(Name = "field1")]
public string field1 {get; set;}
[DataMember(Name = "field2")]
public Object2 field2 {get; set;}
}
[DataContract(Name = "field2", IsReference = true)]
public class Object2
{
[DataMember(Name = "field3")]
public string field3 {get; set;}
[DataMember(Name = "field4")]
public Object3 field4 {get; set;}
}
[DataContract(Name = "field3", IsReference = true)]
public class Object3
{
[DataMember(Name = "field5")]
public string field5 {get; set;}
[DataMember(Name = "field6")]
public string field6 {get; set;}
}
所以现在当我发送 XML 对象时,它现在可以进行一些处理了。我可以得到 field1 的值,看起来 field2 对象不再为空,但其中的所有内容都是空的。
我不确定如何正确处理这个问题。有什么我想念的吗?
我的控制器看起来像这样
[HttpPost]
[Consumes("application/xml")]
public async Task<IActionResult> UpdateObject([FromBody]Object1 object1)
{
var testObject1 = object1.field1; // this value is not null because it is a string datatype and not like the one below which is slightly more complex
var testObject2 = object1.field2; //this is not null but the properties inside the object are null
}
解决方案
您还需要设置DataContractAttribute.Namespace
forObject2
和Object3
:
[DataContract(Namespace = "", Name = "field2", IsReference = true)]
public class Object2
{
[DataMember(Name = "field3")]
public string field3 {get; set;}
[DataMember(Name = "field4")]
public Object3 field4 {get; set;}
}
[DataContract(Namespace = "", Name = "field3", IsReference = true)]
public class Object3
{
[DataMember(Name = "field5")]
public string field5 {get; set;}
[DataMember(Name = "field6")]
public string field6 {get; set;}
}
演示小提琴#1在这里。
笔记:
使用数据契约序列化程序,如果您没有为数据契约对象明确指定命名空间,则会按照文档中的说明分配默认值:
默认情况下,为特定类型的数据协定分配一个命名空间,该命名空间来自该类型的公共语言运行时 (CLR) 命名空间。
默认情况下,任何给定的 CLR 命名空间(格式为 Clr.Namespace)都映射到命名空间
http://schemas.datacontract.org/2004/07/Clr.Namespace
。的默认命名空间逻辑
DataContractSerializer
不同于XmlSerializer
. 默认情况下,对象未分配给命名空间XmlSerializer
,因此您的原始模型与该序列化程序按原样工作。演示小提琴#2在这里。如果您更愿意使用
XmlSerializer
而不是DataContractSerializer
我相信您可以删除AddXmlDataContractSerializerFormatters()
leave onlyAddXmlSerializerFormatters()
。调试反序列化问题的一种简单方法是序列化您的模型并将实际结果与您尝试反序列化的内容进行比较。如果我尝试序列化您当前
Object1
模型的实例,我会得到:<?xml version="1.0" encoding="utf-16"?> <Object1 xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <field1>Hello</field1> <field2 xmlns:d2p1="http://schemas.datacontract.org/2004/07/" z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"> <d2p1:field3>World</d2p1:field3> <d2p1:field4 z:Id="i2"> <d2p1:field5>Test</d2p1:field5> <d2p1:field6>Test2</d2p1:field6> </d2p1:field4> </field2> </Object1>
从中可以看出
d2p1:
元素的命名空间Object2
和Object3
是错误的。(此处选择的精确命名空间http://schemas.datacontract.org/2004/07/
将取决于模型的 CLR 命名空间,您的问题中未显示。)演示小提琴#3在这里。
您的 XML 元素没有
z:Id="xxx"
或z:ref="xxx"
属性,因此我认为不需要启用IsReference
引用跟踪机制。
推荐阅读
- python - 以最小/最有效路径(Scipy distance.cdist)3D 浏览坐标?
- go - 奇怪的切片行为
- javascript - 里面的噩梦然后不能使用pdf
- java - 在表格中设置项目 java web 抓取
- ibm-cloud - 无法读取 null 的属性“匹配”
- reactjs - 是否可以覆盖 material-ui 组件的默认道具?
- html - 当开发工具在底部打开时,如何在 html 上强制执行 100%/vh?
- roku - 如何使用明亮的脚本删除按钮中的项目符号文本?
- javascript - 使用 amCharts.js 将饼图导出到 CSV / XLSX
- sql - 我们如何使用 mybatis-spring 映射 Mapper.xml 中的多个表?