【问题标题】:.NET Core 3.1 API to Accept Complex XML Object.NET Core 3.1 API 接受复杂的 XML 对象
【发布时间】:2021-11-28 15:28:57
【问题描述】:

编辑

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
}

【问题讨论】:

    标签: c# xml api asp.net-core-3.1 datacontractserializer


    【解决方案1】:

    您还需要为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;}
    }
    

    演示小提琴 #1 here.

    注意事项:

    • 对于data contract serializer,如果您没有为数据协定对象明确指定命名空间,则会按照docs 中的说明分配默认值:

      默认情况下,为特定类型的数据协定分配一个命名空间,该命名空间来自该类型的公共语言运行时 (CLR) 命名空间。

      默认情况下,任何给定的 CLR 命名空间(格式为 Clr.Namespace)都映射到命名空间 http://schemas.datacontract.org/2004/07/Clr.Namespace

    • DataContractSerializer 的默认命名空间逻辑与 XmlSerializer 不同。默认情况下,XmlSerializer 不会将对象分配给命名空间,因此您的原始模型与该序列化程序一起工作。演示小提琴 #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 命名空间,您的问题中未显示。)

      演示小提琴#3 here.

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

    【讨论】:

    • 感谢您的意见!我不知道我还需要为所有其他对象放入命名空间!非常感谢您的澄清!
    猜你喜欢
    • 1970-01-01
    • 2020-10-03
    • 1970-01-01
    • 2020-11-16
    • 2021-04-13
    • 1970-01-01
    • 1970-01-01
    • 2020-07-16
    相关资源
    最近更新 更多