2

I am developing a .NET 4.0 Console Application to serve as a SOAP Web Service client which will send data (POST) through to a third-party. I have no control over the web service on the server-side. The third-party did provide WSDL's to use, and I was able to import them and use them with reasonable success. However, there is a requirement to compress the request message using gzip, and I could not for the life of me figure out how to do that using the proxy services.

This topic here on SO, led me to believe that without having control over both the client and server code, the request is unable to be compressed. As a result of this finding, I wrote the code in my application to manually create the SOAP XML in a XDocument object; then, populated the values from the WSDL proxy class objects which I had previously coded my client application to use.

The first requirement for this client, is to send the message compressed via gzip. After some research, I have seen answers as simple as just adding the HttpRequestHeader.AcceptEncoding, "gzip, deflate" to the request header. Unfortunately, doing that that didn't appear to work.

Currently, the certificate which I am retrieving is not the real certificate. I am trying to make the code as sound as I can before deploying to a test environment to do the actual service testing.

  1. Is there a way to compress the request via the proxy call (wsdl)?
  2. Is there something I am missing in order to properly compress the HttpWebRequest?
  3. Might there be something else going wrong which would result in the error message to be returned?
    I would expect a different message pertaining to authentication being invalid if the request itself was OK.
  4. Is there a way the compression can be done through the app.config?

The next set of requirements I'm a little confused on how to handle/what to do. Under the assumption that what I have set the ContentType of the request to, how (and what) do I add in order to add the content-transfer-encoding piece to the request? If the ContentType is incorrect, how should I add this information as well?

The content type for the SOAP Evenlope with MTOM encoded attachment must be "application/xop+xml" and the content-transfer-encoding must be 8-bit.

I've gone through a few iterations of the code below, however, I believe the relevant snippets are the code at its simplest form. Please let me know if there is other information that would be helpful.

Method to create the HttpWebRequest:

private static HttpWebRequest CreateWebRequest(SoapAction action)
{
    string url = GetUrlAddress(action);

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

    request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
    request.Headers.Add("SOAPAction", action.ToString());
    request.ContentType = "application/xop+xml";
    request.Accept = "text/xml";
    request.Method = "POST";

    request.ClientCertificates.Add(/* Retrieve X509Certificate Object*/);

    return request;
}

Code to Send Request:

using (Stream stream = request.GetRequestStream())
{
    soapXml.Save(stream);
}

Code to retrieve the Response:
This is how I am retrieving the error message that is occurring

try
{
    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    {
        using (StreamReader reader = new StreamReader(response, Encoding.Default))
        {
            File.AppendAllText(filePath, response.Headers.ToString());
            File.AppendAllText(filePath, reader.ReadToEnd());
        }
    }
}
catch (WebException ex)
{
    using (var stream = ex.Response.GetResponseStream())
    {
        using (var reader = new StreamReader(stream))
        {
            Console.WriteLine(reader.ReadToEnd());
        }
    }
}

Error Message being Received:

The request message must be sent using HTTP compression (RFC 1952 - GZIP).

Community
  • 1
  • 1
Russ
  • 678
  • 8
  • 26

2 Answers2

2

I think I was able to solve the compression error message by adding the following to the HttpWebRequest method:

request.Headers.Add(HttpRequestHeader.ContentEncoding, "gzip"); 

Updated Method to create the HttpWebRequest:

private static HttpWebRequest CreateWebRequest(SoapAction action)
{
    string url = GetUrlAddress(action);

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

    request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
    request.Headers.Add(HttpRequestHeader.ContentEncoding, "gzip"); 
    request.Headers.Add("SOAPAction", action.ToString());
    request.ContentType = "application/xop+xml";
    request.Accept = "text/xml";
    request.Method = "POST";

    request.ClientCertificates.Add(/* Retrieve X509Certificate Object*/);

    return request;
}
Russ
  • 678
  • 8
  • 26
  • Aha, looks like another example of convention based programming. I despise convention based, as it's very unintuitive. Either you know what magical properties to add, or you don't. I once spent a day banging my head against the desk trying to figure out why a controller I created in ASP.NET wasn't working, until I realized the class name -had- to end with "Controller" (as in MyClassController) or ASP.NET wouldn't recognize it.... even if it inherits from Controller. Such a pain. – Brett Allen Jan 31 '16 at 21:14
1

Use the following in place of your current code to send the request.

using (Stream stream = request.GetRequestStream())
using (GZipStream gz = new GZipStream(stream, CompressionMode.Compress, false))
{
    soapXml.Save(gz);
}

Edit: Might need to use "new GZipStream(stream, CompressionMode.Compress, true)". Can't say for certain how that constructor parameter will affect the web request stream.

Brett Allen
  • 5,297
  • 5
  • 32
  • 62
  • First, thank you for your response. Unfortunately, using that with either true or false as the constructor parameter, resulted in the same error message output by the WebException. – Russ Jan 28 '16 at 16:18
  • Very odd. I'll have to check the code I've written in the past. – Brett Allen Jan 28 '16 at 20:27
  • 1
    See my response to what I had to do in order to overcome the error. I also kept your suggestion in place and put a `CompressionMode.Decompress` on the `HttpWebResponse`. – Russ Jan 28 '16 at 22:01