Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX

By submitting your information, you agree that devx.com may send you DevX offers via email, phone and text message, as well as email offers about other products and services that DevX believes may be of interest to you. DevX will process your information in accordance with the Quinstreet Privacy Policy.


Build a Custom WCF Encoder  : Page 2

When the built-in WCF encoders don't meet your needs, follow this example to create a custom encoder—and just plug it in!




Application Security Testing: An Integral Part of DevOps

Creating a Custom Encoder

To begin, you need to create a custom MessageEncoderFactory, which creates your custom encoder object. It needs:

  • An overridden encoder object
  • An overridden message version

Listing 1 contains the code for an example class named CustomEncoderFactory created from the CustomMessageEncoder factory. You need to mark the Encoder as a singleton object of the CustomMessageEncoder factory.

To create a CustomEncoderFactory instance, you need to pass in two new things: an EncodeMode enumeration value, and an EnableCompression variable:

  • EncodeMode is an enum that supports dynamically changing the encoding format based on configuration values, and writing compression/decompression logic without relying on advance knowledge of any particular Encoder. The enum shown below supports various compression types including None, Deflate, Gzip, and you could easily add many more custom compression encoder formats in the future:

/// <summary> /// Compression Encoder formats. Add custom encoders such as /// ICSharpLib, 7z, rar /// </summary> public enum CompressionEncoder { None, Deflate, GZip }

  • EnableCompression is a Boolean switch value that lets you enable or disable compression as discussed earlier.

Next, you need to create a CustomEncoder that implements the abstract MessageEncoder class (see Listing 2). The example in Listing 2 implements an IsDataCompressed Boolean method that provides an easy way to determine if the data is compressed. For Gzip, you can use the "magic code" value (see the GZIP_MAGIC constant in Listing 2) to determine whether the data is compressed.

As mentioned earlier, you'll see that the encoding process in this custom encoder takes place at in the ReadMessage and WriteMessage methods. You also need to override the ContentType property to deliver different content types. The CompressionEncoder enum value determines the content type at runtime.

Next, you need to create a CustomMessageEncodingBinding Element that lets you specify the configurable custom properties, which in this case include EnableCompression, CompressionEncoder, and the binding element. Listing 3 contains the code.

Lastly, you need to create a CustomMessageEncodingElement. This element derives from the BindingElementExtensionElement class (see Listing 4).

Note: the use of the ConfigurationPropertyAttribute—it helps to map the attributes to the properties.

After the values have been read from the configuration file, the CreateBindingElement method acts as an entry point and serves to convert the values read into suitable properties of the Custom Binding Element.

The key points to note are:

  • The CreateBindingElement method, which acts as an entry point.

  • Author's Note: You could alter the messageversion property of the binding element through configuration, but for simplicity, that process is not shown here.

  • The ApplyConfiguration method which lets you explicitly indicate properties such as:
  • ReaderQuotas, which are used to assign properties to the CustomMesssageEncodingBindingElement.
  • The ReaderQuotas.MaxArrayLength value controls the request size. Because this example uses custom binding, you need to set it to the binding element.

To conclude, you need to implement the configuration sections for the CustomBindingElement. On the client, the configuration looks like this:

<system.serviceModel> <extensions> <bindingElementExtensions> <add name="customMessageEncoding" type=" Infrastructure.CustomEncoder.CustomMessageEncodingElement, assemblyname" /> </bindingElementExtensions> </extensions> <bindings> <customBinding> <binding name="myBinding"> <customMessageEncoding innerMessageEncoding= "textMessageEncoding" enableCompression="false" compressionEncode="gzip"> <readerQuotas maxArrayLength="62914560" ></readerQuotas> </customMessageEncoding > <httpTransport maxBufferSize="62914560" maxReceivedMessageSize="62914560" authenticationScheme="Anonymous" proxyAuthenticationScheme="Anonymous" useDefaultWebProxy="true" /> </binding> </customBinding> </bindings> <client> <endpoint address="" binding="customBinding" bindingConfiguration="myBinding" contract="IService" name="Service1"> </endpoint> </client> </system.serviceModel>

The custom binding created above uses the new CustomMessageEncoding. Also note that the httpTransport inner element currently represents only BasicHttpBinding, but could be adapted to work with future needs. Requests do not usually need to be compressed, as they tend to be small; in fact, compressing them often increases the request size. Hence, the client configuration file shown above uses the enableCompression="false" setting.

The server configuration would look like this:

<system.serviceModel> <extensions> <bindingElementExtensions> <add name="customMessageEncoding" type=" Infrastructure.CustomEncoder.CustomMessageEncodingElement, assemblyname" /> </bindingElementExtensions> </extensions> <bindings> <customBinding> <binding name="myBinding"> <customMessageEncoding innerMessageEncoding="textMessageEncoding" enableCompression="true" compressionEncode="gzip"> <readerQuotas maxArrayLength="62914560" > </readerQuotas> </customMessageEncoding > <httpTransport maxBufferSize="62914560" maxReceivedMessageSize="62914560" authenticationScheme="Anonymous" proxyAuthenticationScheme="Anonymous" useDefaultWebProxy="true" /> </binding> </customBinding> <bindings> <services> <service behaviorConfiguration="Host.Behavior" name="Host.Service"> endpoint address="" binding="customBinding" bindingConfiguration="myBinding" contract="ServiceContracts.IService" /> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> </system.serviceModel>

By following the procedures described in this article, you'll find that it's both straightforward and transparent to add custom encoding to your WCF messaging applications. Be sure to download the provided sample code, which contains the full source for all the classes described in this article as well as the configuration sections you'll need.


Srinath M. S. says: "I would love to leave a footprint in this flat world."
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



We have made updates to our Privacy Policy to reflect the implementation of the General Data Protection Regulation.
Thanks for your registration, follow us on our social networks to keep up-to-date