XML API 请求 returns "d3p1" 数组或子数组 类

XML API Request returns "d3p1" for arrays or sub-classes

使用 Postman、C#、.NET Framework 4.7

我从 Postman 发出 GET 请求,内容接受设置为 "application/xml",我的 .NET Framework Web API 将以 XML 响应(太棒了!)。我不需要手动序列化任何东西,因为 .NET Framework 序列化我的响应对象时 return Request.CreateResponse(HttpStatusCode.OK, myResponse).

但是,它似乎包含我不熟悉的额外内容,我想知道是否可以通过 Global.asax 设置或类似设置删除它们?

因此,XML 响应如下所示:

<SimpleResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/dto.MyModels">
    <error i:nil="true" />
    <result>
        <bookList xmlns:d3p1="http://schemas.datacontract.org/2004/07/dto.MyModels.Shared">
            <d3p1:Book>
                <d3p1:bookname>Book 1 Name</d3p1:bookname>
                <d3p1:serial>ZMeTaQ1kejh0mJYGHE4+1a4Y2juU6tMDd5zYDqN4tqI=</d3p1:serial>
                <d3p1:id>4</d3p1:id>

            </d3p1:Book>
            <d3p1:Book>
                <d3p1:bookname>Hello World</d3p1:bookname>
                <d3p1:serial>9lM16kho3bgsrG+wRh4ejtZjwrYJwp6FbRqnnZ4CJPA=</d3p1:serial>
                <d3p1:id>5</d3p1:id>
            </d3p1:Book>
            <d3p1:Book>
                <d3p1:bookname>Ding</d3p1:bookname>
                <d3p1:serial>XCqqKB+Wi3i4z6nN1Ry8IHtar6ogojjiqxMfvfgC0qc=</d3p1:serial>
                <d3p1:id>6</d3p1:id>
            </d3p1:Book>
        </bookList>
        <author xmlns:d3p1="http://schemas.datacontract.org/2004/07/dto.Models.Android.Shared">
            <d3p1:pictureId>0</d3p1:pictureId>
            <d3p1:websiteurl i:nil="true" />
            <d3p1:email i:nil="true" />
            <d3p1:name>Jo Blogs</d3p1:size>
            <d3p1:age>0</d3p1:size>
        </author>
    </result>
</SimpleResponse>

我的 类 看起来像这样:

public string error { get; set;}
public class SimpleResponse 
{
 public List<Book> bookList { get; set; }
 public Author author { get; set; }
}

public class Book
{
    public string bookname { get; set; }
    public string serial { get; set; }
    public int id { get; set; }
}

public class Author
{
    public string pictureId{ get; set; }
    public string websiteurl { get; set; }
    public string email { get; set; }
    public string name { get; set; }
    public int age { get; set; }
}

xmlns="http://schemas.datacontract.org/2004/07/dto.MyModels" 是我要删除的东西!
"d3p1" 不是我在创建 XML 时遇到的东西。我能以某种方式删除它吗?

属性:

  • xmlns="http://schemas.datacontract.org/2004/07/dto.MyModels"
  • xmlns:d3p1="http://schemas.datacontract.org/2004/07/dto.MyModels.Shared"

都是XML namespace declarations。第一个为您的 XML 文档建立一个默认的 XML 命名空间;第二个声明一个名称空间,所有以 d3p1: 开头的子元素都属于该名称空间。

从所选的特定命名空间来看,显然您正在使用 DataContractSerializer for XML serialization. This serializer assigns XML namespaces according to rules documented in Data Contract Names: Data Contract Namespaces

By default, any given CLR namespace (in the format Clr.Namespace) is mapped to the namespace http://schemas.datacontract.org/2004/07/Clr.Namespace. To override this default, apply the ContractNamespaceAttribute attribute to the entire module or assembly. Alternatively, to control the data contract namespace for each type, set the Namespace property of the DataContractAttribute.

由于您不需要任何类型的 XML 命名空间,因此第一个选项似乎是最简单的:将以下属性应用于您的程序集:

[assembly: ContractNamespaceAttribute("", ClrNamespace = "dto.MyModels")]
[assembly: ContractNamespaceAttribute("", ClrNamespace = "dto.MyModels.Shared")]
[assembly: ContractNamespaceAttribute("", ClrNamespace = "dto.Models.Android.Shared")]

或者,您可以将 data contract attributes 应用于您的类型:

[DataContract(Name = "Book", Namespace = "")]
public class Book
{
    [DataMember]
    public string bookname { get; set; }
    [DataMember]
    public string serial { get; set; }
    [DataMember]
    public int id { get; set; }
}

请注意,数据合同序列化是 opt-in,因此您需要将 [DataMember] 应用于每个要序列化的成员。

作为最后的选择,您可以切换到使用 XmlSerializer which has no default XML namespace. To do that you will need to apply [XmlSerializerFormat] to your service contract as shown in Manually Switching to the XmlSerializer.

<error i:nil="true" /> 为 null 时弹出。当它为 null 时是否可以只出现或不出现?

可以通过设置 DataMemberAttribute.EmitDefaultValue on reference type data members as shown in this answer to Can I configure the DataContractSerializer to not create optional (i.e. Nullable<> and List<>) elements in output XML? by Darren Clark:

来删除这些空元素
[DataContract(Name = "Book", Namespace = "")]
public class Book
{
    [DataMember(EmitDefaultValue = false)]
    public string bookname { get; set; }
    [DataMember(EmitDefaultValue = false)]
    public string serial { get; set; }
    [DataMember]
    public int id { get; set; }
}

或者您可以切换到 XmlSerializer,它默认不输出空引用值。