C#中如何结合WebRequest与对象调用SOAP的createEvents方法(Basic Auth)
嘿,我来帮你解决这个C#发送SOAP POST请求的问题!你已经有了BusinessEvent对象和WebRequest的基础配置,现在关键是把这些和createEvents方法结合起来——其实有两种常用方案,我给你详细拆解下:
方案一:用代理类(推荐,最省心)
如果服务端提供了WSDL文件,直接用微软的svcutil.exe生成代理类是最简单的方式,它会帮你自动处理SOAP序列化、认证和MTOM这些细节,不用手动拼XML。
步骤:
打开Visual Studio的开发者命令提示符,运行生成命令:
svcutil.exe https://eu3.provider.com/eTech/services/cxf/v6/BusinessEventManager?wsdl /out:BusinessEventManager.cs这会生成一个包含代理类的
.cs文件,把它加到你的项目里。然后直接调用方法,同时配置HTTP Basic Auth:
// 实例化代理客户端(类名可能根据WSDL生成的不同略有变化) var eventManagerClient = new BusinessEventManagerClient(); // 配置HTTPS下的Basic Auth eventManagerClient.ClientCredentials.UserName.UserName = "你的用户名"; eventManagerClient.ClientCredentials.UserName.Password = "你的密码"; // 构造你已经写好的BusinessEvent数组和WSEntry数组 BusinessEvent[] events = new BusinessEvent[] { /* 你的BusinessEvent实例 */ }; WSEntry[] entries = new WSEntry[] { /* 你的WSEntry实例 */ }; // 直接调用createEvents方法 var response = eventManagerClient.createEvents(events, entries); // 处理响应结果(如果有返回值的话) Console.WriteLine("请求成功,响应结果:" + response.ToString());如果需要启用MTOM(比如你的事件里包含二进制数据),只需要给绑定配置MTOM编码:
var binding = (BasicHttpBinding)eventManagerClient.Endpoint.Binding; binding.MessageEncoding = WSMessageEncoding.Mtom;
方案二:手动构造SOAP请求(适合不能生成代理的场景)
如果无法生成代理类,就需要手动把对象序列化成符合服务要求的SOAP XML,再通过WebRequest发送。
核心思路:
你需要把BusinessEvent[]和WSEntry[]序列化成XML,然后嵌入到SOAP 1.2的Envelope结构里,同时设置正确的HTTP头和Basic Auth。
代码示例:
using System; using System.IO; using System.Net; using System.Text; using System.Xml.Serialization; // 假设你的BusinessEvent和WSEntry类已经正确定义(带正确的XmlAttribute/XmlElement特性) public class SOAPRequestHelper { public static void SendCreateEventsRequest(string username, string password, BusinessEvent[] events, WSEntry[] entries) { // 1. 初始化WebRequest var request = WebRequest.Create("https://eu3.provider.com/eTech/services/cxf/v6/BusinessEventManager"); request.Method = "POST"; // SOAP 1.2必须用这个Content-Type,别和SOAP 1.1的text/xml搞混 request.ContentType = "application/soap+xml; charset=utf-8"; // 2. 设置HTTP Basic Auth string authCredentials = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{username}:{password}")); request.Headers.Add("Authorization", $"Basic {authCredentials}"); // 3. 构造SOAP Envelope并序列化对象 var soapEnvelopeBuilder = new StringBuilder(); soapEnvelopeBuilder.Append(@" <soap12:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap12=""http://www.w3.org/2003/05/soap-envelope""> <soap12:Body> <createEvents xmlns=""http://provider.com/eTech/services/cxf/v6/"">"); // 这里的命名空间要和服务端一致 // 序列化BusinessEvent数组 var eventSerializer = new XmlSerializer(typeof(BusinessEvent[]), new XmlRootAttribute("businessEvents") { Namespace = "http://provider.com/eTech/services/cxf/v6/" }); using (var writer = new StringWriter(soapEnvelopeBuilder)) { eventSerializer.Serialize(writer, events); } // 序列化WSEntry数组 var entrySerializer = new XmlSerializer(typeof(WSEntry[]), new XmlRootAttribute("wsEntries") { Namespace = "http://provider.com/eTech/services/cxf/v6/" }); using (var writer = new StringWriter(soapEnvelopeBuilder)) { entrySerializer.Serialize(writer, entries); } // 关闭SOAP标签 soapEnvelopeBuilder.Append(@" </createEvents> </soap12:Body> </soap12:Envelope>"); // 4. 写入请求流 byte[] requestData = Encoding.UTF8.GetBytes(soapEnvelopeBuilder.ToString()); request.ContentLength = requestData.Length; using (var stream = request.GetRequestStream()) { stream.Write(requestData, 0, requestData.Length); } // 5. 获取并处理响应 try { using (var response = (HttpWebResponse)request.GetResponse()) { using (var reader = new StreamReader(response.GetResponseStream())) { string responseXml = reader.ReadToEnd(); // 这里可以把responseXml反序列化成对应的结果对象,或者直接处理XML Console.WriteLine("请求成功,响应XML:" + responseXml); } } } catch (WebException ex) { // 捕获错误响应,比如401、500等 using (var errorResponse = (HttpWebResponse)ex.Response) { using (var reader = new StreamReader(errorResponse.GetResponseStream())) { string errorXml = reader.ReadToEnd(); Console.WriteLine("请求失败,错误信息:" + errorXml); } } } } }
关键注意事项
- 命名空间必须完全匹配:服务端的
createEvents方法、BusinessEvent、WSEntry都有对应的XML命名空间,一定要从WSDL里找准确,否则服务端会识别不了请求参数。 - SOAP版本不要搞错:SOAP 1.2的Content-Type是
application/soap+xml,如果用成SOAP 1.1的text/xml,服务端会直接返回错误。 - MTOM的处理:如果你的事件包含大文件或二进制数据,需要启用MTOM,手动构造的话要用到
MtomMessageEncoder,或者直接用代理类的MTOM配置更简单。 - 异常处理:一定要捕获
WebException,因为SOAP服务的错误通常会返回HTTP错误码(比如401表示认证失败,500表示服务端异常),通过异常可以拿到详细的错误XML。
内容的提问来源于stack exchange,提问作者Rachel-Abc
相关产品推荐
相关产品推荐

