http://www.cnblogs.com/zitjubiz/archive/2011/09/27/WCF_Soap_Header.html
最近Oracle的DRM系统发布了新版本,其中的webService发生了重大的转变. 把验证信息放在了SoapHeader里面.
这样原来系统(在vs.net2005开发).net引用WebService就不能成功调用了. 因为默认的代理类调用是没有SoapHeader的.
新版DRM的Soap信息如下:
<
soap:Envelope
xmlns:soap
="http://schemas.xmlsoap.org/soap/envelope/"
>
< soap:Header >
< wsse:Security soap:mustUnderstand ="1" xmlns:wsse ="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" >
< wsse:Usernametoken >
< wsse:Username >UserName </ wsse:Username >
< wsse:Password Type ="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText" >Password </ wsse:Password >
</ wsse:Usernametoken >
</ wsse:Security >
< AppParameters xmlns ="http://drm.webservices.epm.oracle" >
< serverUrl >http://DRMServer:5240/Oracle/Drm/APIAdapter </ serverUrl >
< sessionParams >ProductVersion=11.1.2.1 </ sessionParams >
</ AppParameters >
</ soap:Header >
< soap:Body xmlns:ns1 ="http://drm.webservices.epm.oracle" >
< ns1:getVersions />
</ soap:Body >
</ soap:Envelope >
< soap:Header >
< wsse:Security soap:mustUnderstand ="1" xmlns:wsse ="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" >
< wsse:Usernametoken >
< wsse:Username >UserName </ wsse:Username >
< wsse:Password Type ="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText" >Password </ wsse:Password >
</ wsse:Usernametoken >
</ wsse:Security >
< AppParameters xmlns ="http://drm.webservices.epm.oracle" >
< serverUrl >http://DRMServer:5240/Oracle/Drm/APIAdapter </ serverUrl >
< sessionParams >ProductVersion=11.1.2.1 </ sessionParams >
</ AppParameters >
</ soap:Header >
< soap:Body xmlns:ns1 ="http://drm.webservices.epm.oracle" >
< ns1:getVersions />
</ soap:Body >
</ soap:Envelope >
在园子里搜了一下,找到下面的方法 .net 调用 Java编写的WebService
Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(
"
WinFormDRMService.soapHeader.xml
");
xml = new XmlDocument();
xml.Load(stream);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NaMetable);
nsmgr.AddNamespace( " soap ", " http://schemas.xmlsoap.org/soap/envelope/ ");
XmlNode SoaoBodyNode = xml.SelectSingleNode( " soap:Envelope/soap:Body ", nsmgr);
string SoapBodyNodeInnerXml = " <ns1: " + MethodName + " > ";
// 修改参数的值
foreach (DictionaryEntry de in Pars)
{
Hashtable subpars = de.Value as Hashtable;
// 如果参数不是Hashtable,就直接用其key,value
if (subpars == null)
{
SoapBodyNodeInnerXml += " <ns1: " + de.Key.ToString() + " > ";
SoapBodyNodeInnerXml += de.Value.ToString()+ " </ns1: " + de.Key.ToString() + " > ";
}
else
{
SoapBodyNodeInnerXml += " <ns1: " + de.Key.ToString() + " > ";
foreach (DictionaryEntry subde in subpars)
{
SoapBodyNodeInnerXml += " <ns1: " + subde.Key.ToString() + " > ";
SoapBodyNodeInnerXml += subde.Value.ToString() + " </ns1: " + subde.Key.ToString() + " > ";
}
SoapBodyNodeInnerXml += de.Value.ToString() + " </ns1: " + de.Key.ToString() + " > ";
}
}
SoapBodyNodeInnerXml += " </ns1: " + MethodName + " > ";
SoaoBodyNode.InnerXml = SoapBodyNodeInnerXml;
// 将修改后的XML文件保存到流中
// 这样做还可以保证发送的XML文件也是格式化的那种形式,而不是一整行
// 如通过OuterXml获取的就是一整行,这样也可能会导致服务端解析失败,个人这次就碰到这种情况了
MemoryStream outStream = new MemoryStream();
xml.Save(outStream);
xml = new XmlDocument();
xml.Load(stream);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NaMetable);
nsmgr.AddNamespace( " soap ", " http://schemas.xmlsoap.org/soap/envelope/ ");
XmlNode SoaoBodyNode = xml.SelectSingleNode( " soap:Envelope/soap:Body ", nsmgr);
string SoapBodyNodeInnerXml = " <ns1: " + MethodName + " > ";
// 修改参数的值
foreach (DictionaryEntry de in Pars)
{
Hashtable subpars = de.Value as Hashtable;
// 如果参数不是Hashtable,就直接用其key,value
if (subpars == null)
{
SoapBodyNodeInnerXml += " <ns1: " + de.Key.ToString() + " > ";
SoapBodyNodeInnerXml += de.Value.ToString()+ " </ns1: " + de.Key.ToString() + " > ";
}
else
{
SoapBodyNodeInnerXml += " <ns1: " + de.Key.ToString() + " > ";
foreach (DictionaryEntry subde in subpars)
{
SoapBodyNodeInnerXml += " <ns1: " + subde.Key.ToString() + " > ";
SoapBodyNodeInnerXml += subde.Value.ToString() + " </ns1: " + subde.Key.ToString() + " > ";
}
SoapBodyNodeInnerXml += de.Value.ToString() + " </ns1: " + de.Key.ToString() + " > ";
}
}
SoapBodyNodeInnerXml += " </ns1: " + MethodName + " > ";
SoaoBodyNode.InnerXml = SoapBodyNodeInnerXml;
// 将修改后的XML文件保存到流中
// 这样做还可以保证发送的XML文件也是格式化的那种形式,而不是一整行
// 如通过OuterXml获取的就是一整行,这样也可能会导致服务端解析失败,个人这次就碰到这种情况了
MemoryStream outStream = new MemoryStream();
xml.Save(outStream);
该方法调用成功,但它有个缺点,只适用了类比较少,没什么复杂类型的WebService,假如有上百个方法和自定义类,你还要自己解析xml包装成类,又等于重新造轮子,而且99%可能性没有微软造的好.
待续 To be continue...
调用非.net系统的Webservice的探索 ( 三 ) -WCF
WCF的模型和之前.net的WS有所不同. 你在添加Service Reference生成的代理类可以看到
而WCF著名的"ABC"
而我们这里调用java系统的WebService,只需要处理Address和Binding
来看看生成的app.config内容,留意黄色高亮的,是我们手工添加修改的.
<
configuration
>
< system.serviceModel >
< bindings >
< customBinding >
< binding name ="IDrmServiceSoapHttp" >
< security @H_308_502@authenticationMode ="UserNameOverTransport"
@H_308_502@ allowInsecureTransport ="true" @H_308_502@ includeTimestamp ="false" >
</ security >
< textMessageEncoding maxReadPoolSize ="64" maxWritePoolSize ="16"
messageVersion ="Soap11" writeEncoding ="utf-8" >
< readerQuotas maxDepth ="32" maxStringContentLength ="8192" maxArrayLength ="16384"
maxBytesPerRead ="4096" @H_308_502@maxNaMetableCharCount ="65536" />
</ textMessageEncoding >
< httpTransport manualAddressing ="false" maxBufferPoolSize ="524288"
maxReceivedMessageSize ="65536" allowCookies ="false" authenticationScheme ="Anonymous"
bypassproxyOnLocal ="false" decompressionEnabled ="true" hostNameComparisonMode ="StrongWildcard"
keepAliveEnabled ="true" maxBufferSize ="65536" proxyAuthenticationScheme ="Anonymous"
realm ="" transferMode ="Buffered" unsafeConnectionNtlmAuthentication ="false"
useDefaultWebProxy ="true" />
</ binding >
</ customBinding >
</ bindings >
< client >
< endpoint @H_308_502@address ="http://localhost:8080/oracle-epm-drm-webservices/DrmService"
binding ="customBinding" bindingConfiguration ="IDrmServiceSoapHttp"
contract ="DRM.IDrmService" name ="DrmServicePortType" >
< headers >
< AppParameters @H_308_502@xmlns ="http://drm.webservices.epm.oracle" >
< serverUrl > http://DRMServer:5240/Oracle/Drm/APIAdapter </ serverUrl >
< sessionParams > ProductVersion=11.1.2.1 </ sessionParams >
</ AppParameters >
</ headers >
</ endpoint >
</ client >
</ system.serviceModel >
</ configuration >
< system.serviceModel >
< bindings >
< customBinding >
< binding name ="IDrmServiceSoapHttp" >
< security @H_308_502@authenticationMode ="UserNameOverTransport"
@H_308_502@ allowInsecureTransport ="true" @H_308_502@ includeTimestamp ="false" >
</ security >
< textMessageEncoding maxReadPoolSize ="64" maxWritePoolSize ="16"
messageVersion ="Soap11" writeEncoding ="utf-8" >
< readerQuotas maxDepth ="32" maxStringContentLength ="8192" maxArrayLength ="16384"
maxBytesPerRead ="4096" @H_308_502@maxNaMetableCharCount ="65536" />
</ textMessageEncoding >
< httpTransport manualAddressing ="false" maxBufferPoolSize ="524288"
maxReceivedMessageSize ="65536" allowCookies ="false" authenticationScheme ="Anonymous"
bypassproxyOnLocal ="false" decompressionEnabled ="true" hostNameComparisonMode ="StrongWildcard"
keepAliveEnabled ="true" maxBufferSize ="65536" proxyAuthenticationScheme ="Anonymous"
realm ="" transferMode ="Buffered" unsafeConnectionNtlmAuthentication ="false"
useDefaultWebProxy ="true" />
</ binding >
</ customBinding >
</ bindings >
< client >
< endpoint @H_308_502@address ="http://localhost:8080/oracle-epm-drm-webservices/DrmService"
binding ="customBinding" bindingConfiguration ="IDrmServiceSoapHttp"
contract ="DRM.IDrmService" name ="DrmServicePortType" >
< headers >
< AppParameters @H_308_502@xmlns ="http://drm.webservices.epm.oracle" >
< serverUrl > http://DRMServer:5240/Oracle/Drm/APIAdapter </ serverUrl >
< sessionParams > ProductVersion=11.1.2.1 </ sessionParams >
</ AppParameters >
</ headers >
</ endpoint >
</ client >
</ system.serviceModel >
</ configuration >
MathServiceClient svc =
new MathServiceClient();
svc.ClientCredentials.UserName.UserName = " MyUserName ";
svc.ClientCredentials.UserName.Password = " MyPassword ";
label1.Text =svc.Add( 1, 2);
svc.ClientCredentials.UserName.UserName = " MyUserName ";
svc.ClientCredentials.UserName.Password = " MyPassword ";
label1.Text =svc.Add( 1, 2);
WCF整个使用方法对比起WSE就简单很多了.
但作为客户端来说,我粗略测试了性能,和WSE差不多,WCF还略慢一点.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。