Session: Refactoring to SOLID Code

We recently organized October User Group Meeting on Design Principles and Practices at MIC, Karachi. I did a session on “Refactoring to SOLID code” and really enjoyed discussion with developers on design principles and practices.
We talked about aspects of bad design, better design and how we can apply SOLID principles to our day to day code. The session was irrespective of any technology and more related to Object Oriented Principles. As ‘software design’ is one of the area I am passionate about, so I love the talk.

AttendeesAdil Mughal - Refactoring to SOLID Code

The objective was to provide awareness and realization to developers on how following different design principles and practices will eventually make their life easy. I would like to thank everyone who attended the session and the contributors who made this event reality especially speaker (visitor) Zubair Ahmed and Kamran (from MIC) for needful arrangements.
As promised, I have shared session presentation and source code. See details below. StructureMap, the free Dependency Injection tool can be downloaded from github or Nuget Package
You can download source code demonstrated and presentation from shared folder.
P.S. Hope everyone enjoyed lucky draw 😉

WCF Custom Header with Silverlight

In my previous post “Client Additional Parameters using Custom Headers in WCF“, I discussed about passing additional parameters from client in SOAP header with WCF service by implementing IClientMessageInspector, IEndPointBehavior and BehaviorExtensionElement.

I am really glad to know that it help some of you. However, I have received some queries from readers for implementing custom headers with Silverlight client which I am going to discuss in this post.

While working on Silverlight client, we have limited framework available and to implement custom headers there are some slight changes:

  1. Instead of App.config or Web.config, you have ServiceReference.ClientConfig
  2. MessageHeader (Generic) class is not available instead you can use MessageHeader class
  3. There is no BehaviorExtensionElement class available in Silverlight 4 Runtime
  4. Since there is no BehaviorExtensionElement class, therefore you cannot define extension in .config file
  5. You need to programmatically bind/add custom endpoint behavior

I have pasted the code snippet below, that would work fine with Silverlight 4 client to pass custom header to WCF service.

IClientMessageInspector

   1:  public class MyMessageInspector : IClientMessageInspector
   2:  {
   3:      #region IClientMessageInspector Members
   4:   
   5:      public void AfterReceiveReply(ref Message reply,
   6:                                      object correlationState)
   7:      {
   8:          Debug.WriteLine("SOAP Response: {0}", reply.ToString());
   9:      }
  10:   
  11:      public object BeforeSendRequest(ref Message request,
  12:                                      IClientChannel channel)
  13:      {
  14:          const string STR_Customer_Unique_Id = "Customer Unique Id: 12345";
  15:          var header = MessageHeader.CreateHeader("Identity", 
  16:                                                  "http://www.adilmughal.com", 
  17:                                                  STR_Customer_Unique_Id);
  18:          request.Headers.Add(header);
  19:          Debug.WriteLine("SOAP Request: {0}", request.ToString());
  20:          return null;
  21:      }
  22:      #endregion
  23:  }

Note that the header is now created (see line 15) using simple MessageHeader class.

IEndPointBehavior

   1:  public class CustomBehavior : IEndpointBehavior
   2:  {
   3:      #region IEndpointBehavior Members
   4:   
   5:      public void AddBindingParameters(ServiceEndpoint endpoint,
   6:                                          BindingParameterCollection bindingParameters)
   7:      {
   8:      }
   9:   
  10:      public void ApplyClientBehavior(ServiceEndpoint endpoint,
  11:                                      ClientRuntime clientRuntime)
  12:      {
  13:          clientRuntime.MessageInspectors.Add(new MyMessageInspector());
  14:      }
  15:   
  16:      public void ApplyDispatchBehavior(ServiceEndpoint endpoint,
  17:                                          EndpointDispatcher endpointDispatcher)
  18:      {
  19:      }
  20:   
  21:      public void Validate(
  22:          ServiceEndpoint endpoint)
  23:      {
  24:      }
  25:      #endregion
  26:  }

You may have observed that in contrast to previously discussed solution in last post, we are not implementing BehaviorExtensionElement any more.

Adding Behavior to Proxy

ServiceProxy.TestServiceClient proxy = new ServiceProxy.TestServiceClient();
proxy.Endpoint.Behaviors.Add(new CustomBehavior());

Without BehaviorExtensionElement, we cannot define custom endpoint behavior in .config file so need to plug it programmatically.

That is all. You may download code sample-LINK TO CODE. Hope this helps. If you have somewhat different solution, please do share.

Client Additional Parameters using Custom Headers in WCF

When building Service communication applications using Windows Communication Foundation, we often come to a situation where we have multiple clients communicating with WCF Service and we need to pass additional parameters from client to service. This may be due to number of reasons such as sharing a unique customer ID to identify certain elements for that particular client. In such scenarios, for every communication between client and server, you need this unique ID to treat each client accordingly.

Client-Server-Customer-Id-Parameter-WCF

In a typical disconnected environment over the internet you need to pass such data on each call to service and of course passing in each Service Method or Operation Call is confusing and not appropriate.

A good Solution is to pass additional parameters in SOAP headers utilizing with the help of Custom headers in WCF. A SOAP envelope contains a header and a body. Method call and its parameters are transformed to SOAP body whereas SOAP header usually contains application-specific information (like authentication etc.)

 image

A simple way to achieve this in WCF is to add MessageHeader in your proxy class as in code snippet below:

public partial class TestServiceClient : ClientBase<Client.ServiceProxy.ITestService>, Client.ServiceProxy.ITestService
{
    public TestServiceClient()
    {
        var header = new MessageHeader<string>("Customer Unique Id: 12345");
        var untyped = header.GetUntypedHeader("Identity", "http://www.adilmughal.com");
        OperationContext.Current.OutgoingMessageHeaders.Add(untyped);
    } 
    //Other constructors and Service Method Calls
}

However this is really NOT a suitable approach as if you would be generating proxy using svcutil.exe or using Visual Studio then it will replace your proxy code.

A Better Solution to solve this problem is to utilize custom behavior extension in WCF to pass additional parameters in SOAP Message header. Following are the steps required on client:

1) Implement IClientMessageInspector to create custom message inspector

public class MyMessageInspector : IClientMessageInspector
{
    public void AfterReceiveReply(ref Message reply,object correlationState)
    {
       Console.WriteLine("SOAP Response: {0}", reply.ToString());
    }
        
    public object BeforeSendRequest(ref Message request,IClientChannel channel)
    {
       var header = new MessageHeader<string>("Customer Unique Id: 12345");
       var untyped = header.GetUntypedHeader("Identity", "http://www.adilmughal.com");
       request.Headers.Add(untyped);Console.WriteLine("SOAP Request: {0}", request.ToString());
       return null;
    } 
}

2) Create a custom behavior class implementing IEndPointBehavior and BehaviorExtensionElement. Then add the custom message inspector in runtime in ApplyClientBehavior method as shown in code snippet below:

public class CustomBehavior : BehaviorExtensionElement, IEndpointBehavior
{
    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.MessageInspectors.Add(new MyMessageInspector());
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
    }

    public void Validate(ServiceEndpoint endpoint)
    {
    }

    public override Type BehaviorType
    {
        get {   return typeof(CustomBehavior);  }
    }   

    protected override object CreateBehavior()
    {
        return new CustomBehavior();
    }
}

3) Finally, register behavior in .config under

<behaviors>
 <endpointBehaviors>
 <behavior>
 <customInspector />
 </behavior>
 </endpointBehaviors>
</behaviors>
<extensions>
 <behaviorExtensions>
 <add name="customInspector" type="Client.CustomBehavior, Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
 </behaviorExtensions>
</extensions>

That is all you have to do on client end to pass additional parameter in SOAP header using Custom Behavior in WCF.

To retrieve parameter passed in header on server side, you need to use OperationContext object

MessageHeaders headers = OperationContext.Current.IncomingMessageHeaders;
string customParameter = headers.GetHeader&lt;string&gt;("Identity", "http://www.adilmughal.com");
return string.Format("You entered: {0}", customParameter);

This would achieve the objective. Following is the detail of SOAP Envelope:

SOAP Request:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/ITestService/GetDataAction>
<Identity xmlns="http://www.adilmughal.com">Customer Unique Id: 12345Identity>
s:Header>
<s:Body>
<GetData xmlns="http://tempuri.org/">
<value>123value>
GetData>
s:Body>
SOAP Response:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<GetDataResponse xmlns="http://tempuri.org/">
<GetDataResult>You entered: Customer Unique Id: 12345GetDataResult>
GetDataResponse>
s:Body>
s:Envelope>

In this post we saw how to create custom SOAP header in WCF to pass parameter from client to server using WCF behavior extension. Hope this helps.