.NET调用Apache Axis实现的Web Service
最近需要工作需要做一个代收接口,服务端是Java实现的,有认证机制。需要用.NET来调用,SOAP协议并不复杂,但.NET和JAVA实现起来是有区别的,直接用.NET封装的web servvice方法调用是不行的。
在网上找了些资料,已经有人解决了这个问题,就是LongShine营销系统的代收接口。我在了解了基本原理后重新整理了下,完整的代码如下:
public class Service
{
#region 成员变量
/// <summary>
/// 服务地址
/// </summary>
public static string endpoint = Constant.GetParamVale("endpoint");
/// <summary>
/// 服务路径
/// </summary>
public static string path = Constant.GetParamVale("path");
/// <summary>
/// 用户名
/// </summary>
public static string username = Constant.GetParamVale("username");
/// <summary>
/// 密码
/// </summary>
public static string password = Constant.GetParamVale("password");
/// <summary>
/// 服务函数设置
/// </summary>
public static string SoapNode = "invokeService";
/// <summary>
/// xml列表
/// </summary>
private static Hashtable htXML=new Hashtable();
/// <summary>
/// XML名称空间
/// </summary>
public static string XMLNS
{
get
{
if (xmlns == null || xmlns=="")
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(endpoint + "?WSDL");
request.Credentials = CredentialCache.DefaultCredentials;
request.Timeout = 0x2710;
try
{
StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream(), Encoding.UTF8);
XmlDocument document = new XmlDocument();
string temp = reader.ReadToEnd();
document.LoadXml(temp);
return document.SelectSingleNode("//@targetNamespace").Value;
}
catch (WebException exception)
{
xmlns = "";
}
}
return xmlns;
}
}private static string xmlns;
#endregion
#region 创建SOAP的XML文件
#region 示例
/*
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<ns1:username soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" soapenv:mustUnderstand="0" xsi:type="soapenc:string" xmlns:ns1="Authorization" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
jxzx
</ns1:username>
<ns2:password soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" soapenv:mustUnderstand="0" xsi:type="soapenc:string" xmlns:ns2="Authorization" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
1
</ns2:password>
</soapenv:Header>
<soapenv:Body>
<invokeService xmlns="http://tempuri.org/">
<path type="xsd:string">epm/mp/sitechk/service/LocaleCheckResultDownloadService</path>
<methodName type="xsd:string">GET_METER_SITECHK</methodName>
<dataXmlStr type="xsd:string"><?xml version="1.0" encoding="UTF-8" ?><DBSET><R><C N="APP_NO">200810119759</C></R></DBSET></dataXmlStr>
</invokeService>
</soapenv:Body>
</soapenv:Envelope>
*/
#endregion
/// <summary>
/// 创建SOAP的XML文件
/// </summary>
/// <param name="methodName">调用方法名</param>
/// <param name="dataXmlStr">请求XML</param>
/// <param name="xmlns">xml命名空间</param>
/// <returns>返回SOAP格式的XML</returns>
public static XmlDocument CreateSoapXml(string methodName, string dataXmlStr, string xmlns)
{
XmlDocument doc = new XmlDocument();
string xml = "<soapenv:Envelope xmlns:xsi=/"http://www.w3.org/2001/XMLSchema-instance/" xmlns:xsd=/"http://www.w3.org/2001/XMLSchema/" xmlns:soapenv=/"http://schemas.xmlsoap.org/soap/envelope//">"
+ "<soapenv:Header>"
+ "<ns1:username soapenv:actor=/"http://schemas.xmlsoap.org/soap/actor/next/" soapenv:mustUnderstand=/"0/" xsi:type=/"soapenc:string/" xmlns:ns1=/"Authorization/" xmlns:soapenc=/"http://schemas.xmlsoap.org/soap/encoding//">"
+ username
+ "</ns1:username>"
+ "<ns2:password soapenv:actor=/"http://schemas.xmlsoap.org/soap/actor/next/" soapenv:mustUnderstand=/"0/" xsi:type=/"soapenc:string/" xmlns:ns2=/"Authorization/" xmlns:soapenc=/"http://schemas.xmlsoap.org/soap/encoding//">"
+ password
+ "</ns2:password> "
+ "</soapenv:Header>"
+ "</soapenv:Envelope>";
doc.LoadXml(xml);
//添加节点声明
XmlDeclaration xmlDec = doc.CreateXmlDeclaration("1.0", "utf-8", null);
doc.InsertBefore(xmlDec, doc.DocumentElement);
XmlElement body = doc.CreateElement("soapenv", "Body", "http://schemas.xmlsoap.org/soap/envelope/");
XmlElement child = doc.CreateElement(SoapNode);
child.SetAttribute("xmlns", xmlns);
//path
XmlElement subChild = doc.CreateElement("path");
subChild.SetAttribute("xsi:type", "xsd:string");
subChild.InnerText = path;
child.AppendChild(subChild);
//methodName
subChild = doc.CreateElement("methodName");
subChild.SetAttribute("xsi:type", "xsd:string");
subChild.InnerText = methodName;
child.AppendChild(subChild);
//dataXmlStr
subChild = doc.CreateElement("dataXmlStr");
subChild.SetAttribute("xsi:type", "xsd:string");
subChild.InnerText = dataXmlStr;
child.AppendChild(subChild);
body.AppendChild(child);
doc.DocumentElement.AppendChild(body);
return doc;
}
/// <summary>
/// 创建SOAP格式的XML
/// </summary>
/// <param name="xml">存在的XML</param>
/// <param name="dataXmlStr">请求参数数据</param>
/// <returns></returns>
public static XmlDocument CreateSoapXml(string xml,string dataXmlStr)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
XmlNode body = xmlDoc.DocumentElement.SelectSingleNode("soapenv:Body");
XmlNode soap = body.SelectSingleNode("invokeService");
XmlNode data = soap.SelectSingleNode("dataXmlStr");
data.InnerText = dataXmlStr;
return xmlDoc;
}
#endregion
#region 通用WebService调用(Soap)
/// <summary>
/// 通用WebService调用(Soap),参数Pars为String类型的参数名、参数值
/// </summary>
public static XmlDocument WebService(String methodName, string dataXmlStr)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(endpoint);
//HTTP头
request.Method = "POST";
request.ContentType = "text/xml; charset=utf-8";
request.Headers.Add("SOAPAction", "/"" + XMLNS + (XMLNS.EndsWith("/") ? "" : "/") + SoapNode + "/"");
request.Credentials = CredentialCache.DefaultCredentials;
request.Timeout = 0x493E0;
//获取SOAP格式XML
XmlDocument xml = null;
xml = CreateSoapXml(methodName, dataXmlStr, XMLNS);
//发送HTTP请求,获取返回结果
byte[] data=Encoding.UTF8.GetBytes(xml.OuterXml);
XmlDocument responseXml = new XmlDocument();
WriteRequestData(request, data);
try
{
responseXml = ReadXmlResponse(request.GetResponse());
}
catch (WebException exception)
{
throw exception;
}
//处理返回的XML结果
XmlNamespaceManager xnm = new XmlNamespaceManager(responseXml.NameTable);
xnm.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
responseXml.LoadXml("<root>" + responseXml.SelectSingleNode("//soap:Body/*", xnm).InnerXml + "</root>");
//添加节点声明
XmlDeclaration xmlDec = responseXml.CreateXmlDeclaration("1.0", "utf-8", null);
responseXml.InsertBefore(xmlDec, responseXml.DocumentElement);
return responseXml;
}
#endregion
#region 写到流中,发送给服务端
/// <summary>
/// 写到流中,发送给服务端
/// </summary>
/// <param name="request">HttpWebRequest连接对象</param>
/// <param name="data">要写入连接流发给服务端的内容</param>
private static void WriteRequestData(HttpWebRequest request, byte[] data)
{
request.ContentLength = data.Length;
Stream writer = request.GetRequestStream();
writer.Write(data, 0, data.Length);
writer.Close();
}
#endregion
#region 读取服务端返回的结果
/// <summary>
/// 读取服务端返回的结果
/// </summary>
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;
}
#endregion
}
调用方法:
/// <summary>
/// Demo
/// </summary>
public class Demo
{
#region 成员变量
public const string methodName = "Webservice_Function";
//请求变量
/// <summary>
/// 函数参数一
/// </summary>
public string parameter1;
/// <summary>
/// 函数参数二
/// </summary>
public string parameter2;
//返回信息
/// <summary>
/// 返回值一
/// </summary>
public string returnVaule1;
/// <summary>
/// 返回值二
/// </summary>
public string returnValue2;
#endregion
#region 获取请求的XML
/// <summary>
/// 获取请求的XML
/// </summary>
/// <returns></returns>
public string DataXmlStr()
{
string xml = "<?xml version=/"1.0/" encoding=/"UTF-8/"?>"
+ "<DBSET>"
+ "<R>"
+ "<C N=/"parameter1/">" + parameter1+ "</C>"
+ "<C N=/"parameter2">" + parameter2+ "</C>"
+ "</R>"
+ "</DBSET>";
return xml;
}
#endregion
#region 解析返回的XML
/// <summary>
/// 解析返回的XML
/// </summary>
/// <param name="xml"></param>
public bool ReadData(XmlDocument xml)
{
if (xml == null)
{
return false;
}
try
{
XmlNodeList rNodeList = xml.DocumentElement.SelectNodes("R");
if (rNodeList == null || rNodeList.Count < 0)
{
return false;
}
else
{
XmlNodeList cNodeList = rNodeList[0].SelectNodes("C");
if (cNodeList == null)
return false;
else
{
foreach (XmlNode xd in cNodeList)
{
XmlElement xe = (XmlElement)xd;
if (xe.GetAttribute("N") == "returnVaule1")
{
returnVaule1= xe.InnerText;
}
else if (xe.GetAttribute("N") == "returnVaule2")
{
returnVaule2= xe.InnerText;
}
}
}
}
return true;
}
catch (Exception ex)
{
}
return false;
}
#endregion
#region 调用Web Service
/// <summary>
/// 调用Web Service
/// </summary>
public bool InvokeService()
{
XmlDocument xmlDoc = new XmlDocument();
if (!Constant.debug)//测试标志,因无测试环境,暂从本地加载测试,直接环境关掉
{
xmlDoc = Service.WebService(methodName, DataXmlStr());
}
else
{
xmlDoc = new XmlDocument();
xmlDoc.Load(System.AppDomain.CurrentDomain.BaseDirectory + @"/测试数据/2.xml");
}
return ReadData(xmlDoc);
}
#endregion
public string InvokeService(string xml)
{
XmlDocument xmlDoc = Service.WebService(methodName, xml);
return xmlDoc.InnerText;
}
}
整理原有方法只是为了我便于理解,别无他意。因编码过去已经有一个多月了,程序原来的出处我边上没有,就不注明了,一搜索就能找到。
注:问题虽最终解决,但结果仍是失败的,编写的程序并未使用。失败在于原本的技术设计。只想到Web service协议简单通用,却没有想到可行性和目前实现技术的现状,只是想当然了。