WCF client->J2EE server - using GZip


Lars Hulvej

Hi all, sorry for the long post. However I just spend quite some time trying
to figure out how to do this, so I thought I would share the result.

I wanted to use a WCF (3.5) client to call a J2EE web service and having the
request and response compressed using gzip. I couldn't find an example that
really worked, but ended up using one of Microsoft's samples and changing it

This is really my first few days playing with WCF, so there might an easier
way - if there is I would love to know what it is.

Below is how I did it.

1) Go to this page:
http://msdn2.microsoft.com/en-us/library/ms751458(VS.90).aspx. The page
demonstrates how to use a custom message encoder.

2) Download the sample pack mentioned on the page from here:

3) Extract all files to a location on your harddrive.

4) While the files extract, create a new project in Visual Studio 2008 and
add a service reference to your web service (I’m calling a J2EE web service,
but it shouldn’t really matter). Leave all settings at the default values.

5) In Explorer go to (where you put the extracted sample pack)

6) Copy the GZIPEncoder project to your solution folder created in step 4

7) Add the GZIPEncoder project to your solution. Click Finish and then Close
in the upgrade wizard that pops up. Add a project reference to GZIPEncoder to
your own project.

8) Add a method that will call your service (for simplicity I use a
button_click event).

9) Add these Using statements:
using System.ServiceModel;
using System.ServiceModel.Channels;
using Microsoft.ServiceModel.Samples;
using System.Net;
using (reference to your service);

10) In the method create a CustomBinding and set it up to use the
ICollection<BindingElement> bindingElements = new List<BindingElement>();
HttpTransportBindingElement httpBindingElement = new
httpBindingElement.AuthenticationScheme = AuthenticationSchemes.Basic;

GZipMessageEncodingBindingElement compBindingElement = new

CustomBinding myBinding = new CustomBinding(bindingElements);
myBinding.Name = "SampleBinding";
myBinding.Namespace = "http://tempuri.org/bindings";

11) (optional): Change AuthenticationScheme to whatever you need.

12) Create a new endpoint setting it to the right URL for your web service.
Also create a new instance of your service (called MyClient below – change to
match whatever name you have):
EndpointAddress ea = new EndpointAddress("");

MyClient executer = new MyClient(myBinding, ea);

13) (optional): Set user name/password for access to your web service if
executer.ClientCredentials.UserName.UserName = "xxx";
executer.ClientCredentials.UserName.Password = "yyy";

14) We now need to add HTTP headers to tell the server that we will compress
our requests and require responses returned compressed:
HttpRequestMessageProperty httpRequestProperty = new
httpRequestProperty.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip");
httpRequestProperty.Headers.Add(HttpRequestHeader.ContentEncoding, "gzip");

15) There might an easier way to inject the headers into your message, but
this is the way I’m using:
using (OperationContextScope scope = new
[HttpRequestMessageProperty.Name] = httpRequestProperty;

executer.BeginSession("some string");

16) Replace executer.BeginSession(xxx) with a valid method for your web
service, e.g executer.AddNumbers or whatever.

17) We still need to change a few things in the GZipEncoder, but let’s try
to run it and see what happens. We get a nice exception:
The content type text/xml;charset=utf-8 of the response message does not
match the content type of the binding (application/x-gzip)

18) Looking at a Wireshark trace, we can see that the content type is not
text/xml, but: Content-Type: application/x-gzip.

19) Go to GZIPMessageEncoderFactory.cs and find these lines:
class GZipMessageEncoder : MessageEncoder
static string GZipContentType = "application/x-gzip";

20) Change the GZIPContentType to look like this:
static string GZipContentType = "text/xml";

21) Run it again. Your mileage might vary, but I now received an error about
SOAP version. You can change the SOAP version used from the default by going
to GZIPMessageEncodingBindingElement.cs and finding these lines:
public GZipMessageEncodingBindingElement(MessageEncodingBindingElement
this.innerBindingElement = messageEncoderBindingElement;

22) Insert the correct SOAP version in this constructor like this:
public GZipMessageEncodingBindingElement(MessageEncodingBindingElement
this.innerBindingElement = messageEncoderBindingElement;
this.innerBindingElement.MessageVersion = MessageVersion.Soap11;

23) Run the code again. It should now work. If not there might be some other
version issues, but try to work from the exception text and see where it
takes you ïŠ

My Computer