C#中如何反序列化含MTOM边界的SOAP XML响应为POCO
实现方案
问题1解答
不需要自行编写边界和元数据处理逻辑,.NET 内置了MIME多部分内容解析能力,符合C#开发规范,可以直接从MTOM响应中提取目标SOAP XML:
using System.IO; using System.Net.Http.Headers; using System.Net.Http; public static async Task<string> ExtractSoapXmlFromMtomResponse(string rawResponse, string contentTypeHeaderValue) { // 解析响应头的Content-Type获取边界值 var contentType = MediaTypeHeaderValue.Parse(contentTypeHeaderValue); var boundary = contentType.Boundary.Trim('"'); // 将原始响应转为流供MultipartReader读取 using var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(rawResponse)); var reader = new MultipartReader(boundary, stream); // 遍历多部分内容,找到SOAP XML部分 while (await reader.ReadNextSectionAsync()) { var section = reader.CurrentSection; if (section.ContentType.MediaType == "application/xop+xml") { using var readerStream = new StreamReader(section.Body); return await readerStream.ReadToEndAsync(); } } return string.Empty; }
如果调用接口时直接用HttpClient拿到HttpResponseMessage,可以直接读响应内容的流,不需要先转成字符串,性能更优。
问题2解答
命名空间不需要关注别名,只需要匹配实际的命名空间URI即可,return等特殊命名节点可以通过XML序列化属性显式指定映射关系。调整后的POCO定义如下,直接适配响应结构:
using System.Xml.Serialization; // 对应SOAP Body内的listAttachmentsResponse节点 [XmlRoot("listAttachmentsResponse", Namespace = "http://ws.praxedo.com/v6/businessEvent")] public class ListAttachmentsResponseDto { [XmlElement("return")] public ResponseContent Content { get; set; } } public class ResponseContent { [XmlElement("resultCode")] public int ResultCode { get; set; } [XmlElement("entities")] public Attachment[] Attachments { get; set; } } public class Attachment { [XmlElement("entityId")] public string BusinessEventId { get; set; } [XmlElement("name")] public string FileName { get; set; } [XmlElement("addedOnDevice")] public bool IsAddedOnDevice { get; set; } [XmlElement("creationDate")] public DateTime CreationDate { get; set; } [XmlElement("external")] public bool IsExternal { get; set; } [XmlElement("id")] public string Id { get; set; } [XmlElement("lastModificationDate")] public DateTime LastModificationDate { get; set; } [XmlElement("size")] public int Size { get; set; } [XmlElement("unmodifiable")] public bool IsUnmodifiable { get; set; } }
XML反序列化代码
提取到SOAP XML之后,直接用XmlSerializer反序列化即可,会自动处理命名空间和节点映射:
using System.Xml; using System.Xml.Serialization; public static ListAttachmentsResponse DeserializeSoapResponse(string soapXml) { var serializer = new XmlSerializer(typeof(ListAttachmentsResponseDto)); using var stringReader = new StringReader(soapXml); using var xmlReader = XmlReader.Create(stringReader); var dto = (ListAttachmentsResponseDto)serializer.Deserialize(xmlReader); // 转换为你需要的最终POCO结构 return new ListAttachmentsResponse { ResultCode = dto.Content.ResultCode, Attachments = dto.Content.Attachments }; }
如果不需要分层的DTO结构,也可以直接调整POCO的序列化属性适配层级,减少转换步骤。
内容的提问来源于stack exchange,提问作者Brian Kessler
相关产品推荐
相关产品推荐

