zoukankan      html  css  js  c++  java
  • 关于.NET中动态调用Web Service服务的方法心得

    介绍.NET中动态调用Web Service的相关技术文章。

    在.NET中调用Web Service服务(WSDL)有两种可行的方法:
    1、通过Web 服务引用,在本地生成所要调用服务的类;(静态方法)
    2、通过给定的WSDL服务地址,动态生成Web Service服务类进行服务调用;(动态方法)

    由于1中的方法大部分人都会经常用到,因此暂不讨论。

    对于2,实现上较为复杂,主要的过程为:
    (1)读取WSDL内容到内存中;
    (2)根据WSDL内容,动态生成Web Service服务代码;
    (3)使用动态编译技术将生成的Web Service服务代码编译为DLL;
    (4)通过反射机制实现动态调用。
    _________________________________________________________

    有关这类技术请参考如下网站:
    1、《动态调用 WebService》
    地址:http://www.rainsts.net/article.asp?id=304
    2、《DynWsLib》
    地址:http://www.thinktecture.com/Resources/Software/DynWsLib/default.html
    说明:
    欧洲一家名位Thinktecture公司发布的开源项目,实现了比较完整的动态调用Web Service的方法,最新版本为1.6,支持.NET 2.0。最可贵的是这是一个完全开源的项目,我们可以下载下来根据实际情况进行一些修改,以适应不同的需求。
    3、WSE
    地址:http://msdn2.microsoft.com/en-us/webservices/aa740663.aspx
    说明:
    微软发布的支持Web Service的工具包。目前最新版本为3.0。
    _________________________________________________________
    Java 与 .NET的互调用
    这是本文重点要讨论的话题。
    由于项目需要,我们必须为客户提供一个.NET的动态调用Web Service包,以实现对Oracle的BPEL服务器上发布的Web Service进行动态调用。

    在使用动态DynWSLib生成的对象进行调用的时候,发现只能够发送一次SOAP,当第二次发送之后,.NET程序会抛出链接已被断开的异常。

    这样的错误十分诡异,在网上搜索了之后,发现问题在于BPEL服务器与Microsoft的IIS之间是有区别的,看来微软还是很喜欢搞垄断。

    下面说说个人分析的结论,共大家参考:
    问题的出现可能和微软的地层支持有关,本人猜测,微软生成的Web Service对象在发送SOAP请求时,建立的HTTP链接在请求发送完成之后,会长时间保持链接状态(即链接没有立即断开),而对于Oracle的Web服务器,当相应SOAP请求之后,会主动断开HTTP链接,这也许就是为什么用微软的东西发送SOAP消息给Oracle服务器,第一次能够成功,第二次就会报链接已断开,发送失败的错误。后面的解决方案中也部分支持了我的这个观点。
    ________________________________________________________
    解决方案:
    WSE + HTTP
    1、使用WSE构造SOAP请求消息;
    2、使用HTTP发送SOAP消息。

    下面给出部分参考代码:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;
    using System.Net;
    using System.Net.Security;
    using System.Security.Cryptography.X509Certificates;

    namespace My.Web.WebService
    {
        internal class SoapHttpClient
        {
            private string url = null;

            public SoapHttpClient(string url)
            {
                this.url = url;
            }

            public string RequestResponse(string methodName, string envelope)
            {
                // 用于支持SSL
                ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(OnCheckRemoteCallback);

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Credentials = CredentialCache.DefaultCredentials;

                // 必须设置该值为flase,否则出错
                request.KeepAlive = false;

                request.Method = "POST";
                request.ContentType = "text/xml";
                request.Headers.Add("SOAPAction", methodName);

                UTF8Encoding encoding = new UTF8Encoding();
                byte[] bodyBytes = encoding.GetBytes(envelope);
                request.ContentLength = bodyBytes.Length;
                using (Stream serviceRequestBodyStream = request.GetRequestStream())
                {
                    serviceRequestBodyStream.Write(bodyBytes, 0, bodyBytes.Length);
                    serviceRequestBodyStream.Close();

                    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                    {
                        using (StreamReader reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8))
                        {
                            string result = reader.ReadToEnd();
                            return result;
                        }
                    }
                }
            }

            /// <summary>
            /// Using untrusted SSL certificates
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="certificate"></param>
            /// <param name="chain"></param>
            /// <param name="sslPolicyErrors"></param>
            /// <returns></returns>
            private static bool OnCheckRemoteCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
            {
                return true;
            }
        }
    }

    _________________________________________________________
    [b]最后讨论一下有关DynWSLib动态调用的问题。[/b]
    使用DynWSLib在调用Web Service服务的时候,需要对传入的参数进行适当的处理。

    private void bnCalc_Click(object sender, System.EventArgs e)
      {
                DynamicWebServiceProxy ws = new DynamicWebServiceProxy();

                ws.EnableMessageAccess = true;
                ws.Wsdl = "http://localhost:3092/CatalogueDataPublishTest.asmx?WSDL";
                //ws.Url = new Uri("http://localhost:3092/CatalogueDataPublishTest.asmx");
                ws.TypeName = "CatalogueDataPublishTest";
                ws.MethodName = "HelloWorld";
               
                //ws.AddParameter(XmlHelper.Object2Xml(new DCMCatalogueWork()));
                //ws.AddParameter(new DCMCatalogueWork());

                AddParameter(ws, "dcw", new Sobey.MAM.Common.InterfaceDataType.DCM2.Catalogue.SystemDefineType());

                object result = ws.InvokeCall();

                MessageBox.Show(result.ToString());
      }

            /// <summary>
            /// 添加WebService类型体系中的参数值
            /// </summary>
            /// <param name="ws">代理</param>
            /// <param name="name">参数名字(WebService中的参数名字,这里也可以是参数位置索引)</param>
            /// <param name="value">参数取值</param>
            public void AddParameter(DynamicWebServiceProxy ws,string name, object value)
            {
                //找到该参数的类型
                Type objType = GetParameterType(ws,name);

                //由于2个对象只是命名空间不同,不能强制转换,就采用序列化与反序列化的方式进行深度拷贝。
                ws.AddParameter(XmlHelper.Xml2Object(XmlHelper.Object2Xml(value), objType));
            }

            /// <summary>
            /// 获取WebService方法指定参数的类型
            /// </summary>
            /// <param name="ws">服务代理</param>
            /// <param name="parameterName">参数名称</param>
            /// <returns></returns>
            private Type GetParameterType(DynamicWebServiceProxy ws,string parameterName)
            {
                Type t = ws.Instance.GetType();
                MethodInfo methodInfo = t.GetMethod(ws.MethodName);

                // 获得方法的参数类型
                ParameterInfo[] param = methodInfo.GetParameters();

                if (param.Length < 1)
                {
                    return null;
                }

                foreach (ParameterInfo pi in param)
                {
                    if (pi.Name == parameterName)
                    {
                        return pi.ParameterType;
                    }
                }

                return null;
            }

  • 相关阅读:
    hi3531 SDK 编译 uboot, 修改PHY地址, 修改 uboot 参数 . 分类: arm-linux-Ubuntu HI3531 2014-06-18 08:55 1204人阅读 评论(0) 收藏
    hi3531 SDK 编译 kernel, 修改 参数 . 分类: HI3531 arm-linux-Ubuntu 2014-06-18 08:54 773人阅读 评论(0) 收藏
    hi3531 SDK已编译文件系统制作jffs2文件系统镜像并解决问题 . 分类: arm-linux-Ubuntu HI3531 2014-06-18 08:45 951人阅读 评论(0) 收藏
    Ubuntu 上 hi3531 交叉编译环境 arm-hisiv100nptl-linux 搭建过程 分类: HI3531 arm-linux-Ubuntu 2014-06-18 08:44 807人阅读 评论(0) 收藏
    Linux 软连接与硬连接 分类: arm-linux-Ubuntu 2014-06-18 08:42 466人阅读 评论(0) 收藏
    SUSE(Linux操作系统) 分类: arm-linux-Ubuntu 2014-06-17 14:27 502人阅读 评论(0) 收藏
    项目管理中的导向性 . 分类: 项目管理 2014-06-14 15:11 184人阅读 评论(0) 收藏
    ios 开发初步(zz)
    中国字 (zz)
    CString TO Double (zz)
  • 原文地址:https://www.cnblogs.com/zjoch/p/1495371.html
Copyright © 2011-2022 走看看