Silverlight 3: Calling a WCF service without a proxy using Binary XML

David Betz has a really solid (and really, really long) post on calling a WCF service from Silverlight, without using a Service Reference. I'm certainly not going to try and top that or duplicate it, but I wanted to share my experience using the same methodology only with Binary XML as the medium. I'm not interested in the politics over whether or not it should be used, as I'm using WCF and Silverlight. Interoperability beyond that is not important to me.

The WCF side of things has been pretty well covered, but your web.config should look something like this, with the important parts bold:

 <system.serviceModel>
  <bindings>
   <customBinding>
    <binding name="binaryBinding">
     <binaryMessageEncoding />
     <httpTransport />
    </binding>
   </customBinding>

  </bindings>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
  <behaviors>
   <serviceBehaviors>
    <behavior name="FeedBehavior">
     <serviceMetadata httpGetEnabled="true" />
     <serviceDebug includeExceptionDetailInFaults="false" />
    </behavior>
   </serviceBehaviors>
  </behaviors>
  <services>
   <service behaviorConfiguration="FeedBehavior" name="Namespace.ServiceClass">
    <endpoint address="" binding="customBinding" bindingConfiguration="binaryBinding" contract="Namespace.IWhateverContract" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
   </service>
  </services>
 </system.serviceModel>

It's important that the binaryMessageEncoding comes before httpTransport. I don't know why, it's just how it is.

The Silverlight side of things weren't as obvious to me at first. Looking at Betz's code, find the part with the basic code for calling the service, and replace the binding part so that it looks something like this:

var elements = new List<BindingElement>();
elements.Add(new BinaryMessageEncodingBindingElement());
elements.Add(new HttpTransportBindingElement());
var binding = new CustomBinding(elements);
var endpointAddress = new EndpointAddress("http://localhost:69/Feed.svc");
var channel = new ChannelFactory<IFeedService>(binding, endpointAddress).CreateChannel();

The first four lines replace the BasicHttpBinding. The rest of Betz's code is about the same.

Is this something that really matters, doing this instead of generating a proxy via the "Add Service Reference.." in Visual Studio? Personally, I think it's worth it, for delivery size alone. The .xap was 3k larger for a single service reference with one simple method. It just seems to me that for a big piece of application thingy that you'd want to keep it as small as possible, or at least use that 3k on something pretty, you know?

One other thing that I should mention is that I had some difficulty getting the client to talk to the service, but couldn't figure out why. No errors, the messages on the wire were correct, I was a little lost. What it ended up being is that I wasn't setting the name and namespace in the DataContract attribute on both ends. It'd be nice if there was something to clue me in that was a problem.

In any case, I'll buy into the speed and size benefits of using the binary mode for now. It's easy enough to create other end points for other data formats.

No Comments