简体   繁体   中英

Enabling GZIP for call WCF service on client

I enable Dynamic Compression on IIS using great Scott Hanselman article:

Enabling dynamic compression (gzip, deflate) for WCF Data Feeds, OData and other custom services in IIS7

In the beginning of the article he says that:

On the client side, it's easy to just add code like this:

request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate

First question is: Where should I add above code?

I'm using BasicHttpBinding and now please consider this code:

using (ServiceReference1.Srv1 client = new ServiceReference1.Srv1Client())
{
    var data = client.GetData(string longText, byte[] file);
}

by that code I call my service from client application. Now the question is how can I zip the client request(every parameters) with GZIP automatically that cause calling web service become faster?

Thanks

The request.AutomaticDecompression property is on HttpWebRequest object. I am not sure if you are using WCF OData Service. As per the Scott Hanselman's blog, this should work for WCF OData Service.

I guess the compression is not by default supported for BasciHttpBinding. The idea came from this blog.

I would create BehaviorExtensionElement, CompressionBehaviorSection as shown below.

public class MessageCompressionBehavior : IDispatchMessageInspector, IServiceBehavior, IClientMessageInspector
{

}


public class CompressionBehaviorExtensionElement :BehaviorExtensionElement
{

}

 <extensions> 
            <behaviorExtensions> 
                <add name="compression" type="yournamespace.CompressionBehaviorExtensionElement, yourassembly, Version=...., Culture=neutral, PublicKeyToken=......"/> 
            </behaviorExtensions> 
 </extensions>


<behaviors>
   <serviceBehavior>
         <compression />
   </serviceBehavior>
</behaviors>

Then apply this behavior on Basic Http Binding.

The IDispatchMessageInspector and IClientMessageInspector would compress / decompress the data depending on whether it is being sent or being received.

UPDATE: 29 / Jan / 2019 There is another way I found yesterday:

Step 1: If your service is IIS Hosted, you can enable dynamic Compression module.

Then add mime type for SOAP message in applicationHost.config as shown below:

<add mimeType="application/soap+xml" enabled="true" />
<add mimeType="application/soap+xml; charset=utf-8" enabled="true" />
<add mimeType="application/soap+xml; charset=ISO-8895-1" enabled="true" />

Step 2: Custom IWebRequestCreate

Once this is done, you will have to make the WCF send the "Accept Encoding" header with HTTP request. You can create custom IWebRequestCreate as shown below

public class CompressibleHttpRequestCreator : IWebRequestCreate
{
    public CompressibleHttpRequestCreator()
    {
    }

    WebRequest IWebRequestCreate.Create(Uri uri)
    {
        HttpWebRequest httpWebRequest =
            Activator.CreateInstance(typeof(HttpWebRequest),
            BindingFlags.CreateInstance | BindingFlags.Public |
            BindingFlags.NonPublic | BindingFlags.Instance,
            null, new object[] { uri, null }, null) as HttpWebRequest;

        if (httpWebRequest == null)
        {
            return null;
        }

        httpWebRequest.AutomaticDecompression = DecompressionMethods.GZip |
            DecompressionMethods.Deflate;

        return httpWebRequest;
    }
}

Step 3: Configuration Change in your client's config Then you can add below setting in your client's app.config or web.config:

<system.net>
  <webRequestModules>
    <remove prefix="http:"/>
    <add prefix="http:" type="WcfHttpCompressionEnabler.CompressibleHttpRequestCreator, WcfHttpCompressionEnabler, 
        Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  </webRequestModules>
</system.net>

The solution is explained at this blog . It also has a sample code at this link.

I hope this provides enough help on your issue.

This is just my suggestion.

You could define your own ClientMessageFormatter, DispatchMessageFormatter.

ClientMessageFormatter is used to serialize request and deserialize response.

DispatchMessageFormatter is used to deserialize request and serialize request.

If you could use your own CompressionAlgorithm to serialize and deserialize request and response using Gzip or deflate,the message will be smaller.

The two interface has bellow methods.

   public void DeserializeRequest(Message message, object[] parameters)
{

}

public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
{
       }

public object DeserializeReply(Message message, object[] parameters)
{
       }
public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
{
  }

To use your own ClientMessageFormatter and DispatchMessageFormatter, you should use an EndpointBehavior.

In you ApplyClientBehavior and ApplyDispatchBehavior, you should set your ClientMessageFormatter to ClientOperation's Formatter property and set your DispatchMessageFormatter to your DispatchOperation 's formatter property.

What's more, to enable dynamical compressionAlgorithm , you had better pass your compressionAlgorithm to your endpointbehavior, then the behavior passes the compressionAlgorithm to your ClientMessageFormatter and DispatchMessageFormatter so that it could know which compression to use.

There are still many things to do, for example, how to use wcf's default ClientMessageFormatter and DispatchMessageFormatter to serialize and deserialize the message combining your own ClientMessageFormatter and DispatchMessageFormatter.

Because wcf's default formatter is used to serialize and deserialize request and response, you could use your formatter to compress the message on the basic of wcf's serialize. So , before use your formatter , you should get wcf's default formatter in endpointbehavior's ApplyDispatchBehavior and ApplyClientBehavior.

Then set your own formatter's some property to wcf's default property so that you could use wcf's default formatter.

Request compressions is not an HTTP standard the servers or clients understand. To achieve that, you'll have to do it yourself both in the client and the server.

I haven't done WCF development in a while, but I'm pretty sure WCF has ways to do that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM