C#调用第三方带附件SOAP WebService的实现疑问
C#调用带附件SOAP服务的实现思路与指引
核心逻辑理解
从你提供的示例来看,Details字段填写的cid:12345678是MIME内容ID(Content-ID),作用是将SOAP请求体和附件关联起来。本质是把附件打包成MIME多部分消息的一部分,SOAP体里通过cid指向这个附件的唯一标识。
两种实现方案
方案1:手动构造MIME请求(灵活可控)
如果自动生成的客户端不好扩展,直接用HttpClient构造请求最直接:
- 先生成SOAP XML内容,将
Details替换为cid:唯一ID(用GUID生成,避免重复冲突) - 把SOAP主体和附件拼成MIME多部分内容,分别设置对应的Content-Type和Content-ID
- 发送HTTP请求
代码片段参考:
var cid = Guid.NewGuid().ToString(); // 拼接SOAP XML,替换Details为cid:xxx var soapXml = @"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/""...> <soapenv:Body> <abc:abdReq> <def:reqinfo> <jkl:field1>12345</jkl:field1> <jkl:field2>ABC</jkl:field2> <jkl:field3>XYZ</jkl:field3> </def:reqinfo> <ghi:Details>cid:" + cid + @"</ghi:Details> </abc:abdReq> </soapenv:Body> </soapenv:Envelope>"; // 构造多部分MIME内容 var multipartContent = new MultipartContent("related", "uuid:" + Guid.NewGuid()); // 添加SOAP主体部分 var soapContent = new StringContent(soapXml, Encoding.UTF8, "application/soap+xml"); soapContent.Headers.ContentId = "<soap-body>"; multipartContent.Add(soapContent); // 添加XML附件 var attachmentContent = new StringContent(File.ReadAllText("你的附件.xml"), Encoding.UTF8, "text/xml"); attachmentContent.Headers.ContentId = "<" + cid + ">"; // 注意cid要加尖括号 multipartContent.Add(attachmentContent); // 发送请求 using var client = new HttpClient(); var response = await client.PostAsync("第三方服务地址", multipartContent); response.EnsureSuccessStatusCode(); var result = await response.Content.ReadAsStringAsync();
方案2:扩展自动生成的客户端(贴合WSDL生成类)
如果用Visual Studio添加服务引用或wsdl.exe生成了客户端类,可以扩展它支持附件:
- 启用MTOM编码,可通过配置文件或代码添加行为实现
- 构造请求对象时,将
Details设为cid:唯一ID - 创建
Attachment对象,设置对应的Content-ID,再添加到请求头中
代码片段参考:
// 实例化自动生成的服务客户端 var client = new YourGeneratedServiceClient(); // 启用MTOM编码 client.Endpoint.Behaviors.Add(new MtomMessageEncodingBindingElement()); // 构造请求参数 var cid = Guid.NewGuid().ToString(); var req = new abdReq { reqinfo = new reqinfo { field1 = "12345", field2 = "ABC", field3 = "XYZ" }, Details = $"cid:{cid}" }; // 创建XML附件 var attachment = new Attachment( "attachment.xml", new MemoryStream(File.ReadAllBytes("你的附件.xml")), "text/xml" ); attachment.ContentId = $"<{cid}>"; // 与SOAP中的cid完全匹配 // 调用服务时携带附件 using (new OperationContextScope(client.InnerChannel)) { OperationContext.Current.OutgoingMessageHeaders.Add(attachment); var response = client.YourServiceMethod(req); }
SOAP UI测试排查要点
之前MTOM测试失败,检查以下几点:
- 确认请求窗口的
MTOM标签已勾选Enable MTOM - 附件的Content-ID要与SOAP体中的
cid:完全对应:比如SOAP里是cid:12345,附件的Content-ID必须是<12345> - 附件的Content-Type设置为
text/xml,匹配你的XML附件类型 - 检查服务端是否要求特定的MIME边界或请求头参数
关键注意事项
- cid必须唯一:每次请求用新的GUID生成,避免和其他请求冲突
- MIME格式要准确:多部分消息的边界、各部分的Content-Type/Content-ID不能出错,抓包对比正确请求是最有效的调试方式
- 确认服务端支持的方式:有些服务只支持普通MIME多部分,不支持MTOM,需提前确认
- 用抓包工具调试:通过Fiddler、Wireshark抓包,对比自己的请求与示例请求(如果有)的差异,比如头信息、格式细节
内容的提问来源于stack exchange,提问作者AntDC
相关产品推荐
相关产品推荐

