Reusable WCF components using Message Inspector, Contract Behavior and WSDL Export Extensions

Background & Problem Definition

 

While building web services to be provisioned to the world, there are certain functions which are generally required for every web service.

–          Authentication / Authorization of the Web API calls for security.

–          Service logging and more….

In an organization investing in a service infrastructure, as more web services are built and deployed, with similar needs, building reusable components can reduce the time and costs.

Hence, the goal of this study is to analyze WCF support for building such reusable components

Solution Discussion

 

Technical Problem 1: Need Reusable Components for the above requirements

To solve the above problem we researched on WCF service documentation and found a solution that WCF provides an inspector which can be plugged in the service behavior.

WCF Message Inspector:-

A WCF Message Inspector is a kind of a “message filter” that we can develop on the service or on the consumer side, in order to intercept and inspect the messages coming in or going out of the service layer infrastructure.

In order to define a Message Inspector on the consumer side we need to implement the IClientMessageInspector interface, while on the service side we need to implement the IDispatchMessageInspector interface. Here are their definitions:

public interface IClientMessageInspector
{
     void AfterReceiveReply (ref Message reply, object correlationState);
     object BeforeSendRequest (ref Message request, IClientChannel channel);
}
public interface IDispatchMessageInspector
{
    object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext);
    void BeforeSendReply(ref Message reply, object correlationState);
}

As we see in the above code the interfaces having a couple of methods defined and It’s very important to underline that the message provided to this method is a “by reference” parameter, because this allows our Message Inspector implementations to change the message while it is moving along the service model pipeline.

Here is an example of a service-side Message Inspector used to output to the Console any received and sent message:

public class MyMessageInspector: IDispatchMessageInspector
{
      public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
      {
          MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
          request = buffer.CreateMessage ();
          Console.WriteLine ("Received:{0}",
          buffer.CreateMessage ().ToString ());
          return null;
      }
      public void BeforeSendReply(ref Message reply, object correlationState)
      {
          MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue);
          reply = buffer.CreateMessage();
          Console.WriteLine("Sending: {0}",
          buffer.CreateMessage ().ToString ());
      }
}

In order to configure these message inspectors we can use a custom behavior. Behaviors are classes that extend the service model defining custom extensions for: contracts, endpoints, services, operations. In these examples we defined two different kinds of behaviors: one endpoint behavior and one service behavior.

Let’s start from the EndpointBehavior:

public class MyBehavior: IEndpointBehavior
{
       public void AddBindingParameters (ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
       {}
       public void ApplyClientBehavior (ServiceEndpoint endpoint, ClientRuntime clientRuntime)
       {
           throw new Exception("Behavior not supported on the consumer side!");
       }
       public void ApplyDispatchBehavior (ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
       {
           MyMessageInspector inspector = new MyMessageInspector ();
           endpointDispatcher.DispatchRuntime.MessageInspectors.Add (inspector);
       }
       public void Validate (ServiceEndpoint endpoint)
       {}

}

Adding the Message Inspector through Configuration

So, we built an inspector which made possible for our requirement of building a separate authentication component so that we can attach it with any WCF service which needs to check the authentication.

 

Problem 2: The authentication is needed as SOAP headers. For reusability, Can we insert dynamic SOAP Headers at run-time into WSDL?

 The goal here is to export custom metadata when a metadata request arrives, that is when WSDL is requested. Also, this has to be built into the runtime behavior of any service that needs this.

We used a combination of IWSDLExportExtension, IContractBehavior and used those as function attributes in the method on which this is needed. This will add authentication details in soap headers section in WSDL requests at run time.

Now on server side Message Inspector will inspect this MyAuthHeader and will perform the required action like Authentication and Authorization. Syntax is as follows –

[MyHeaders]

[MyHeader(“MyAuthHeader”, typeof (MyAuthHeader), Direction=SoapHeaderDirection.In)]

This MyHeader attribute will take HeaderName, HeaderType and Direction as input parameters and will apply them in the outgoing messages as described in the below example.

public class MyHeadersAttribute: Attribute, IContractBehavior, IWsdlExportExtension
{
     void IContractBehavior.AddBindingParameters(ContractDescription contractDescription,
          ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) {}

     void IContractBehavior.ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint,   System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
     {
          //Hook your Header here
     }
     void IContractBehavior.ApplyDispatchBehavior (ContractDescription contractDescription,
           ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.DispatchRuntime dispatchRuntime) {}

     void IContractBehavior.Validate(ContractDescription contractDescription, ServiceEndpoint endpoint){}

     void IWsdlExportExtension.ExportContract(WsdlExporter exporter, WsdlContractConversionContext context)
     {
        //Add and export your Header here
     }
     void IWsdlExportExtension.ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext   context){}
}

This MyHeader will be added in the custom MyHeaders attribute collection. Custom MyHeaders attribute collection implements the Attribute, IContractBehavior and IWsdlExportExtension. Now in the IContractBehavior.ApplyContractBehavior we hooked the Authentication Header and in IWsdlExportExtension.ExportContract we add the Headers in MyHeaders attribute. 

 

In the above diagram, there is a client consuming a service, when client calls the service the Authentication header will be added in the request header. Then request goes to the Inspector. The Inspector will validate the client credentials. If credentials are valid then it will transfer the call to the service method otherwise give an exception message invalid credential.

Conclusion

A combination of WCF message inspectors, Contract Behavior and WSDL Export Extensions made it possible to create reusable Web Services Components.

We built components which we were subsequently able to use in new WCF Web Service projects successfully.

For the inspectors, we just have to put a dll in bin folder and add one configuration in web.config file.

This can make our life much easier.

References

http://msdn.microsoft.com/en-us/library/aa717047.aspx

http://msdn.microsoft.com/en-us/library/system.servicemodel.description.icontractbehavior.aspx

http://msdn.microsoft.com/en-us/library/system.servicemodel.description.iwsdlexportextension.aspx

Leave a Reply

Your email address will not be published. Required fields are marked *


four × = 24

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>