.NET Core 3.1 API 接受复杂 XML 对象

.NET Core 3.1 API to Accept Complex XML Object


编辑

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 对象有点困惑

比如我有一个class是这样的

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 对象不再是 null,但它里面的所有内容都是 null。

我不确定如何正确处理这个问题。我有什么遗漏吗?

我的控制器看起来像这样

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

您还需要为 Object2Object3 设置 DataContractAttribute.Namespace:

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

演示 fiddle #1 here.

备注:

  • data contract serializer, if you do not explicitly specify a namespace for a data contract object, a default is assigned as explained in the docs:

    By default, data contracts for a particular type are assigned a namespace that comes from the common language runtime (CLR) namespace of that type.

    By default, any given CLR namespace (in the format Clr.Namespace) is mapped to the namespace http://schemas.datacontract.org/2004/07/Clr.Namespace.

  • DataContractSerializer 的默认命名空间逻辑不同于 XmlSerializer. Objects are not assigned to a namespace by default by XmlSerializer, so your original model works as-is with that serializer. Demo fiddle #2 here

    如果您更愿意使用 XmlSerializer 而不是 DataContractSerializer 我相信您可以删除 AddXmlDataContractSerializerFormatters() 只留下 AddXmlSerializerFormatters().

  • 调试反序列化问题的一种简单方法是序列化您的模型并将实际结果与内容进行比较您正在尝试反序列化。如果我尝试序列化您当前 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>    
    

    从中可以看出Object2Object3的元素的命名空间d2p1:是错误的。 (此处 http://schemas.datacontract.org/2004/07/ 所选择的精确命名空间将取决于您的模型的 CLR 命名空间,这在您的问题中未显示。)

    演示 fiddle #3 here.

  • 您的 XML 元素没有 z:Id="xxx"z:ref="xxx" 属性,因此我认为不需要启用 IsReference reference tracking mechanism