关于.NET中动态调用Web Service服务的方法心得。
2007-06-28 17:33
716 查看
介绍.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;
}
}
}
_________________________________________________________
最后讨论一下有关DynWSLib动态调用的问题。
使用DynWSLib在调用Web Service服务的时候,需要对传入的参数进行适当的处理。
1、获取所调用的方法的参数类型。
/// <summary>
/// 获取参数类型。该方法只获取第一个参数的类型。
/// </summary>
/// <returns></returns>
private Type GetParameterType()
{
Type t = wsp.Instance.GetType();
MethodInfo methodInfo = t.GetMethod(wsp.MethodName);
// 获得方法的参数类型
ParameterInfo[] param = methodInfo.GetParameters();
if (param.Length < 1)
return null;
// 实例化参数类型
Type objType = param[0].ParameterType;
return objType;
}
2、添加参数到调用方法中。
private DynamicWebServiceProxy wsp = null;
// For SOAP Body Parameters.
private IDictionary paramsTable = new Hashtable();
public void AddParameter(string name, object value)
{
Type objType = GetParameterType();
// 处理字符串类型
if (objType == "".GetType())
{
wsp.AddParameter(value);
}
else // 处理对象类型
{
object obj = Activator.CreateInstance(objType);
FieldInfo field = obj.GetType().GetField(name);
Type filedType = field.FieldType;
// 对基本类型和泛型区别处理
object valueObj = null;
if (filedType.IsGenericType)
{
Type[] typeParameters = filedType.GetGenericArguments();
Type valueType = Type.GetType(typeParameters[0].FullName);
valueObj = Convert.ChangeType(value, valueType);
}
else
{
valueObj = Convert.ChangeType(value, filedType);
}
field.SetValue(obj, valueObj);
wsp.AddParameter(obj);
}
}
在.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;
}
}
}
_________________________________________________________
最后讨论一下有关DynWSLib动态调用的问题。
使用DynWSLib在调用Web Service服务的时候,需要对传入的参数进行适当的处理。
1、获取所调用的方法的参数类型。
/// <summary>
/// 获取参数类型。该方法只获取第一个参数的类型。
/// </summary>
/// <returns></returns>
private Type GetParameterType()
{
Type t = wsp.Instance.GetType();
MethodInfo methodInfo = t.GetMethod(wsp.MethodName);
// 获得方法的参数类型
ParameterInfo[] param = methodInfo.GetParameters();
if (param.Length < 1)
return null;
// 实例化参数类型
Type objType = param[0].ParameterType;
return objType;
}
2、添加参数到调用方法中。
private DynamicWebServiceProxy wsp = null;
// For SOAP Body Parameters.
private IDictionary paramsTable = new Hashtable();
public void AddParameter(string name, object value)
{
Type objType = GetParameterType();
// 处理字符串类型
if (objType == "".GetType())
{
wsp.AddParameter(value);
}
else // 处理对象类型
{
object obj = Activator.CreateInstance(objType);
FieldInfo field = obj.GetType().GetField(name);
Type filedType = field.FieldType;
// 对基本类型和泛型区别处理
object valueObj = null;
if (filedType.IsGenericType)
{
Type[] typeParameters = filedType.GetGenericArguments();
Type valueType = Type.GetType(typeParameters[0].FullName);
valueObj = Convert.ChangeType(value, valueType);
}
else
{
valueObj = Convert.ChangeType(value, filedType);
}
field.SetValue(obj, valueObj);
wsp.AddParameter(obj);
}
}
相关文章推荐
- 关于.NET中动态调用Web Service服务的方法心得
- .NET动态调用Web Service服务
- .Net下采用GET/POST/SOAP方式动态调用WebService的简易灵活方法(C#)
- 关于struts2.5以后 遇到的几点改变以及动态调用方法问题
- C#动态调用Web服务的3种方法
- 一起谈.NET技术,.NET动态调用DLL的方法
- .Net下采用GET/POST/SOAP方式动态调用WebService的简易灵活方法(C#)
- [转]C# 关于反射类[System.Reflection] 根据类名 动态调用 类方法
- .Net 下采用GET/POST/SOAP方式动态调用WebService的简易灵活方法(C#) [轉]Redfox
- 客户端动态调用WCF服务中的方法
- .Net下采用GET/POST/SOAP方式动态调用WebService的简易灵活方法(C#)
- 从webconfig中动态调用web服务,找到的一个简单方法!!!!
- 关于Struts2 使用! 感叹号 动态调用Action中的方法
- C#动态调用Web服务的3种方法
- 【心得】关于删除结构体动态数组指定项的正确方法
- 动态调用Web Service的方法
- Struts2关于Action的系统训练4关于动态方法调用DMI
- 关于C#下写的Web Service 服务在Delphi下调用时的问题
- .Net下采用GET/POST/SOAP方式动态调用WebService的简易灵活方法(C#)
- 动态调用Web Service的方法