将 XML 包装在 .net 中的 SOAP 信封中 [英] Wrap XML in SOAP envelope in .net
问题描述
我需要帮助将 XML 包装在第三方 SOAP 服务器的 SOAP 信封中.第三方为入站请求和出站响应提供了 xsd 文件.我已经获取了这些 XSD 文件并使用 xsd 工具创建了它们的 C# 类.我的问题是我需要用 SOAP 信封包装序列化的请求,但我不知道从哪里开始.我正在查看 Microsoft Web Service Enhancements 3,但这表明它仅适用于 .net 2.0 和 VS2005.我正在使用 VS2012 和 .net 4.5.此外,我已经考虑通过网络服务连接到服务器,但它似乎不兼容并且没有 WSDL.
I need help with wrapping an XML in a SOAP envelope for a third party SOAP server. The third party has provided xsd files for the inbound request and outbound response. I've taken those XSD files and created C# classes of them using the xsd tool. My problem is that I need to wrap the serialized request with a SOAP envelope and I don't know where to start. I was looking at the Microsoft Web Service Enhancements 3, but that says that it's only for .net 2.0 and VS2005. I am using VS2012 and .net 4.5. Also, I've looked into connecting to the server by way of web service but it doesn't seem compatible and does not have a WSDL.
以下是 SOAP 服务器对入站请求的期望示例.
The following is a sample of what the SOAP server expects for an inbound request.
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<soap:Body>
<GetBasicData xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="CRS610MI">
<CONO xmlns="">1</CONO>
<CUNO xmlns="">12345</CUNO>
</GetBasicData>
</soap:Body>
</soap:Envelope>
这是序列化的 XML 字符串的样子.
This is what the serialized XML string looks like.
<?xml version="1.0" encoding="utf-8"?>
<GetBasicData xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="CRS610MI">
<CONO xmlns="">1</CONO>
<CUNO xmlns="">12345</CUNO>
</GetBasicData>
我用于网络请求和响应的代码.
Code I'm using for my web request and response.
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);
}
我已经通过用第三方提供的示例文件中的文本替换我的序列化字符串来测试我的代码,并且它按预期工作.我还拿了我的序列化字符串并将信封文本插入正确的位置,这也有效,网络请求通过,我得到了我正在寻找的响应.如果没有手动将信封文本插入我的序列化字符串,我该怎么办.我必须想象有一种方法或类可以以标准化的方式为我解决这个问题?
I've tested my code by replacing my serialized string with the text in the sample file provided by the third party and it worked as expected. I also took my serialized string and inserted the envelope text in the correct places and that also worked, web request went through and I got the response I was looking for. Short of inserting the envelope text into my serialized string manually what can I do. I have to imagine there's a method or class that will take care of this for me in a standardized way?
推荐答案
我能够通过使用 XLST 将 XML 包装在 soap 中来解决这个问题.
I was able to solve this by using an XLST to wrap the XML in soap.
这是我的工作测试应用代码
Here's my working test app code
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:DariceM3 SOAPGetBasicData.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<T>(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>(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 代码
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:crs="CRS610MI" exclude-result-prefixes="crs">
<xsl:output method="xml"/>
<xsl:template match="/">
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<soap:Body>
<xsl:apply-templates select="node()|@*"/>
</soap:Body>
</soap:Envelope>
</xsl:template>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这篇关于将 XML 包装在 .net 中的 SOAP 信封中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!