.NET调用JAVA的WebService方法

原文:https://www.cnblogs.com/fengyao/archive/2010/06/14/1749383.html

调用WebService,最简单的办法当然是直接添加WEB引用,然后自动产生代理类,但是在调用JAVA的WebService时并没有这么简单,特别是对于SoapHeader的处理,在网上也有相关资料,但是都整理的不够清晰明了。根据网上的资料,个人也对各种方法进行了尝试,费了不少精力,为此特将自己的解决方法进行总结一下,以备以后需要以及相关朋友参考。

先说说的思路:

1、先用soapUI进行测试,这个工具会自动生成调用某个方法的XML。

2、把soapUI生成的XML作为模版,自己也生成一个一模一样的XML并为参数节点赋好值。

3、将这个XML通过http直接发送给WebService。

4、接收返回的XML进行处理。

这样做最大的好处就是可以自己很轻松的控制XML格式,最开始的时候我是通过添加引用的方式去调用某个方法一直失败,但是用soapUI去测试这个方法又是可以成功调用的,折腾了半天,最后通过抓包的方式对发送的数据进行对比,发现两者发送的XML相差甚远,好了废话不说了,就拿一个小实例来演示这个过程吧。

首先,通过soapUI工具测试调用WebService里一个名为getPopCheckedInfo的方法,生成的XML如下:

soapUI生成的XML

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.pop.wsif.cogent.com/">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-2" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>用户名</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">密码</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">qTW5ajMAEp4o9BiSvcczNA==</wsse:Nonce>
<wsu:Created>2010-05-24T07:02:10.531Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<ws:getPopCheckedInfo>
<arg0>参数</arg0>
</ws:getPopCheckedInfo>
</soapenv:Body>
</soapenv:Envelope>

上面三个用汉字标示的地方就是我们要修改赋值的地方,大家看到了吧,如果用添加引用自动生成代理类的方式,要产生这样格式的XML有多难控制了吧,但是如果全部用代码来生成也不是一件容易的事,个人用了一个比较巧妙的办法:

在项目中添加一个名为“getPopCheckedInfo”的xml文件,将上面的XML粘贴上去,然后再将这个XML文件作为内嵌资源(在这个的文件属性里面的‘生产操作’选择‘嵌入的资源’),使用的时候直接加载这个XML文件,然后修改那3个节点的值就可以了(用户名和密码一般都预先确定的,也可以直接写在XML文件里,调用的时候就只要对那一个参数赋值了)。使用内嵌资源是为了不让外面看到我们的那个XML文件,以防被修改了什么的。

下面看看调用的代码实现吧:(为了理解方便清晰,我们用跟WebService上一模一样的方法名和参数)

/// <summary>
        /// 根据居民id获取该居民信息
        /// </summary>
        /// <param name="id">居民id</param>
        public static People getPopCheckedInfo(string id)
        {
            String ServerUrl = Config.GetWebServerURL();//得到WebServer地址
            Hashtable pars = new Hashtable();//用来存放参数
            pars["arg0"] = id;
            XmlDocument xml = WebSvcCaller.QuerySoapWebService(ServerUrl, "getPopCheckedInfo", pars);
            //这个是对返回的XML文件处理,我删掉了,处理完后返回一个居民的实体对象
            return myPeople;
        }

 WebSvcCaller.QuerySoapWebService方法代码:

/// <summary>
        /// 通用WebService调用(Soap),参数Pars为String类型的参数名、参数值
        /// </summary>
        public static XmlDocument QuerySoapWebService(String URL, String MethodName, Hashtable Pars)
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL);
            request.Method = "POST";
            request.Accept = @"gzip,deflate";
            request.ContentType = @"text/xml;charset=utf-8";
            request.UserAgent = @"Jakarta Commons-HttpClient/3.1";
            request.Credentials = CredentialCache.DefaultCredentials;
            request.Timeout = 10000;
            byte[] data = EncodeParsToSoap(Pars, MethodName);
            WriteRequestData(request, data);//将处理成字节组的XML写到流中发送到服务端
            XmlDocument doc = new XmlDocument();
            doc = ReadXmlResponse(request.GetResponse());//读取服务端返回的结果
            return doc;
        }

EncodeParsToSoap(Pars, MethodName),处理XML文件方法的代码:(以下仅供参考,大家根据自己的实际情况变动)

处理XML文件方法的代码

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> /// <summary>
/// 处理要发送的XML文档
/// </summary>
/// <param name="Pars">参数</param>
/// <param name="MethodName">方法名</param>
private static byte[] EncodeParsToSoap(Hashtable Pars, String MethodName)
{
XmlDocument xml = null;
if (hshtableXML.ContainsKey(MethodName))
{//如果已经加载过,则从缓存中读取
xml = (XmlDocument)hshtableXML[MethodName];
}
else
{//如果还未加载则进行加载,并放入缓存

//从资源文件得到文件流
Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("你的项目的名称.XML文件存放的文件夹." + MethodName + ".xml");
xml = new XmlDocument();
xml.Load(stream);
hshtableXML.Add(MethodName, xml);
}

//修改参数的值
foreach (DictionaryEntry de in Pars)
{
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable);
nsmgr.AddNamespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
nsmgr.AddNamespace("ws", "http://ws.pop.wsif.cogent.com/");
Hashtable subpars = de.Value as Hashtable;
if (subpars == null)
{
string subNode = "soapenv:Envelope/soapenv:Body/ws:" + MethodName + "/" + de.Key.ToString();
XmlNode node = xml.SelectSingleNode(subNode, nsmgr);
node.InnerText = de.Value.ToString();
}
else
{
foreach (DictionaryEntry subde in subpars)
{
string subNode = "soapenv:Envelope/soapenv:Body/ws:" + MethodName + "/" + de.Key.ToString() + "/" + subde.Key.ToString();
XmlNode node = xml.SelectSingleNode(subNode, nsmgr);
node.InnerText = subde.Value.ToString();
}
}

}

//将修改后的XML文件保存到流中
//这样做还可以保证发送的XML文件也是格式化的那种形式,而不是一整行
//如通过OuterXml获取的就是一整行,这样也可能会导致服务端解析失败,个人这次就碰到这种情况了
MemoryStream outStream = new MemoryStream();
xml.Save(outStream);

byte[] buffer = new byte[outStream.Length];
byte[] temp = outStream.GetBuffer();
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = temp[i];
}
outStream.Close();

return buffer;
}

最后还有WriteRequestData、ReadXmlResponse两个方法的代码:

/// <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();
        }

/// <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;
        }

参考文章:

1、.Net下采用GET/POST/SOAP方式动态调用WebService的简易灵活实现(C#)

分类: WebService

原文地址:https://www.cnblogs.com/zhyp/p/12242484.html

时间: 2024-10-02 22:32:08

.NET调用JAVA的WebService方法的相关文章

Delphi调用JAVA的WebService上传XML文件(XE10.2+WIN764)

相关资料:1.http://blog.csdn.net/luojianfeng/article/details/512198902.http://blog.csdn.net/avsuper/article/details/8764165 注意事项: 1.生成WSDL文件时,D7可能有的无法生成,用XE版本可以全部生成. 返回字节流: 1 function GetByte(AString: string): TByteDynArray; 2 var 3 sByte: TByteDynArray;

delphi调用 java 的 WebService服务端.

// InvRegistry.RegisterInvokeOptions(TypeInfo(ModelADServicePortType), ioLiteral); InvRegistry.RegisterInvokeOptions(TypeInfo(ModelADServicePortType), ioDocument); delphi调用 java 的 WebService服务端.,布布扣,bubuko.com

世界上最恶心的调用方法:Delphi调用Java的class方法法

世界上最恶心的调用方法是,:用Delphi调用Java的class方法: 如果写了一个java方法: package com.api; public class DelphiCallJava { public static String dTest(String args,int args2,String args3){ if(args==null){ return "您沒有輸入參數."; }else { return "您輸入的參數是:"+args; } } }

C#调用Java的WebService出现500 服务器错误

最近在用C#调用Java写的WebService时,发现老是返回500 服务器错误,到底什么原因一直找不出来, 后来google了以后,找到国外的http://stackoverflow.com站点已经有人碰到过这个问题了. 转帖如下: HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest; WebResponse wr = req.GetResponse(); When the server returns 500 Inte

.Net调用Java的实现方法

一. IKVM 1.1下载配置IKVM 1.1.1. 下载路径 http://www.ikvm.net/index.html 1.1.2. 设置路径 解压ikvm-0.42.0.3.zip,并将%IKVM_HOME%/bin添加到path中.此处的%IKVM_HOME%是指解压后ikvm的主目录. 1.2第一种方式:直接将.class文件转化成.dll 网站介绍 http://www.codeproject.com/Articles/13549/Using-Java-Classes-in-you

PHP调用JAVA的WebService简单实例

使用PHP调用JAVA语言开发的WebService.客户端提交两个String类型的参数,服务端返回一个对象类型.服务端使用AXIS-1.4作为SOAP引擎.客户端为PHP5.2.9,使用NuSOAP作为SOAP引擎. 服务端: 对象类 import java.io.Serializable; public class Person implements Serializable { /** * */ private static final long serialVersionUID = -

C#实现调用Java类中方法

基本思路: 用C#实现调用Java编写的类中的方法:重点是将Java编写的程序打包成Jar,然后使用开源工具IKVM将其转化成DLL控件,在.NET环境下调用. 分为以下步骤: 1.下载JDK6(注:JDK7下可能不支持,建议使用JDK6和Eclipse),进行安装,然后配置环境变量Path,将JDK安装的路径(例如:D:\Program Files\Java\jdk1.6.0_10\bin)添加到Path变量后面,如图所示: 用cmd打开DOS框,输入javac就可以查看是否配置成功,配置成功

delphi xe6 调用java GPS的方法

如果用xe6自带的LocationSensor控件,默认优先使用网络位置,网络位置定位精度不准确,不能满足高精度定位的要求.但xe6自带的LocationSensor控件不能指定网络定位优先还是GPS定位优先,如果调用java API是可以指定优先使用GPS定位,以下代码经实测证实是可以直接指定GPS定位的. uses Androidapi.JNI.Location, Androidapi.JNIBridge, Androidapi.JNI.JavaTypes, Androidapi.JNI.O

C#调用Java的WebService时添加身法认证信息的方法

Java生成的WebService要求在调用时在http的header里必须带上Authorization:Basic xxxxxxxxxxxxxxx的认证信息 因为是在添加Web Reference后直接调用服务,所以就要重写服务类,重写服务类的GetWebRequest方法,示例代码如下 public class MyService : xxx服务类 { public MyService(string url) { Url = url; } protected override WebReq