使用 .NET 客户端消费 Java Web 服务






4.89/5 (5投票s)
使用 .NET 客户端消费 Java Web 服务
引言
我写这个技巧是因为经过一周的研究和反复试验,我终于找到了一个解决方案,使 .NET 可以与 Java Web 服务进行通信。
背景
最近,我被要求为一个第三方的 Java Web 服务编写一个 .NET 客户端。我有关于第三方 Web 服务的以下信息。
- 它使用封装的文档/文字样式 SOAP 消息进行通信。
- WSDL 在服务器上的位置。
使用代码
在 Visual Studio 2010 中,我创建了一个空的 Web 应用程序。 自动生成的 web.config 文件的内容如下图所示
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
</configuration>
接下来,我添加了一个服务引用。 在“添加服务引用”对话框中,我浏览到 WSDL 的位置并命名我的服务引用。 这生成了服务的客户端代理,并且还更新了 web.config 文件。 自动生成的 web.config 文件的内容如下图所示
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="ChangeServiceHttpBinding" closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false"
hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288"
maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8"
transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32"
maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
我创建了一个带有按钮的简单 Web 窗体。 在按钮的 Click 事件中,我编写了以下代码
protected void Button1_Click(object sender, EventArgs e)
{
try
{
// This is the client proxy
ChangeService proxy = new ChangeServiceClient();
// Based on all of the examples I saw, I thought I would be able to
// call the methods directly, such as proxy.getLoginInfo(),
// proxy.LogIn(), etc. But, that is not how it works in this example.
// I will need to create the Request and Response Objects
// This object will contain the login info: roles, databases, etc.
getLoginInfo loginInfo = new getLoginInfo();
// This request object contains the loginInfo object
getLoginInfoRequest loginRequest = new getLoginInfoRequest(loginInfo);
// This response object will contain the loginInfo object populated
// with roles, databases, etc.
getLoginInfoResponse1 loginResponse;
// Send the request
loginResponse = proxy.getLoginInfo(loginRequest);
// Get the loginInfo data from the response
getLoginInfoResponse response;
response = loginResponse.getLoginInfoResponse;
foreach (DatabaseInfo db in response.loginInfo.databases)
{
Debug.WriteLine("Database: " + db.name);
}
foreach (string role in response.loginInfo.loginRoles)
{
Debug.WriteLine("Role: " + role);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message + "\n" + ex.InnerException);
}
}
不幸的是,当我运行时,我得到一个异常。
类型为“System.InvalidOperationException
”的首次机会异常发生在System.ServiceModel.dll中。
在 ServiceModel 客户端配置节中找不到引用合约“ThirdPartyServiceReference.ChangeService
”的默认终结点元素。 这可能是因为未找到应用程序的任何配置文件,或者因为在客户端元素中找不到与此合约匹配的终结点元素。
默认的自动生成的 web.config 文件不起作用。 它需要一个终结点地址和一个代理地址。 我修改了 web.config 文件,如下所示
<system.serviceModel>
<client>
<endpoint name="ThirdPartyClient"
contract="ThirdPartyServiceReference.ChangeService"
address="http://sol8srv:8600/cs/webservices/ChangeService/"
binding="basicHttpBinding"
bindingConfiguration="ChangeServiceHttpBinding">
</endpoint>
</client>
<bindings>
<basicHttpBinding>
<binding name="ChangeServiceHttpBinding" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00"
sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false"
hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288"
maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8"
transferMode="Buffered"
useDefaultWebProxy="false"
proxyAddress="http://sol8srv:8600/cs/">
<readerQuotas maxDepth="32"
maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
请注意添加了 <client>
节。 另请注意在绑定节中添加了 proxyAddress
。 最后,将 useDefaultWebProxy
设置为 false。
现在,出现了一个非常模糊的异常消息
类型为“System.ServiceModel.ProtocolException”的首次机会异常发生在System.ServiceModel.dll中。
类型为“System.ServiceModel.ProtocolException”的首次机会异常发生在mscorlib.dll中。
响应消息的内容类型 multipart/related; boundary=MIMEBoundaryurn_uuid_D3E58CD9C1BEF463F71371565723198; type="application/xop+xml"; start="<0.urn:uuid:D3E58CD9C1BEF463F71371565723199@apache.org>"; start-info="text/xml";charset=windows-1252 与绑定的内容类型 (text/xml; charset=utf-8) 不匹配。 如果使用自定义编码器,请确保正确实现了 IsContentTypeSupported 方法。 响应的前 1024 个字节是:'--MIMEBoundaryurn_uuid_D3E58CD9C1BEF463F71371565723198
Content-Type: application/xop+xml; charset=utf-8; type="text/xml"
Content-Transfer-Encoding: binary
Content-ID: <0.urn:uuid:D3E58CD9C1BEF463F71371565723199@apache.org>
响应中似乎存在不匹配。 我期望 basicHttpBinding,这是默认设置。 回到 web.config 文件。 我将 <basicHttpBinding>
更改为 <webHttpBinding>
并删除 messageEncoding
和 textEncoding
属性,这些属性在 webHttpBinding
元素中不可用。 此外,我从 <security>
元素中删除 <message>
元素,因为它不可用。 最后,我将 <endpoint>
中的 binding 属性设置为 webHttpBinding
。 更新后的 web.config 文件如下所示
<system.serviceModel>
<client>
<endpoint name="ThirdPartyClient"
contract="ThirdPartyServiceReference.ChangeService"
address="http://sol8srv:8600/cs/webservices/ChangeService/"
binding="webHttpBinding" bindingConfiguration="ChangeServiceHttpBinding">
</endpoint>
</client>
<bindings>
<webHttpBinding>
<binding name="ChangeServiceHttpBinding" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false"
hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288"
maxReceivedMessageSize="65536"
transferMode="Buffered"
useDefaultWebProxy="false" proxyAddress="http://sol8srv:8600/cs/">
<readerQuotas maxDepth="32"
maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
</security>
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>
我越来越接近了。 新的异常现在显示
类型为“System.InvalidOperationException”的首次机会异常发生在 System.ServiceModel.dll 中
类型为“System.InvalidOperationException”的首次机会异常发生在 System.ServiceModel.dll 中
类型为“System.InvalidOperationException”的首次机会异常发生在 mscorlib.dll 中
在此工厂上启用了手动寻址,因此发送的所有消息都必须预先寻址。
在快速搜索 Internet 上的消息后,我知道我需要指定一个终结点行为。 我再次修改了 web.config 文件。 更新后的 web.config 文件如下所示
<system.serviceModel>
<client>
<endpoint name="ThirdPartyClient"
contract="ThirdPartyServiceReference.ChangeService"
address="http://sol8srv:8600/cs/webservices/ChangeService/"
binding="webHttpBinding" bindingConfiguration="ChangeServiceHttpBinding"
behaviorConfiguration="webHttpBehavior">
</endpoint>
</client>
<bindings>
<webHttpBinding>
<binding name="ChangeServiceHttpBinding" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00"
sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false"
hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288"
maxReceivedMessageSize="65536"
transferMode="Buffered"
useDefaultWebProxy="false"
proxyAddress="http://sol8srv:8600/cs/">
<readerQuotas maxDepth="32"
maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
</security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="webHttpBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
最后,我正在与 Web 服务通信,并且正在获得有效的响应。 输出如下所示
Database: /ccmdb/fxif
Database: /ccmdb/HPS
Database: /ccmdb/FoxIA
Database: /ccmdb/foxvrtx
Database: /ccmdb/PER
Role: ReportBuilder
Role: Admin
Role: User
历史
无。