Posted by: beatkiener | May 22, 2009

BasicHttpBinaryBinding for Silverlight

Silverlight 3 beta introduces a binary message encoder on the channel stack.

Binary encoding is implemented as a custom binding, there is no out-of-the-box binary binding.

<bindings>
  <customBinding>
	<binding name="binaryHttpBinding">
	   <binaryMessageEncoding />
         <httpTransport />
      </binding>
  </customBinding>
</bindings>
<endpoint address=""
          binding="customBinding"
          bindingConfiguration="binaryHttpBinding"
          contract="Service" />

If you would set the binding programmatically you have to configure your own CustomBinding instance.

This was the reason to implement the BasicHttpBinaryBinding class as you can find below.

UPDATE May 2010: The method CreateBindingElements copies now the reader quotas and other settings to the binary element.

/// <summary>
// Represents a basic http binding with binary encoding.
/// </summary>
public class BasicHttpBinaryBinding : BasicHttpBinding
{
  /// <summary>
  ///  Initializes a new instance of the BasicHttpBinaryBinding class.
  /// </summary>
  public BasicHttpBinaryBinding()
    : this(BasicHttpSecurityMode.None)
  {
  }

  /// <summary>
  /// Initializes a new instance of the BasicHttpBinaryBinding class.
  /// </summary>
  /// <param name="securityMode">
  /// The value of System.ServiceModel.BasicHttpSecurityMode that specifies 
  /// the type of security that is used with the SOAP message and for the client.
  /// </param>
  public BasicHttpBinaryBinding(BasicHttpSecurityMode securityMode)
    : this(securityMode, true)
  {
  }

  /// <summary>
  /// Initializes a new instance of the BasicHttpBinaryBinding class.
  /// </summary>
  /// <param name="securityMode">
  /// The value of System.ServiceModel.BasicHttpSecurityMode that specifies 
  /// the type of security that is used with the SOAP message and for the client.
  /// </param>
  /// <param name="binaryEncoding">
  /// Indicates whether the binary encoding is enabled or not
  /// </param>
  public BasicHttpBinaryBinding(BasicHttpSecurityMode securityMode, bool binaryEncoding)
    : base(securityMode)
  {
    this.BinaryEncoding = true;
    this.BinaryEncoding = binaryEncoding;
  }

  /// <summary>
  /// Gets or sets a value that indicates whether the binary encoding is enabled or not. 
  /// Default is true.
  /// </summary>
  public bool BinaryEncoding { get; set; }

  /// <summary>
  /// Returns an ordered collection of binding elements contained in the current binding.
  /// </summary>
  public override BindingElementCollection CreateBindingElements()
  {
    BindingElementCollection elements = base.CreateBindingElements();

    if (this.BinaryEncoding)
    {
      // search the existing message encoding element (Text or MTOM) and replace it
      // note: the search must be done with the base type of text and mtom binding element, 
      // because this code is compiled against silverlight also 
      // and there is no mtom encoding available
      for (int i = elements.Count - 1; i >= 0; i--)
      {
        BindingElement element = elements[i];
        if (element.GetType().IsSubclassOf(typeof(MessageEncodingBindingElement)))
        {
          BinaryMessageEncodingBindingElement binaryElement = null;

          if (element is TextMessageEncodingBindingElement)
          {
            // copy settings to binary element
            TextMessageEncodingBindingElement textEncoding = element as TextMessageEncodingBindingElement;
            binaryElement = new BinaryMessageEncodingBindingElement();

            // copy settings
            binaryElement.ReaderQuotas.MaxArrayLength = textEncoding.ReaderQuotas.MaxArrayLength;
            binaryElement.ReaderQuotas.MaxBytesPerRead = textEncoding.ReaderQuotas.MaxBytesPerRead;
            binaryElement.ReaderQuotas.MaxDepth = textEncoding.ReaderQuotas.MaxDepth;
            binaryElement.ReaderQuotas.MaxNameTableCharCount = textEncoding.ReaderQuotas.MaxNameTableCharCount;
            binaryElement.ReaderQuotas.MaxStringContentLength = textEncoding.ReaderQuotas.MaxStringContentLength;
            binaryElement.MaxReadPoolSize = textEncoding.MaxReadPoolSize;
            binaryElement.MaxWritePoolSize = textEncoding.MaxWritePoolSize;

            // binary uses always soap-1.2
            //binaryElement.MessageVersion = textEncoding.MessageVersion;
          }
          else if (element is MtomMessageEncodingBindingElement)
          {
            // copy settings to binary element
            MtomMessageEncodingBindingElement mtomEncoding = element as MtomMessageEncodingBindingElement;
            binaryElement = new BinaryMessageEncodingBindingElement();

            // copy settings
            binaryElement.ReaderQuotas.MaxArrayLength = mtomEncoding.ReaderQuotas.MaxArrayLength;
            binaryElement.ReaderQuotas.MaxBytesPerRead = mtomEncoding.ReaderQuotas.MaxBytesPerRead;
            binaryElement.ReaderQuotas.MaxDepth = mtomEncoding.ReaderQuotas.MaxDepth;
            binaryElement.ReaderQuotas.MaxNameTableCharCount = mtomEncoding.ReaderQuotas.MaxNameTableCharCount;
            binaryElement.ReaderQuotas.MaxStringContentLength = mtomEncoding.ReaderQuotas.MaxStringContentLength;
            binaryElement.MaxReadPoolSize = mtomEncoding.MaxReadPoolSize;
            binaryElement.MaxWritePoolSize = mtomEncoding.MaxWritePoolSize;

            // binary uses always soap-1.2
            //binaryElement.MessageVersion = mtomEncoding.MessageVersion;
          }
          else if (element is BinaryMessageEncodingBindingElement)
          {
            // it's already binary
          }
          else
          {
            string exStr = string.Format("Message encoding type {0} is not implemented.", element.GetType().Name);
            throw new NotImplementedException(exStr);
          }

          if (binaryElement != null)
          {
            elements.RemoveAt(i);
            elements.Insert(i, binaryElement);
            break;
          }
        }
      }
    }

    return elements;
  }

}

The class is Silverlight compilable, therefore you can share it along the Silverlight and wcf-service project.

How to use: instead of the BasicHttpBinding you can use BasicHttpBinaryBinding as following to enable binary encoding.

BasicHttpBinding binding = new BasicHttpBinding();

BasicHttpBinding binding = new BasicHttpBinaryBinding();

Download the code here

Advertisement

Responses

  1. Kieners — Please help. (1) You mention MTOM but I have been reading elsewhere that SL3 does not support MTOM at all. Which is correct? Is your solution a workaround that allows SL3 to use MTOM? Is it is fact true that MTOM is supported intrinsically in SL3? Something else? (2) I have to move large chunks of data, large DOC or RTF or similar files, and I am wondering– will the BasicBinaryBinding solution you note help to move that data faster? Do you have any recommendations for my case? Pelase advise. Thank you. — Mark Kmaoski

    • Hi mkamoski,

      Sorry for my late anwser.

      Well, SL3 doesn’t support MTOM. The difference is that binary encoding is proprietary and MTOM is standardized and interoperable.
      With binary encoding you get some serious performance gains over text encoding. In our projects, when binary encoding is enabled the reduction of the message size is about 30-40 percent. But keep in mind that binary encoding is a proprietary format and a WCF only feature.

      Some explanations about the code:
      My class BasicHttpBinaryBinding is compiled against Silverlight-CLR and the normal-CLR, because you will use it in both environments to declare your endpoints for binary message encoding. On server side (in the normal-CLR) the BasicHttpBinaryBinding must ensure that no other encoding such as Text or MTOM is in use or you get an exception.

      Hope this helps.

      Best regards,
      Beat Kiener


Leave a Reply

Fill in your details below or click an icon to log in:

Gravatar
WordPress.com Logo

Please log in to WordPress.com to post a comment to your blog.

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Categories

Follow

Get every new post delivered to your Inbox.