在.net中的SOAP信封中包装XML

我需要帮助将XML封装在第二方SOAP服务器的SOAP信封中。 第三方为入站请求和出站响应提供了xsd文件。 我已经使用xsd工具获取了这些XSD文件并创建了它们的C#类。 我的问题是我需要用SOAP信封包装序列化的请求,我不知道从哪里开始。 我正在查看Microsoft Web服务增强function3,但这表明它仅适用于.net 2.0和VS2005。 我正在使用VS2012和.net 4.5。 此外,我已经考虑通过Web服务连接到服务器,但它似乎不兼容, 并且没有WSDL

以下是SOAP服务器对入站请求的预期示例。

    1 12345    

这就是序列化XML字符串的样子。

   1 12345  

代码我用于我的网络请求和响应。

 Byte[] byteArray = System.Text.UTF8Encoding.UTF8.GetBytes(data); WebRequest webRequest = WebRequest.Create(@"http://myserver:8888"); webRequest.ContentLength = byteArray.Length; webRequest.ContentType = @"text/xml; charset=utf-8"; webRequest.Headers.Add("SOAPAction", @"http://schemas.xmlsoap.org/soap/envelope/"); webRequest.Method = "POST"; Stream requestStream = webRequest.GetRequestStream(); requestStream.Write(byteArray, 0, byteArray.Length); requestStream.Close(); requestStream.Dispose(); WebResponse webResponse = webRequest.GetResponse(); Stream responseStream = webResponse.GetResponseStream(); StreamReader streamReader = new StreamReader(responseStream); String line; while ((line = streamReader.ReadLine()) != null) { Debug.WriteLine(line); } 

我已经通过用第三方提供的示例文件中的文本替换我的序列化字符串来测试我的代码,并且它按预期工作。 我也拿了我的序列化字符串并将信封文本插入正确的位置,这也有效,网页请求通过,我得到了我正在寻找的响应。 没有手动将信封文本插入我的序列化字符串我该怎么办。 我不得不想象有一种方法或课程能够以标准化的方式为我解决这个问题吗?

如果服务提供者不提供WSDL,那么您不应该与他们做生意。 它不是火箭科学,而是SOAP Web服务的标准方式。 这只是十多年来的标准。 我真的很想知道这个服务提供商还有什么其他方式不称职。

如果你别无选择,只能与不称职的商业伙伴做生意,那么

  1. 祝你好运
  2. 创建自己的 WSDL以匹配其服务,然后使用“添加服务引用”来创建与服务通信所必需的代理类。

我能够通过使用XLST将XML包装在soap中来解决这个问题。

这是我的工作测试应用程序代码

 using System; using System.Diagnostics; using System.IO; using System.Net; using System.Text; using System.Xml; using System.Xml.Serialization; using System.Xml.XPath; using System.Xml.Xsl; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { GetBasicData getBasicData = new GetBasicData(); getBasicData.CONO = "1"; getBasicData.CUNO = "201702"; XPathDocument requestXPathDocument; if (SerializeIntoRequestXPathDocument(getBasicData, out requestXPathDocument)) { XmlDocument requestXmlDocument; if (CreateRequestXMLDocument(requestXPathDocument, @"Z:\Darice\M3 SOAP\GetBasicData.xsl", out requestXmlDocument)) { XmlDocument responseXmlDocument; if (ExecuteRequestSoap(requestXmlDocument, out responseXmlDocument)) { MemoryStream unwrappedMemoryStream; if (UnwrapSoapResponseXmlDocumentIntoMemoryStream(responseXmlDocument, out unwrappedMemoryStream)) { GetBasicDataResponse getBasicDataResponse; if (!DeserializeResponseMemoryStream(unwrappedMemoryStream, out getBasicDataResponse)) { Debug.WriteLine("FAIL"); } } } } } Console.ReadLine(); } //STATIC FUNCTIONS private static Boolean CreateRequestXMLDocument(XPathDocument xPathDocument, String xslPath, out XmlDocument xmlDocument) { try { using (MemoryStream memoryStream = new MemoryStream()) { using (StreamWriter streamWriter = new StreamWriter(memoryStream)) { XmlWriter xmlWriter = XmlWriter.Create(streamWriter); XsltSettings xsltSettings = new XsltSettings(); xsltSettings.EnableScript = true; XslCompiledTransform xslCompiledTransform = new XslCompiledTransform(); xslCompiledTransform.Load(xslPath, xsltSettings, null); xslCompiledTransform.Transform(xPathDocument, xmlWriter); memoryStream.Position = 0; using (StreamReader streamReader = new StreamReader(memoryStream)) { XmlReader xmlReader = XmlReader.Create(streamReader); xmlDocument = new XmlDocument(); xmlDocument.Load(xmlReader); } } } } catch (Exception exception) { Debug.WriteLine(exception); xmlDocument = null; return false; } return true; } private static Boolean DeserializeResponseMemoryStream(MemoryStream memoryStream, out T xmlObject) { try { using (StreamReader streamReader = new StreamReader(memoryStream)) { XmlSerializer xmlSerializer = new XmlSerializer(typeof(T)); using (XmlReader xmlReader = XmlReader.Create(streamReader)) { xmlObject = (T)xmlSerializer.Deserialize(xmlReader); } } } catch (Exception exception) { Debug.WriteLine(exception); xmlObject = default(T); return false; } return true; } private static Boolean ExecuteRequestSoap(XmlDocument requestXmlDocument, out XmlDocument responseXmlDocument) { try { Byte[] byteArray = UTF8Encoding.UTF8.GetBytes(requestXmlDocument.OuterXml); WebRequest webRequest = WebRequest.Create(Properties.Resources.SoapServerAddress); webRequest.ContentLength = byteArray.Length; webRequest.ContentType = @"text/xml; charset=utf-8"; webRequest.Headers.Add("SOAPAction", @"http://schemas.xmlsoap.org/soap/envelope/"); webRequest.Method = "POST"; using (Stream requestStream = webRequest.GetRequestStream()) { requestStream.Write(byteArray, 0, byteArray.Length); using (WebResponse webResponse = webRequest.GetResponse()) { using (Stream responseStream = webResponse.GetResponseStream()) { using (StreamReader streamReader = new StreamReader(responseStream)) { responseXmlDocument = new XmlDocument(); responseXmlDocument.LoadXml(streamReader.ReadToEnd()); } } } } } catch (Exception exception) { Debug.WriteLine(exception); responseXmlDocument = null; return false; } return true; } private static Boolean SerializeIntoRequestXPathDocument(T dataObject, out XPathDocument xPathDocument) { try { XmlSerializer xmlSerializer = new XmlSerializer(typeof(T)); using (MemoryStream memoryStream = new MemoryStream()) { using (StreamWriter streamWriter = new StreamWriter(memoryStream)) { xmlSerializer.Serialize(streamWriter, dataObject); memoryStream.Position = 0; using (StreamReader streamReader = new StreamReader(memoryStream)) { memoryStream.Position = 0; xPathDocument = new XPathDocument(streamReader); } } } } catch (Exception exception) { Debug.WriteLine(exception); xPathDocument = null; return false; } return true; } private static Boolean UnwrapSoapResponseXmlDocumentIntoMemoryStream(XmlDocument responseXmlDocument, out MemoryStream memoryStream) { try { XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(responseXmlDocument.NameTable); xmlNamespaceManager.AddNamespace("tns", "CRS610MI"); xmlNamespaceManager.AddNamespace("SOAP", @"http://schemas.xmlsoap.org/soap/envelope/"); XmlNode xmlNode = responseXmlDocument.SelectSingleNode(@"/SOAP:Envelope/SOAP:Body/tns:GetBasicDataResponse", xmlNamespaceManager); memoryStream = new MemoryStream(UTF8Encoding.UTF8.GetBytes(xmlNode.OuterXml)); } catch (Exception exception) { Debug.WriteLine(exception); memoryStream = null; return false; } return true; } } } 

这是XSL代码

                 

您需要使用MessageContract为soap标记您的类

 [MessageContract] public class ExampleResponse { private string _myResponse = String.Empty; [MessageBodyMember(Name = "ResponseToGive", Namespace = "http://myserver:8888")] public string ResponseToGive { get { return _myResponse; } set { _myResponse = value; } } } 

我不明白为什么有些人如此坚决以至于你必须使用WSDL。 WSDL很简单,您可以调用它们的方法,并使用它们的实体,并且是可选的。

我已经通过转到他们服务的确切url来实现这一点,例如https://something.com/SomeService/TheService.asmx?method=DoSomething

只需分析其API定义的精确标头和XML,包括SOAP信封。 第一部分应该是标题信息,然后是XML。 完全按照指定的方式创建XML,包括信封标记。 对于Header:POST,Host,Content-Type和SOAPAction是最重要的。 我发现有些服务器不需要Content-Length,即使它们在API中列出。

这是一些示例代码

 public void PostXMLData(string serviceUrl, XDocument requestXML) { HttpWebRequest req = (HttpWebRequest)WebRequest.Create(serviceUrl); req.Method = "POST"; req.Host = "SOMETHING"; req.ContentType = "text/xml; charset=utf-8"; req.Headers.Add("SOAPAction", "SOMETHING"); req.Accept = "text/xml"; using (Stream stream = req.GetRequestStream()) { requestXML.Save(stream); } using (WebResponse resp = req.GetResponse()) { using (StreamReader rd = new StreamReader(resp.GetResponseStream())) { var result = rd.ReadToEnd(); if (result.Contains("error")) { throw new Exception($"XML Submission Failed: {result}"); } } } }