且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

HttpClient的不正确序列化

更新时间:2023-11-08 11:34:58

综观的 PostAsXmlAsync来源$ C ​​$ C ,我们可以看到它使用 XmlMediaTypeFormatter 它内部使用的DataContractSerializer 不可以 的XmlSerializer 。前者不尊重 XmlRootAttribute

 公共静态任务< Htt的presponseMessage> PostAsXmlAsync< T>(这HttpClient的客户端,乌里requestUri,T值的CancellationToken的CancellationToken)
{
      返回client.PostAsync(requestUri,价值,新XmlMediaTypeFormatter()
                    的CancellationToken);
}
 

为了实现你需要什么,你可以创建自己的自定义扩展方法,其中明确指定要使用的XmlSerializer

 公共静态类HttpExtensions
{
    公共静态任务< Htt的presponseMessage> PostAsXmlWithSerializerAsync< T>(这HttpClient的客户端,乌里requestUri,T值的CancellationToken的CancellationToken)
    {
        返回client.PostAsync(requestUri,价值,
                      新XmlMediaTypeFormatter {UseXmlSerializer = TRUE},
                      的CancellationToken);
    }
}
 

When calling HttpClient's extension method PostAsXmlAsync, it ignores the XmlRootAttribute on the class. Is this behaviour a bug?

Test

[Serializable]
[XmlRoot("record")]
class Account 
{
    [XmlElement("account-id")]
    public int ID { get; set }
}


var client = new HttpClient();
await client.PostAsXmlAsync(url, new Account())

Looking at the source code of PostAsXmlAsync, we can see that it uses XmlMediaTypeFormatter which internally uses DataContractSerializer and not XmlSerializer. The former doesn't respect the XmlRootAttribute:

public static Task<HttpResponseMessage> PostAsXmlAsync<T>(this HttpClient client, Uri requestUri, T value, CancellationToken cancellationToken)
{
      return client.PostAsync(requestUri, value, new XmlMediaTypeFormatter(),
                    cancellationToken);
}

In order to achieve what you need, you can create a your own custom extension method which explicitly specifies to use XmlSerializer:

public static class HttpExtensions
{
    public static Task<HttpResponseMessage> PostAsXmlWithSerializerAsync<T>(this HttpClient client, Uri requestUri, T value, CancellationToken cancellationToken)
    {
        return client.PostAsync(requestUri, value,
                      new XmlMediaTypeFormatter { UseXmlSerializer = true },
                      cancellationToken);
    }
}