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

先说说的思路:

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

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

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

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

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

首先,通过soapUI工具测试调用WebService里公用的WebSercie(http://www.webxml.com.cn/WebServices/WeatherWebService.asmx)中的一个名为getSupportCity的方法,生成的XML如下:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://WebXml.com.cn/">
<soapenv:Header/>
<soapenv:Body>
<web:getSupportCity>
<!--Optional:-->
<web:byProvinceName>北京</web:byProvinceName>
</web:getSupportCity>
</soapenv:Body>
</soapenv:Envelope>

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

在项目中添加一个名为“getSupportCity”的xml文件,将上面的XML粘贴上去,然后再将这个XML文件作为内嵌资源(在这个的文件属性里面的‘生产操作’选择‘嵌入的资源’),使用的时候直接加载这个XML文件,然后按逻辑处理需要修改的地方(其实就是XML文档操作)。使用内嵌资源是为了不让外面看到我们的那个XML文件,以防被修改了什么的。

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

   /// <summary>
/// 天气预报
/// </summary>
/// <param name="id">居民id</param>
public static void getPopCheckedInfo()
{
String ServerUrl = "http://www.webxml.com.cn/WebServices/WeatherWebService.asmx";//得到WebServer地址
Hashtable pars = new Hashtable();//用来存放参数
pars["byProvinceName"] = "北京";
XmlDocument xml = QuerySoapWebService(ServerUrl, "getSupportCity", pars);
//这个是对返回的XML文件处理,我删掉了,处理完后返回一个居民的实体对象
}

 WebSvcCaller.QuerySoapWebService方法代码:

  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 = ;
byte[] data = EncodeParsToSoap(Pars, MethodName);
WriteRequestData(request, data);//将处理成字节组的XML写到流中发送到服务端
XmlDocument doc = new XmlDocument();
doc = ReadXmlResponse(request.GetResponse());//读取服务端返回的结果
return doc;
}

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

 private static Hashtable hshtableXML = new Hashtable();
/// <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("异步调用.file." + 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("web", "http://WebXml.com.cn/");
Hashtable subpars = de.Value as Hashtable;
if (subpars == null)
{
string subNode = "soapenv:Envelope/soapenv:Body/web:" + MethodName + "/web:" + 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 = ; 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, , 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;
}

注:在实际开发过程中,如果服务器不是标准的WebService,那么返回的数据格式不一定是XML,可能是很难解析的字符串,

出现这种情况解决办法,

第一,让服务器修改接口,返回标准XML格式;

第二:按字符串硬处理

示例下载

参考文档

http://www.cnblogs.com/fengyao/archive/2010/06/14/1749383.html

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

  1. delphi7编写客户端调用java服务器端webservice示例

    1. 首先取得java-webservice服务器端地址.我的是:http://localhost:8080/mywebservice/services/mywebservice?wsdl 2. 然后 ...

  2. C#调用Java的WebService添加SOAPHeader验证(2)

    C#调用Java的WebService添加SOAPHeader验证 上一篇链接如上,更像是 Net下采用GET/POST/SOAP方式动态调用WebService的简易灵活方法(C#) 来处理xml, ...

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

    相关资料:1.http://blog.csdn.net/luojianfeng/article/details/512198902.http://blog.csdn.net/avsuper/artic ...

  4. oracle调用JAVA类的方法

    导入jar包 在oracle中导入需要的jar包,我们把编辑好的java类打成jar包,直接在oarcle里面写简单的调用就可以了,  1.操作系统需要拥有支持loadjava命令的jdk.  2.加 ...

  5. Delphi动态调用Java的WebService 转

    Delphi动态调用Java的WebService —— 基于“Axis2发布WebService例子(HelloWorld)” uses ComObj; var WsObject: Variant; ...

  6. C#调用Java的WebService添加SOAPHeader验证

    C#调用Java的WebService添加SOAPHeader验证(2) 1.问题描述 调用的Java的webservice string Invoke(string func, string req ...

  7. 如何在Mybatis的xml文件调用java类的方法

    在mybatis的映射xml文件调用java类的方法:使用的是OGNL表达式,表达式格式为:${@prefix@methodName(传递参数名称)} 1.如下代码所示:方法必须为静态方法:以下我只是 ...

  8. c#调用JAVA的Webservice处理XML数据及批量轮询的实现方法

    前段时间做一个调用外单位WEBSERVICE的项目,项目完成的功能其实很简单,就是我们单位有很多车友会员,我们想对他们提供车辆违章信息告之服务!我们这边交警部门给我们开放了WS的接口,我们就是想通过这 ...

  9. .Net调用Java的实现方法

    一. IKVM 1.1下载配置IKVM 1.1.1. 下载路径 http://www.ikvm.net/index.html 1.1.2. 设置路径 解压ikvm-0.42.0.3.zip,并将%IK ...

随机推荐

  1. Cocos2dx 3.6源代码编译错误:syntax error : missing &#39;)&#39; before &#39;{&#39;

    在编译Cocos2dx 3.6版本号时.发现编译错误: 定位代码行: debugForNormalSprite->drawPoints(positions, 4, 8, Color4F{0.0, ...

  2. Ubuntu——修正LibreOffice中文乱码以及eclipse提示框颜色

    刚进ubuntu的时候就老遇到用libreoffice打开某些文档时出现一堆叠在一起的乱码.以及最開始使用eclipse编辑时,鼠标放到一个变量或者函数时 弹出来一黑框框-看的难受的.... 这里记录 ...

  3. Centos6.2上做nginx和tomcat的集成及负载均衡(已实践)

    Centos6.2上做nginx和tomcat的集成及负载均衡 ---------------------------------------------------------Jdk-------- ...

  4. LDAP简介及LDAP服务器的安装与配置

    一.LDAP简介 全称:Lightweight Directory Access Protocol,目录服务是一种特殊的数据库系统,其专门针对读取. LDAP目录中的信息是按照树型结构组织,具体信息存 ...

  5. NSDate相差8小时

     NSDate *date = [NSDate date]; NSTimeZone *zone = [NSTimeZone systemTimeZone]; NSInteger interval = ...

  6. 光栅化规则(Rasterization Rules)

    光栅化规则不是唯一的,只要能满足在扫描线填充过程中,对于一条分割线两边的像素能够被不重复不遗漏地填充即可. 在gdi3d中目前使用的是下面光栅化规则: xLeft_int=ceil(xLeft-0.5 ...

  7. Atitit.数据库分区的设计 attilax  总结

    Atitit.数据库分区的设计 attilax  总结 1. 分区就是分门别类的文件夹 (what)1 2. 分区的好处(y)1 3. 分区原则(要不要分区,何时分区)how2 4. 主要的分表类型有 ...

  8. 使用apxs安装apache模块

    使用apxs安装apache模块                 ---by石锅拌饭 1.缘由 前几天迁移系统.发现配置了fastcgi的一个脚本下载文件总是提示类似Connection reset ...

  9. Android 第三方应用广告拦截实现

    前段时间,公司制造的机器里应用装有不良广告,严重影响了儿童客户使用者的思想健康.导致被人投诉. 于是乎.就有了想研发一款相似于360广告屏蔽的应用的念头.嗯.事情就是这样.如今切入主题. 眼下市场上有 ...

  10. socket编程之实现简单的ssh

    服务器代码: #-*- coding:utf-8 -*- #edited by python3.6 # import socket,os ''' 创建socket对象 ''' server = soc ...