Introduction
I am writing this tip/trick because after a week of research and trial and error, I finally found a solution to enable .NET communication with a Java Web Service.
Background
I was recently tasked with writing a .NET Client for a 3rd party Java web service. I had the following information about the 3rd party web service.
- It communicates with wrapped, document/literal style SOAP messages.
- The location on the server of the WSDL.
Using the code
In Visual Studio 2010 I created an empty Web Application. The auto-generated web.config file contents are pictured below:
="1.0"
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
</configuration>
Next, I added a Service Reference. In the Add Service Reference dialog, I browsed to the location of the WSDL and named my Service Reference. This generated the client proxy for the service and also updated the web.config file. The auto-generated web.config file contents are pictured below:
<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>
I created a simple web form with a button. In the button’s Click event, I wrote the following code:
protected void Button1_Click(object sender, EventArgs e)
{
try
{
ChangeService proxy = new ChangeServiceClient();
getLoginInfo loginInfo = new getLoginInfo();
getLoginInfoRequest loginRequest = new getLoginInfoRequest(loginInfo);
getLoginInfoResponse1 loginResponse;
loginResponse = proxy.getLoginInfo(loginRequest);
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);
}
}
Unfortunately, when I run, I get an exception.
A first chance exception of type 'System.InvalidOperationException
' occurred in System.ServiceModel.dll.
Could not find default endpoint element that references contract 'ThirdPartyServiceReference.ChangeService
' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.
The default auto-generated web.config file does not work. It needs an endpoint address and a proxy address. I modified the web.config file as follows:
<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>
Note the addition of the <client>
section. Also, note the addition of the proxyAddress
in the binding section. Lastly, set useDefaultWebProxy
to false.
Now, a very obscure exception message appears:
A first chance exception of type 'System.ServiceModel.ProtocolException' occurred in System.ServiceModel.dll.
A first chance exception of type 'System.ServiceModel.ProtocolException' occurred in mscorlib.dll.
The content type multipart/related; boundary=MIMEBoundaryurn_uuid_D3E58CD9C1BEF463F71371565723198; type="application/xop+xml"; start="<0.urn:uuid:D3E58CD9C1BEF463F71371565723199@apache.org>"; start-info="text/xml";charset=windows-1252 of the response message does not match the content type of the binding (text/xml; charset=utf-8). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly. The first 1024 bytes of the response were: '--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>
There appears to be a mismatch in the response. I am expecting basicHttpBinding, which is the default. Back to the web.config file. I change <basicHttpBinding>
to <webHttpBinding>
and remove the messageEncoding
and textEncoding
attributes, which are unavailable with the webHttpBinding
element. In addition, I remove the <message>
element from the <security>
element, as it is unavailable. Lastly, I set the binding attribute in <endpoint>
to webHttpBinding
. The updated web.config file appears as follows:
<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>
I am getting closer. The new exception now reads:
A first chance exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.dll
A first chance exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.dll
A first chance exception of type 'System.InvalidOperationException' occurred in mscorlib.dll
Manual addressing is enabled on this factory, so all messages sent must be pre-addressed.
After a quick internet search of the message, I learn that I need to specify an endpoint behavior. I modify the web.config file again. The updated web.config file appears as follows:
<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>
Finally, I am communicating with the web service and I’m getting valid responses back. The output appears as follows:
Database: /ccmdb/fxif
Database: /ccmdb/HPS
Database: /ccmdb/FoxIA
Database: /ccmdb/foxvrtx
Database: /ccmdb/PER
Role: ReportBuilder
Role: Admin
Role: User
History
None.