CoreWCF DataContract序列化问题:MTOM附件SOAP服务适配
解决CoreWCF处理带MTOM的自定义SOAP消息问题
针对你遇到的XML属性不识别、附件无法映射的问题,核心解决思路是切换到XmlSerializer而非DataContractSerializer——因为DataContractSerializer是基于数据契约设计,对XML原生特性(比如属性)支持有限,而XmlSerializer完全贴合XML结构,能完美处理属性、XOP引用这类场景。以下是具体实现步骤:
1. 定义匹配XML结构的实体类
手动编写对应SOAP消息的实体,用System.Xml.Serialization下的特性标记,完全对齐XML节点和属性:
using System.Xml.Serialization; // 对应根节点ROOTDOC [XmlRoot("ROOTDOC")] public class RootDoc { [XmlElement("INFO")] public Info Info { get; set; } } // 对应INFO节点,包含myAttribute属性和ATTACHMENTS子节点 public class Info { [XmlAttribute("myAttribute")] public string MyAttribute { get; set; } [XmlElement("ATTACHMENTS")] public Attachments Attachments { get; set; } } public class Attachments { [XmlElement("ATTACHMENT")] public Attachment[] AttachmentList { get; set; } } public class Attachment { [XmlElement("Include", Namespace = "http://www.w3.org/2004/08/xop/include")] public XopInclude XopInclude { get; set; } } // 对应xop:Include节点 public class XopInclude { [XmlAttribute("href")] public string Href { get; set; } }
2. 配置CoreWCF服务使用XmlSerializer
在服务契约上添加[XmlSerializerFormat]特性,指定使用XmlSerializer序列化/反序列化:
using CoreWCF; using CoreWCF.Web; [ServiceContract] public interface IAttachmentService { [OperationContract(Action = "*", ReplyAction = "*")] // 用XmlSerializerFormat替代默认的DataContractSerializer [XmlSerializerFormat] void ProcessAttachment(RootDoc request); }
3. 实现服务逻辑,获取MTOM附件
在服务实现中,通过OperationContext获取MTOM附件的内容,根据xop:Include里的cid匹配:
public class AttachmentService : IAttachmentService { public void ProcessAttachment(RootDoc request) { // 获取MTOM附件集合 var attachmentProperty = OperationContext.Current.IncomingMessageProperties["http://schemas.microsoft.com/ws/2005/05/mtom/properties/attachment"] as MessageAttachmentProperty; if (attachmentProperty != null) { foreach (var attachment in attachmentProperty.Attachments) { // 匹配xop:Include里的cid(注意cid格式是"cid:xxx",Attachment.ContentId不带前缀) var matchingXop = request.Info.Attachments.AttachmentList.FirstOrDefault(a => a.XopInclude.Href == $"cid:{attachment.ContentId}"); if (matchingXop != null) { // 读取附件内容,比如转成字节数组 using var stream = new MemoryStream(); attachment.ContentStream.CopyTo(stream); byte[] attachmentBytes = stream.ToArray(); // 后续处理附件逻辑 } } } // 处理myAttribute属性 string attributeValue = request.Info.MyAttribute; // 这里就能拿到ABC123 } }
4. 启用MTOM绑定
在CoreWCF服务配置中,为绑定启用MTOM:
// 比如在Program.cs中配置服务 var builder = WebApplication.CreateBuilder(args); builder.Services.AddServiceModelServices(); var app = builder.Build(); app.UseServiceModel(builder => { builder.AddService<AttachmentService>(); builder.AddServiceEndpoint<IAttachmentService, BasicHttpBinding>( new BasicHttpBinding(BasicHttpSecurityMode.None) { MessageEncoding = WSMessageEncoding.Mtom, // 启用MTOM TransferMode = TransferMode.Buffered }, "/AttachmentService.svc"); }); app.Run();
关键说明
- 之前用
[DataContract]/[DataMember]时属性被忽略,是因为DataContractSerializer不支持XML属性,只关注数据成员的序列化,切换到XmlSerializer后就能正常识别[XmlAttribute]标记。 - XOP的cid匹配需要注意格式:SOAP消息里的href是
cid:xxx,而MessageAttachmentProperty里的Attachment.ContentId是不带cid:前缀的,所以要做字符串拼接匹配。
内容的提问来源于stack exchange,提问作者Chris Disley
相关产品推荐
相关产品推荐

