从 .NET 调用 Java/AXIS Web Service
从基于 .NET 的客户端调用 Java/AXIS Web Service。使用 VS.NET 提供的自动 Web 引用添加可能会导致空 (null) 响应。
引言
好的,我为此挣扎了几个小时;谷歌搜索并没有帮上什么忙——除了在一些论坛中没有得到解答的类似问题的提问。 有时,当你从 .NET 客户端调用基于 AXIS 的 Web Service 时,你会收到一个 null
(在 VB 中为 Nothing
) 响应。 由于我完全不认为自己是第一个遇到这个问题的人,我认为这个解决方案至少会为处理这个问题的人提供一个良好的基础。
背景
问题所在:我的一个合作伙伴在他的机器上部署了一个基于 AXIS 的 Web Service。 由于我当时已经开始了我的 ASP.NET 2.0 项目,我试图从 VB.NET 调用他的模块。 虽然 Visual Studio 成功地读取了 WSDL 并构建了代理类,但我一直收到来自他的 Web 服务的 NULL
响应 (Nothing
)。 然而,他的实现没有任何问题,因为其他类型的 Web 客户端运行顺畅(我甚至试用了这个漂亮的 通用 SOAP 客户端)。 奇怪的是,我没有从 .NET 收到任何异常,该服务似乎正常运行。 并且实际上确实如此。
所以,总而言之:下面的代码(通常是你期望 .NET 客户端调用 WS 的方式)返回了 null
(在 VB 中为 Nothing
)
'***Let's pretend that you have added a web reference
' to a Java-enabled web service called Service1
'***The name of this web reference is AxisService
'***This service contains a web method called doMergeNames,
' receiving two arguments, FName and SName, returning an XML string
Dim WS As New AxisService.Service1
Dim strFullNameXML as String
strFullNameXML=WS.doMergeNames("John","Doe")
嗯,strFullName
总是 Nothing
。 没有抛出错误,只是一个空值。 对于 ASP .NET 1.1 和 2.0,行为完全相同。
使用代码
解决方案:在放置断点并重载一些方法以跟踪响应后,我发现该服务确实返回了正确的字符串,只是 .NET 很难读取它(也许是奇怪的字符?)。
因此,通过创建一个新类来继承自 Service1
并覆盖 GetWebResponse
函数来解决这个问题,以捕获完整的、正确的 SOAP 响应到我的一个变量中,然后手动解析 SOAP 信封。
这是代码
'I recommend you place this in a public module
' so that it is accessible from any part of your project
Imports System.Xml
Imports System.Net
Namespace AxisService
'********that is a TERRIBLE HACK for accessing Java-Web services**************
'for some STUPID reason all I got was null return values
'I had to override the GetWebResponse and parse the SOAP return myself
'*****************************************************************************
Public Class myService1
Inherits AxisService.Service1
Private m_Return As String
Public Property _ResultStr() As String
Get
Return m_Return
End Get
Set(ByVal value As String)
'parse the soap string
'something like the following
'<?xml version="1.0" encoding="utf-8" ?>
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
' <soapenv:Body>
' <dlwmin:doMergeNamesResponse xmlns:dlwmin="http://test.test.com/">
' <return>return string</return>
' </dlwmin:ddoMergeNamesResponse>
' </soapenv:Body>
'</soapenv:Envelope>
Dim tmpXML As New XmlDocument
tmpXML.LoadXml(value)
Dim tmpValueNodeList As XmlNodeList
Dim tmpValueNode As XmlNode
tmpValueNodeList = _
tmpXML.DocumentElement.GetElementsByTagName("soapenv:Body")
If tmpValueNodeList.Count > 0 Then
tmpValueNode = tmpValueNodeList.Item(0)
End If
If Not tmpValueNode Is Nothing Then
Me.m_Return = tmpValueNode.InnerText
Else
Me.m_Return = ""
End If
End Set
End Property
Protected Overloads Overrides Function GetWebResponse(ByVal _
the_webRequest As WebRequest) As WebResponse
Dim WR As WebResponse
WR = MyBase.GetWebResponse(the_webRequest)
Dim sr As New IO.StreamReader(WR.GetResponseStream)
Me._ResultStr = sr.ReadToEnd
Return MyBase.GetWebResponse(the_webRequest)
End Function
End Class
End Namespace
上面的代码将正确的字符串结果存储到 _ResultSt
r 属性中。 然而,由于你在将响应流返回到其余执行之前读取了它,将会抛出一个异常。 这是预期的;因此,为了调用此 Web Service,你将不得不引用新类,捕获异常,并获取 _ResultStr
属性,如下所示
Dim WS As New AxisService.myService1
Dim strFullNameXML as String
'trap the exception due to the stupid hack ***********
Try
WS.doMergeNames("John","Doe")
Catch ex As Exception
'do something here if you want to
'maybe check for the specific exception number,
'I can't remember it :)
End Try
Dim strReturn As String = WS._ResultStr
'*****************************************************
关注点
我知道,这是一个糟糕的 hack,但它快速而肮脏 :)... 另外,我没有时间找出更优雅的解决方案。 也许,一个更简洁的解决方案是覆盖一些其他的 SOAP/.NET 内部函数,以便更正响应解析,而不是重叠它。
历史
- 2007 年 10 月 26 日:首次代码提交。