65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (5投票s)

2013 年 6 月 18 日

CPOL

3分钟阅读

viewsIcon

62692

使用 .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> 并删除 messageEncodingtextEncoding 属性,这些属性在 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 

历史

无。

© . All rights reserved.