title: WCF binding extension for message compression
body: <p>I'm trying to add message compression to my WCF service, but I'm kind of stuck...</p>
  
  <p>So far I have:</p>
  
  <ol>
  <li><p>An implementation of MessageEncoder:  </p>
  
  <pre><code>public class CompressionEncoder : MessageEncoder  
  {
  
      public CompressionEncoderFactory _factory;  
      public const string GZipContentType = "application/x-gzip";
  
      public override string ContentType
      {
          get
          {
              return GZipContentType;
          }
      }
  
      public override string MediaType
      {
          get { return ContentType; }
      }
  
      public override MessageVersion MessageVersion
      {
          get { return _factory.MessageVersion; }
      }
  
      public CompressionEncoder(CompressionEncoderFactory factory)
      {
          _factory = factory;
      }
  
      public override Message ReadMessage(Stream stream, int maxSizeOfHeaders,     string contentType)
      {
          var decompressedStream = new GZipStream(stream, System.IO.Compression.CompressionMode.Decompress, false);
          XmlReader reader = XmlReader.Create(decompressedStream);
          Message msg = Message.CreateMessage(reader, maxSizeOfHeaders, _factory.MessageVersion);
          msg.Properties.Encoder = this;
          return msg;
      }
  
      public override Message ReadMessage(ArraySegment&lt;byte&gt; buffer, BufferManager bufferManager, string contentType)
      {
          MemoryStream stream = new MemoryStream(buffer.Array, buffer.Offset, buffer.Count);
          GZipStream decompressedStream = new GZipStream(stream, System.IO.Compression.CompressionMode.Decompress);
          return ReadMessage(decompressedStream, int.MaxValue);
      }
  
      public override void WriteMessage(Message message, Stream stream)
      {
          GZipStream compressedStream = new GZipStream(stream, System.IO.Compression.CompressionMode.Compress, true);
          XmlWriter writer = XmlWriter.Create(compressedStream);
          message.WriteMessage(writer);
      }
  
      public override ArraySegment&lt;byte&gt; WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset)
      {
          MemoryStream stream = new MemoryStream();
          GZipStream compressedStream = new GZipStream(stream, System.IO.Compression.CompressionMode.Compress, true);
          XmlWriter writer = XmlWriter.Create(compressedStream);
          message.WriteMessage(writer);
          writer.Close();
  
          int messageLength = (int)compressedStream.Length;
          byte[] messageBytes = new byte[messageLength];
         compressedStream.Read(messageBytes, 0, messageLength);
  
          int totalLength = messageLength + messageOffset;
          byte[] totalBytes = bufferManager.TakeBuffer(totalLength);
          Array.Copy(messageBytes, 0, totalBytes, messageOffset, messageLength);
  
          ArraySegment&lt;byte&gt; byteArray = new ArraySegment&lt;byte&gt;(totalBytes, messageOffset, messageLength);
          return byteArray;
      }
  
  }
  </code></pre></li>
  <li><p>An implementation of MessageEncoderFactory:  </p>
  
  <pre><code>public class CompressionEncoderFactory : MessageEncoderFactory
  {
      CompressionMessageEncodingBindingElement _element;
  
      public CompressionEncoderFactory(CompressionMessageEncodingBindingElement element)
      {
          _element = element;
      }
  
      public override MessageEncoder Encoder
      {
          get { return new CompressionEncoder(this); }
      }
  
      public override MessageVersion MessageVersion
      {
          get { return _element.MessageVersion; }
      }
  }
  </code></pre></li>
  <li><p>An implementation of MessageEncodingBindingElement:  </p>
  
  <pre><code>public sealed class CompressionMessageEncodingBindingElement : MessageEncodingBindingElement 
  {
      MessageVersion _messageVersion = MessageVersion.None;
  
      public override MessageEncoderFactory CreateMessageEncoderFactory()
      {
          return new CompressionEncoderFactory(this);
      }
  
      public override MessageVersion MessageVersion
      {
          get
          {
              return _messageVersion;
          }
          set
          {
              _messageVersion = value;
          }
      }
  
      public override BindingElement Clone()
      {
          return new CompressionMessageEncodingBindingElement();
      }
  }
  </code></pre></li>
  <li><p>An implementation of BindingElementExtensionElement:  </p>
  
  <pre><code>public class CompressionBindingElementExtensionElement : BindingElementExtensionElement
  {
      public override Type BindingElementType
      {
          get { return typeof(CompressionMessageEncodingBindingElement); }
      }
  
      protected override System.ServiceModel.Channels.BindingElement      CreateBindingElement()
      {
          return new CompressionMessageEncodingBindingElement();
      }
  }
  </code></pre></li>
  <li><p>In the web.config I added this:</p>
  
  <pre><code>&lt;service name="MyService"&gt;
      &lt;endpoint address="" binding="customBinding" bindingConfiguration="CompressionBinding" contract="IMyService" /&gt;
      &lt;endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /&gt;
  &lt;/service&gt;
  ...
  &lt;bindings&gt;
    &lt;customBinding&gt;
      &lt;binding name="CompressionBinding"&gt;
        &lt;messageCompression /&gt;
        &lt;httpTransport authenticationScheme="Anonymous"&gt;&lt;/httpTransport&gt;
      &lt;/binding&gt;
    &lt;/customBinding&gt;
  &lt;/bindings&gt;
  ...
  &lt;extensions&gt;
    &lt;bindingElementExtensions&gt;
      &lt;add name="messageCompression" type="MyNamespace.CompressionBindingElementExtensionElement, MyNamespace" /&gt;
    &lt;/bindingElementExtensions&gt;
  &lt;/extensions&gt;
  </code></pre></li>
  </ol>
  
  <hr>
  
  <p>But when I run a client and call some service code, I get the following error:</p>
  
  <pre><code>The message version of the outgoing message (EnvelopeNone (http://schemas.microsoft.com/ws/2005/05/envelope/none) AddressingNone (http://schemas.microsoft.com/ws/2005/05/addressing/none)) does not match that of the encoder (Soap12 (http://www.w3.org/2003/05/soap-envelope) Addressing10 (http://www.w3.org/2005/08/addressing)). Make sure the binding is configured with the same version as the message.
  </code></pre>
  
  <p>What am I doing wrong?</p>