using
System;
using
System.Web;
using
System.Xml;
using
System.Collections;
using
System.Net;
using
System.Text;
using
System.IO;
/**/
/// <summary>
/// 利用WebRequest/WebResponse进行WebService调用的类,By 同济黄正
/// </summary>
public
class
WebSvcCaller
{
//<webServices>
// <protocols>
// <add name="HttpGet"/>
// <add name="HttpPost"/>
// </protocols>
//</webServices>
private
static
Hashtable _xmlNamespaces =
new
Hashtable();
//缓存xmlNamespace,避免重复调用GetNamespace
/**/
/// <summary>
/// 需要WebService支持Post调用
/// </summary>
public
static
XmlDocument QueryPostWebService(String URL , String MethodName , Hashtable Pars)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL +
"/"
+ MethodName);
request.Method =
"POST"
;
request.ContentType =
"application/x-www-form-urlencoded"
;
SetWebRequest(request);
byte
[] data = EncodePars(Pars);
WriteRequestData(request , data);
return
ReadXmlResponse(request.GetResponse());
}
/**/
/// <summary>
/// 需要WebService支持Get调用
/// </summary>
public
static
XmlDocument QueryGetWebService(String URL , String MethodName , Hashtable Pars)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL +
"/"
+ MethodName +
"?"
+ ParsToString(Pars));
request.Method =
"GET"
;
request.ContentType =
"application/x-www-form-urlencoded"
;
SetWebRequest(request);
return
ReadXmlResponse(request.GetResponse());
}
/**/
/// <summary>
/// 通用WebService调用(Soap),参数Pars为String类型的参数名、参数值
/// </summary>
public
static
XmlDocument QuerySoapWebService(String URL , String MethodName , Hashtable Pars)
{
//By 同济黄正 http://hz932.ys168.com 2008-3-19
if
(_xmlNamespaces.ContainsKey(URL))
{
return
QuerySoapWebService(URL , MethodName , Pars , _xmlNamespaces[URL].ToString());
}
else
{
return
QuerySoapWebService(URL , MethodName , Pars ,GetNamespace(URL));
}
}
private
static
XmlDocument QuerySoapWebService(String URL , String MethodName , Hashtable Pars ,
string
XmlNs)
{
_xmlNamespaces[URL] = XmlNs;
//加入缓存,提高效率
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL);
request.Method =
"POST"
;
request.ContentType =
"text/xml; charset=utf-8"
;
request.Headers.Add(
"SOAPAction"
,
""
" + XmlNs + (XmlNs.EndsWith("
/
") ? "
" : "
/
") + MethodName + "
""
);
SetWebRequest(request);
byte
[] data = EncodeParsToSoap(Pars , XmlNs , MethodName);
WriteRequestData(request , data);
XmlDocument doc =
new
XmlDocument() , doc2 =
new
XmlDocument();
doc = ReadXmlResponse(request.GetResponse());
XmlNamespaceManager mgr =
new
XmlNamespaceManager(doc.NameTable);
String RetXml = doc.SelectSingleNode(
"//soap:Body/*"
, mgr).InnerXml;
doc2.LoadXml(
"<root>"
+ RetXml +
"</root>"
);
AddDelaration(doc2);
return
doc2;
}
private
static
string
GetNamespace(String URL)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL +
"?WSDL"
);
SetWebRequest(request);
WebResponse response = request.GetResponse();
StreamReader sr =
new
StreamReader(response.GetResponseStream() , Encoding.UTF8);
XmlDocument doc =
new
XmlDocument();
doc.LoadXml(sr.ReadToEnd());
return
doc.SelectSingleNode(
"//@targetNamespace"
).Value;
}
private
static
byte
[] EncodeParsToSoap(Hashtable Pars , String XmlNs , String MethodName)
{
XmlDocument doc =
new
XmlDocument();
doc.LoadXml(
"<soap:Envelope xmlns:xsi="
http:
//www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"></soap:Envelope>");
AddDelaration(doc);
XmlElement soapBody = doc.CreateElement(
"soap"
,
"Body"
,
"http://schemas.xmlsoap.org/soap/envelope/"
);
XmlElement soapMethod = doc.CreateElement(MethodName);
soapMethod.SetAttribute(
"xmlns"
, XmlNs);
foreach
(
string
k
in
Pars.Keys)
{
XmlElement soapPar = doc.CreateElement(k);
soapPar.InnerText = Pars[k].ToString();
soapMethod.AppendChild(soapPar);
}
soapBody.AppendChild(soapMethod);
doc.DocumentElement.AppendChild(soapBody);
return
Encoding.UTF8.GetBytes(doc.OuterXml);
}
private
static
void
SetWebRequest(HttpWebRequest request)
{
request.Credentials = CredentialCache.DefaultCredentials;
request.Timeout = 10000;
}
private
static
void
WriteRequestData(HttpWebRequest request ,
byte
[] data)
{
request.ContentLength = data.Length;
Stream writer = request.GetRequestStream();
writer.Write(data , 0 , data.Length);
writer.Close();
}
private
static
byte
[] EncodePars(Hashtable Pars)
{
return
Encoding.UTF8.GetBytes(ParsToString(Pars));
}
private
static
String ParsToString(Hashtable Pars)
{
StringBuilder sb =
new
StringBuilder();
foreach
(
string
k
in
Pars.Keys)
{
if
(sb.Length > 0)
{
sb.Append(
"&"
);
}
sb.Append(HttpUtility.UrlEncode(k) +
"="
+ HttpUtility.UrlEncode(Pars[k].ToString()));
}
return
sb.ToString();
}
private
static
XmlDocument ReadXmlResponse(WebResponse response)
{
StreamReader sr =
new
StreamReader(response.GetResponseStream() , Encoding.UTF8);
String retXml = sr.ReadToEnd();
sr.Close();
XmlDocument doc =
new
XmlDocument();
doc.LoadXml(retXml);
return
doc;
}
private
static
void
AddDelaration(XmlDocument doc)
{
XmlDeclaration decl = doc.CreateXmlDeclaration(
"1.0"
,
"utf-8"
,
null
);
doc.InsertBefore(decl , doc.DocumentElement);
}
}
这个类有三个公用的方法:QuerySoapWebService为通用的采用Soap方式调用WebService,QueryGetWebService采用GET方式调用,QueryPostWebService采用POST方式调用,后两个方法需要WebService服务器支持相应的调用方式。三个方法的参数和返回值相同:URL为Webservice的Url地址(以.asmx结尾的);MethodName为要调用的方法名称;Pars为参数表,它的Key为参数名称,Value为要传递的参数的值。注意方法名称、参数名称、参数个数必须完全匹配才能正确调用。第一次以Soap方式调用时,因为需要查询WSDL获取xmlns,因此需要时间相对长些,第二次调用不用再读WSDL,直接从缓存读取。这三个方法的返回值均为XmlDocument对象,这个返回的对象可以进行各种灵活的操作。最常用的一个SelectSingleNode方法,可以让你一步定位到Xml的任何节点,再读取它的文本或属性。也可以直接调用Save保存到磁盘。采用Soap方式调用时,根结点名称固定为root。 这个类主要是利用了WebRequest/WebResponse来完成各种网络查询操作。为了精简明了,这个类中没有添加错误处理,需要在调用的地方设置异常捕获。 下面是一个调用实例:
protected
void
Page_Load(
object
sender , EventArgs e)
{
try
{
Hashtable pars =
new
Hashtable();
pars[
"city"
] =
"上海"
;
pars[
"wdate"
]=
"2008-3-19"
;
XmlDocument doc = WebSvcCaller.QuerySoapWebService(Url ,
"GetWeather"
, pars);
Response.Write(doc.OuterXml);
}
catch
(Exception ex)
{
Response.Write(ex.Message);
}
}