Thursday, May 19, 2011

WCF and Interface

Sometime ago, I had a few WCF services without using interface. As time goes by, some functionality need to expand. To avoid exposing all the service functionality to a single endpoint, implementing multiple interfaces is necessary so that multiple endpoints can be configured based on interface. Unfortunately, with this change, it broke every client call (JavaScript) in the old code.

In the code, the JavaScript function calls were all used and based on the library stub automatically generated by ASP.NET where the page uses ScriptManager to manage MS AJAX library. Thus the change at the contract name specified in the Web.config will automatically refresh the changes into the library.

Previously, there was no interface involved. The contract attribute of the endpoint defined in Web.config is directly pointing to the name of service itself. For example,

 <system.serviceModel> 
  
  <behaviors>
    <endpointBehaviors>
      <behavior name="Shipment.Order.WebAspNetAjaxBehavior">
      <enableWebScript />
  </behavior>
    ....
  <service name="Shipment.Order">  
     <endpoint address="" 
           behaviorConfiguration="Shipment.Order.WebAspNetAjaxBehavior"
           binding="webHttpBinding" 
           contract="Shipment.Order" />
  </service>  
  ...  
</system.serviceModel>  

Now, with the interface; the declaration of the endpoint contract is the interface instead of the service itself.

  <service name="Shipment.Order">  
     <endpoint address="" 
           behaviorConfiguration="Shipment.Order.WebAspNetAjaxBehavior"
           binding="webHttpBinding" 
           contract="Shipment.IOrder" />
  </service>  

In the page, the original JavaScript would call the service operation like this:

    Shipment.Order.Confirm(myId);

In order to work with the interface approach, the JavaScript has to use the interface to make a call:

    Shipment.IOrder.Confirm(myId);

Since the service has been placed into service sometime ago, the change to use interface is not a good idea. It affects a lot of pages that use this service. Instead of making the existing service to implement an interface, I derived a subclass from it so that the subclass inherits whatever its parent has. Then I simply configure an endpoint for this subclass instead of configuring multiple endpoints for the existing service. As a result, it works like a charm!

If you are having a problem with the interface or keep getting JavaScript error such as “xxx is NULL or not an Object” or “Cannot call method 'xxx' of undefined”. You would better look at the method you use in the JavaScript. It must be changed to use the interface because the JavaScript stub generated by ASP.NET is based on the contract defined in the Web.config. You could change the namespace by declaring [ServiceContract(Namespace = "xxx")] at your interface/class but your contract name won't be changed. You can examine the JavaScript stub by appending "/js" to the end of the service URL to compare the differences.