问题
Using Postman, C#, .NET Framework 4.7
I make a GET request from Postman with content-accept set to "application/xml" and my .NET Framework Web API will respond with XML (brilliant!). I have not needed to serialize anything manually as .NET Framework serializes my response object with when I return Request.CreateResponse(HttpStatusCode.OK, myResponse)
.
However, it seems to include extra things which I am not familiar with and I am wondering if they can be removed via Global.asax settings or similar?
- xmlns="http://schemas.datacontract.org/2004/07/dto.MyModels" is something I would like to remove!
- "d3p1" is not something I have come across when creating XML. Can I remove it somehow?
<error i:nil="true" />
pops up when something is null. Is it possible to just be or just not appear when it is null?
So, The XML response looks like this:
<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>
My classes look something like this:
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; }
}
回答1:
xmlns="http://schemas.datacontract.org/2004/07/dto.MyModels" is something I would like to remove!
"d3p1" is not something I have come across when creating XML. Can I remove it somehow?
The attributes:
xmlns="http://schemas.datacontract.org/2004/07/dto.MyModels"
xmlns:d3p1="http://schemas.datacontract.org/2004/07/dto.MyModels.Shared"
are both XML namespace declarations. The first establishes a default XML namespace for your XML document; the second declares a namespace to which all child elements prefaced with d3p1:
belong.
From the specific namespace chosen, it's apparent you are using 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.
Since you don't want an XML namespace for any of your types, the first option would appear to be the easiest: apply the following attributes to your assembly:
[assembly: ContractNamespaceAttribute("", ClrNamespace = "dto.MyModels")]
[assembly: ContractNamespaceAttribute("", ClrNamespace = "dto.MyModels.Shared")]
[assembly: ContractNamespaceAttribute("", ClrNamespace = "dto.Models.Android.Shared")]
Alternatively, you could apply data contract attributes to your types:
[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; }
}
Note that data contract serialization is opt-in so you will need to apply [DataMember]
to each member to be serialized.
As a final alternative, you could switch to using 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" />
pops up when something is null. Is it possible to just be or just not appear when it is null?
These null elements can be removed by setting 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; }
}
Alternatively you could switch to XmlSerializer
which does not output null reference values by default.
来源:https://stackoverflow.com/questions/60214258/xml-api-request-returns-d3p1-for-arrays-or-sub-classes