随笔 - 290  文章 - 10  评论 - 85  2

最近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>
在园子里搜了一下, 找到下面的方法  .net 调用 Java编写的WebService
但他这个文章,每个方法都要一个xml,太啰嗦了,我改成传MethodName和Param进去之后,重写整个<soap:body>

修改后的关键代码如下:

            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);

 该方法调用成功,但它有个缺点,只适用了类比较少,没什么复杂类型的WebService, 假如有上百个方法和自定义类, 你还要自己解析xml包装成类,又等于重新造轮子,而且99%可能性没有微软造的好.

 

待续 To be continue...

 

 

posted on 2011-09-23 17:52  Gu  阅读(...)  评论(...编辑  收藏