c#通过 wsdl调用Webservice 源码

来源:互联网 发布:数据库物理层 编辑:程序博客网 时间:2024/06/01 09:05

1. 将网上查找的C# 通过WSDL调用WEBSERVICE代码整理如下:

   

 /// <summary>      /// WebServiceProxy 的摘要说明      /// </summary>      [WebService(Namespace = "http://tempuri.org/")]    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]    [ToolboxItem(false)]    // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。      // [System.Web.Script.Services.ScriptService]      public class WebServiceProxy : System.Web.Services.WebService    {        #region 私有变量和属性定义        /// <summary>                           /// web服务地址                                   /// </summary>                                      private string _wsdlUrl = string.Empty;        /// <summary>                           /// web服务名称                                   /// </summary>                                      private string _wsdlName = string.Empty;        /// <summary>                           /// 代理类命名空间                                   /// </summary>                                      private string _wsdlNamespace = "FrameWork.WebService.DynamicWebServiceCalling.{0}";        /// <summary>                           /// 代理类类型名称                                   /// </summary>                                      private Type _typeName = null;        /// <summary>                           /// 程序集名称                                     /// </summary>                                      private string _assName = string.Empty;        /// <summary>                           /// 代理类所在程序集路径                                    /// </summary>                                      private string _assPath = string.Empty;        /// <summary>                           /// 代理类的实例                                    /// </summary>                                      private object _instance = null;        /// <summary>                           /// 代理类的实例                                    /// </summary>                                      private object Instance        {            get            {                if (_instance == null)                {                    _instance = Activator.CreateInstance(_typeName);                    return _instance;                }                else                    return _instance;            }        }        #endregion        #region 构造函数        public WebServiceProxy(string wsdlUrl)        {            this._wsdlUrl = wsdlUrl;            string wsdlName = WebServiceProxy.getWsclassName(wsdlUrl);            this._wsdlName = wsdlName;            this._assName = string.Format(_wsdlNamespace, wsdlName);            this._assPath = System.Environment.CurrentDirectory + "\\" + this._assName + getMd5Sum(this._wsdlUrl) + ".dll";            MISLog.GetInstance().Write(MISLog.MSG_LEVEL.FLUSH, _assPath);            if (wsdlUrl.Contains("?wsdl"))            {                this.CreateServiceAssembly();            }            else if (wsdlUrl.Contains(".dll"))            {                CreateDllAssembly();            }        }        #endregion        #region 得到WSDL信息,生成本地代理类并编译为DLL,构造函数调用,类生成时加载        /// <summary>                                   /// 得到WSDL信息,生成本地代理类并编译为DLL                                   /// </summary>                                      private void CreateServiceAssembly()        {            if (this.checkCache())            {                this.initTypeName();                return;            }            if (string.IsNullOrEmpty(this._wsdlUrl))            {                return;            }            try            {                //使用WebClient下载WSDL信息                                         WebClient web = new WebClient();                                Stream stream = web.OpenRead(this._wsdlUrl);                ServiceDescription description = ServiceDescription.Read(stream);//创建和格式化WSDL文档                  ServiceDescriptionImporter importer = new ServiceDescriptionImporter();//创建客户端代理代理类                  importer.ProtocolName = "Soap";                importer.Style = ServiceDescriptionImportStyle.Client;  //生成客户端代理                                         importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;                importer.AddServiceDescription(description, null, null);//添加WSDL文档                  //使用CodeDom编译客户端代理类                                   MISLog.GetInstance().Write(MISLog.MSG_LEVEL.FLUSH, "CodeNamespace");                CodeNamespace nmspace = new CodeNamespace(_assName);    //为代理类添加命名空间                                  CodeCompileUnit unit = new CodeCompileUnit();                unit.Namespaces.Add(nmspace);                this.checkForImports(this._wsdlUrl, importer);                ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit);                CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");                CompilerParameters parameter = new CompilerParameters();                parameter.ReferencedAssemblies.Add("System.dll");                parameter.ReferencedAssemblies.Add("System.XML.dll");                parameter.ReferencedAssemblies.Add("System.Web.Services.dll");                parameter.ReferencedAssemblies.Add("System.Data.dll");                parameter.GenerateExecutable = false;                parameter.GenerateInMemory = false;                parameter.IncludeDebugInformation = false;                CompilerResults result = provider.CompileAssemblyFromDom(parameter, unit);                provider.Dispose();                if (result.Errors.HasErrors)                {                    string errors = string.Format(@"编译错误:{0}错误!", result.Errors.Count);                    foreach (CompilerError error in result.Errors)                    {                        errors += error.ErrorText;                    }                    MISLog.GetInstance().Write(MISLog.MSG_LEVEL.FLUSH, errors);                }                this.copyTempAssembly(result.PathToAssembly);                this.initTypeName();            }            catch (Exception e)            {                MISLog.GetInstance().Write(MISLog.MSG_LEVEL.FLUSH, e.ToString());            }        }        private void CreateDllAssembly()        {                        Assembly serviceAsm = Assembly.LoadFrom(System.Environment.CurrentDirectory + "\\" + _wsdlUrl);            _typeName = serviceAsm.GetType(MISConfig.GetInstance().db.Database);        }        #endregion        #region 执行Web服务方法        /// <summary>                                   /// 执行代理类指定方法,有返回值                                        /// </summary>                                          /// <param   name="methodName">方法名称</param>                                   /// <param   name="param">参数</param>                                      /// <returns>object</returns>                                         public object ExecuteQuery(string methodName, object[] param)        {            object rtnObj = null;            try            {                if (this._typeName == null)                {                    //记录Web服务访问类名错误日志代码位置                     MISLog.GetInstance().Write(MISLog.MSG_LEVEL.FLUSH, "服务访问类名【" + this._wsdlName + "】不正确,请检查!");                    System.Windows.Forms.MessageBox.Show(MultiLanguage.GetString("MIS_Connect_FAIL"));                    return null;                                   }                //调用方法                  MethodInfo mi = this._typeName.GetMethod(methodName);                if (mi == null)                {                    //记录Web服务方法名错误日志代码位置                      MISLog.GetInstance().Write(MISLog.MSG_LEVEL.FLUSH, "Web服务访问方法名【" + methodName + "】不正确,请检查!");                    System.Windows.Forms.MessageBox.Show(MultiLanguage.GetString("MIS_Connect_FAIL"));                }                try                {                    if (param == null)                        rtnObj = mi.Invoke(Instance, null);                    else                    {                        rtnObj = mi.Invoke(Instance, param);                    }                }                catch (TypeLoadException tle)                {                    //记录Web服务方法参数个数错误日志代码位置                      MISLog.GetInstance().Write(MISLog.MSG_LEVEL.FLUSH, "Web服务访问方法【" + methodName + "】参数个数不正确,请检查!");                     System.Windows.Forms.MessageBox.Show(MultiLanguage.GetString("MIS_Connect_FAIL"));                     Log.GetInstance().WriteSYS(tle.ToString());                }            }            catch (Exception ex)            {                MISLog.GetInstance().Write(MISLog.MSG_LEVEL.FLUSH, ex.ToString());                System.Windows.Forms.MessageBox.Show(MultiLanguage.GetString("MIS_Connect_FAIL"));            }            return rtnObj;        }        /// <summary>                                   /// 执行代理类指定方法,无返回值                                        /// </summary>                                          /// <param   name="methodName">方法名称</param>                                   /// <param   name="param">参数</param>                                      public void ExecuteNoQuery(string methodName, object[] param)        {            try            {                if (this._typeName == null)                {                    //记录Web服务访问类名错误日志代码位置                    MISLog.GetInstance().Write(MISLog.MSG_LEVEL.FLUSH, "Web服务访问类名【" + this._wsdlName + "】不正确,请检查!");                    System.Windows.Forms.MessageBox.Show(MultiLanguage.GetString("MIS_Connect_FAIL"));                    return;                }                //调用方法                  MethodInfo mi = this._typeName.GetMethod(methodName);                if (mi == null)                {                    //记录Web服务方法名错误日志代码位置                      MISLog.GetInstance().Write(MISLog.MSG_LEVEL.FLUSH, "Web服务访问方法名【" + methodName + "】不正确,请检查!");                    System.Windows.Forms.MessageBox.Show(MultiLanguage.GetString("MIS_Connect_FAIL"));                }                try                {                    if (param == null)                        mi.Invoke(Instance, null);                    else                        mi.Invoke(Instance, param);                }                catch (TypeLoadException tle)                {                    //记录Web服务方法参数个数错误日志代码位置                      MISLog.GetInstance().Write(MISLog.MSG_LEVEL.FLUSH, "Web服务访问方法【" + methodName + "】参数个数不正确,请检查!");                    System.Windows.Forms.MessageBox.Show(MultiLanguage.GetString("MIS_Connect_FAIL"));                    Log.GetInstance().WriteSYS(tle.ToString());                }            }            catch (Exception ex)            {                MISLog.GetInstance().Write(MISLog.MSG_LEVEL.FLUSH, ex.ToString());                System.Windows.Forms.MessageBox.Show(MultiLanguage.GetString("MIS_Connect_FAIL"));            }        }        #endregion        #region 私有方法        /// <summary>                                       /// 得到代理类类型名称                                         /// </summary>                                          private void initTypeName()        {            Assembly serviceAsm = Assembly.LoadFrom(this._assPath);            Type[] types = serviceAsm.GetTypes();            string objTypeName = "";            foreach (Type t in types)            {                if (t.BaseType == typeof(SoapHttpClientProtocol))                {                    objTypeName = t.Name;                    break;                }            }            _typeName = serviceAsm.GetType(this._assName + "." + objTypeName);        }        /// <summary>                               /// 根据web   service文档架构向代理类添加ServiceDescription和XmlSchema                                     /// </summary>                                          /// <param   name="baseWSDLUrl">web服务地址</param>                                   /// <param   name="importer">代理类</param>                                      private void checkForImports(string baseWsdlUrl, ServiceDescriptionImporter importer)        {            DiscoveryClientProtocol dcp = new DiscoveryClientProtocol();            dcp.DiscoverAny(baseWsdlUrl);            dcp.ResolveAll();            foreach (object osd in dcp.Documents.Values)            {                if (osd is ServiceDescription) importer.AddServiceDescription((ServiceDescription)osd, null, null); ;                if (osd is XmlSchema) importer.Schemas.Add((XmlSchema)osd);            }        }        /// <summary>                                   /// 复制程序集到指定路径                                        /// </summary>                                          /// <param   name="pathToAssembly">程序集路径</param>                                      private void copyTempAssembly(string pathToAssembly)        {            File.Copy(pathToAssembly, this._assPath);        }        private string getMd5Sum(string str)        {            Encoder enc = System.Text.Encoding.Unicode.GetEncoder();            byte[] unicodeText = new byte[str.Length * 2];            enc.GetBytes(str.ToCharArray(), 0, str.Length, unicodeText, 0, true);            MD5 md5 = new MD5CryptoServiceProvider();            byte[] result = md5.ComputeHash(unicodeText);            StringBuilder sb = new StringBuilder();            for (int i = 0; i < result.Length; i++)            {                sb.Append(result[i].ToString("X2"));            }            return sb.ToString();        }        /// <summary>                                   /// 是否已经存在该程序集                                        /// </summary>                                          /// <returns>false:不存在该程序集,true:已经存在该程序集</returns>                                        private bool checkCache()        {            if (File.Exists(this._assPath))            {                return true;            }            return false;        }        //私有方法,默认取url入口的文件名为类名          private static string getWsclassName(string wsdlUrl)        {            string[] parts = wsdlUrl.Split('/');            string[] pps = parts[parts.Length - 1].Split('.');            return pps[0];        }        #endregion    }


上面这部分可以直接使用。

2.下面这部分为网上看到类似的代码,并含有备注。用于备忘 【点击打开链接】

public static class WebServiceHelper
    {
        /// <summary>
        /// 动态调用WebService
        /// </summary>
        /// <param name="url">WebService地址</param>
        /// <param name="methodname">方法名(模块名)</param>
        /// <param name="args">参数列表,无参数为null</param>
        /// <returns>object</returns>
        public static object InvokeWebService(string url, string methodname, object[] args)
        {
            return InvokeWebService(url, null, methodname, args);
        }
        /// <summary>
        /// 动态调用WebService
        /// </summary>
        /// <param name="url">WebService地址</param>
        /// <param name="classname">类名</param>
        /// <param name="methodname">方法名(模块名)</param>
        /// <param name="args">参数列表</param>
        /// <returns>object</returns>
        public static object InvokeWebService(string url, string classname, string methodname, object[] args)
         {
             string @namespace = "fangqm.Netbank.WebService.webservice";
             if (classname == null || classname == "")
             {
                 classname = WebServiceHelper.GetClassName(url);
             }
            //获取服务描述语言(WSDL)
              WebClient wc = new WebClient();
             Stream stream = wc.OpenRead(url+"?WSDL");//【1】
            ServiceDescription sd = ServiceDescription.Read(stream);//【2】
             ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();//【3】
             sdi.AddServiceDescription(sd, "", "");
             CodeNamespace cn = new CodeNamespace(@namespace);//【4】
             //生成客户端代理类代码
             CodeCompileUnit ccu = new CodeCompileUnit();//【5】
            ccu.Namespaces.Add(cn);
             sdi.Import(cn, ccu);
            CSharpCodeProvider csc = new CSharpCodeProvider();//【6】
             ICodeCompiler icc = csc.CreateCompiler();//【7】
             //设定编译器的参数
             CompilerParameters cplist = new CompilerParameters();//【8】
             cplist.GenerateExecutable = false;
             cplist.GenerateInMemory = true;
             cplist.ReferencedAssemblies.Add("System.dll");
             cplist.ReferencedAssemblies.Add("System.XML.dll");
             cplist.ReferencedAssemblies.Add("System.Web.Services.dll");
             cplist.ReferencedAssemblies.Add("System.Data.dll");
             //编译代理类
             CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu);//【9】
             if (true == cr.Errors.HasErrors)
            {
 System.Text.StringBuilder sb = new StringBuilder();
                foreach (CompilerError ce in cr.Errors)
                 {
                     sb.Append(ce.ToString());
                     sb.Append(System.Environment.NewLine);
                 }
                 throw new Exception(sb.ToString());
             }
 
            //生成代理实例,并调用方法
             System.Reflection.Assembly assembly = cr.CompiledAssembly;
             Type t = assembly.GetType(@namespace+"."+ classname, true, true);
             object bj = Activator.CreateInstance(t);//【10】
             System.Reflection.MethodInfo mi = t.GetMethod(methodname);//【11】
             return mi.Invoke(obj, args);
 
         }
        private static string GetClassName(string url)
        {
            //假如URL为"http://localhost/InvokeService/Service1.asmx"
            //最终的返回值为 Service1
            string[] parts = url.Split('/');
            string[] pps = parts[parts.Length - 1].Split('.');
            return pps[0];
        }
    }
}
 
 上面的注释已经很好的说明了各代码段的功能,下面给个例子看看,这个例子是通过访问http://www.webservicex.net/globalweather.asmx服务来获取各大城市的天气状况。
             stringurl="http://www.webservicex.net/globalweather.asmx";
            string[] args=newstring[2] ;
             args[0]=this.textBox_CityName.Text ;
             args[1]="China";
            objectresult=WebServiceHelper.InvokeWebService(url ,"GetWeather",args) ;
            this.label_Result.Text=result.ToString() ;
如果没有参数,则参数为null


     上述的例子中,调用web服务使用了两个参数,第一个是城市的名字,第二个是国家的名字,Web服务返回的是XML文档,可以从其中解析出温度、风力等天气情况。
    
   关于这段代码的注释

【2】    ServiceDescription类提供一种方法,以创建和格式化用于描述 XML Web services 的有效的 Web 服务描述语言 (WSDL) 文档文件,该文件是完整的,具有适当的命名空间、元素和特性。 无法继承此类。
ServiceDescription.Read 方法 (Stream) 通过直接从 Stream实例加载 XML 来初始化ServiceDescription类的实例。
 【3】    ServiceDescriptionImporter 类 公开一种为 XML Web services 生成客户端代理类的方法。
ServiceDescriptionImporter.AddServiceDescription 方法 将指定的ServiceDescription添加到要导入的ServiceDescriptions值的集合中。
 【4】   CodeNamespace表示命名空间声明。
 【5】   CodeCompileUnit会提供一个CodeDOM程式圆形的容器,CodeCompileUnit含有一个集合,可以储存含有CodeDOM原始程式码原形,专案参考的组件集合以及专案组件属性集合的CodeNamespace物件。
 【6】   CSharpCodeProvider类提供存取C#程式码产生器和程式码编译器的执行个体。
 【7】   取得C#程式码编译器的执行个体
 【8】   创建编译器的参数实例
 【9】   CompilerResults表示从编译器返回的编译结果。使用指定的编译器设定,根据CodeCompileUnit物件之指定阵列所包含的System.CodeDom树状结构,编译一个组件。
 【10】 Activator类包含特定的方法,用以在本地或从远程创建对象类型,或获取对现有远程对象的引用。无法继承此类Activator.CreateInstance 方法  使用与指定参数匹配程度最高的构造函数创建指定类型的实例。
 【11】 MethodInfo 的实例可以通过调用GetMethods或者Type对象或派生自Type的对象的GetMethod方法来获取,还可以通过调用表示泛型方法定义的 MethodInfo 的MakeGenericMethod方法来获取。

0 0