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.




MCTS 70-513–.NET 4, Service Communication Apps

Today, I am excited and pleased to share that I have passed Microsoft Exam TS: 70-513 and hence become

Microsoft Certified Technology Specialist (MCTS) – .NET Framework 4, Service Communication Applications.

“This exam is designed to test the candidate’s knowledge and skills for developing applications using Windows Communication Foundation and the .NET Framework 4”. To see the skills measured and outline of the exam, please visit here.

WCF – Browsing svc file – HTTP Error 404.3

Recently,at office, our laptops were replaced by new Sony VAIO with Vista Business SP1. So today when I hosted WCF service in IIS 7.0. I got an error like

HTTP Error 404.3 – Not Found
Description: The page you are requesting cannot be served because of the Multipurpose Internet Mail Extensions (MIME) map policy that is configured on the Web server. The page you requested has a file name extension that is not recognized, and is not allowed.

Solution:

What is intuitive here is that .svc extension is not recognized i.e. Http handler of .svc is not defined 🙂 So the solution I found was that:

Start –> Run –> optionalfeatures

wndFeaturesWCFmarkedAnd you will notice that WCF HTTP Activation and WCF Non-HTTP Activation both are unchecked, so all you have to do is to check both these items and click ok. Windows will take few minutes to update and after that your WCF Service will run smoothly on Vista and IIS7.

I just faced that problem today, so I thought it will be great to share with other developers or perhaps it can be used as reference in future for myself as well.

Microsoft Enterprise Tech Talk – Introduction to WCF

I recently gave an Introductory session on Windows Communication Foundation at Microsoft Innovation Center, Karachi – Pakistan (20th Mar’ 09). Adil

The targeted audience were industry professionals and the goal was to demonstrate them making WCF services. Following was the agenda of the session:

  • Background
  • What is WCF?
  • WCF Service Model
  • Creating a WCF Service
    • Contract
    • Binding
    • Address
  • Hosting ServicesAudience
  • Creating and Invoking WCF Clients
  • Configurable Endpoints
  • Migration and Performance Issues

The session was followed by Q & A in which audience were very keen to ask question related to migration from ASMX to WCF. I shared some of my experience using WCF services with the audience as well.

In collaboration with Microsoft Community Partner, We are soon going to announce another session on “Exploring WCF Features” in which we will see the demo of some features that ship with WCF.

I would like to thank all the participants for their valuable time and interest.

Adil Mughal

WCF Binding Selection

Windows Communication Foundation(WCF) Services exposes endpoint(s) and each endpoint has information of ABC i.e. Address, Binding and Contract.

Binding defines the underlying protocol, message encoding and transport details which are essential for client and service to communicate with each other. WCF provides several pre-configured bindings having different protocols, encoding scheme etc. Further these bindings can be customized. For details, visit “Windows Communication Foundation Bindings” at MSDN.

The WCF ships with the following pre-configured bindings:

Binding

Description

basicHttpBinding

This interoperable binding is commonly used as a replacement for earlier Web services based on ASMX (Active Server Methods). It supports Hypertext Transfer Protocol (HTTP) and Hypertext Transfer Protocol over SSL (HTTPS) transport protocols as well as text and Message Transmission Optimization Mechanism (MTOM) encoding methods.

wsHttpBinding

This secure and interoperable binding uses SOAP over HTTP and supports reliability, transactions, and security over the Internet. It supports HTTP and HTTPS transport protocols as well as text and MTOM encoding methods.

wsDualHttpBinding

This interoperable binding is commonly used for duplex service contracts because it supports bidirectional communication.

webHttpBinding

This secure and interoperable binding sends information directly over HTTP or HTTPS without creating a SOAP envelope. It is an efficient choice when SOAP is not required by the client.

wsFederationHttpBinding

This secure and interoperable binding supports federated security. It supports HTTP and HTTPS transport protocols as well as text and MTOM encoding methods.

netTcpBinding

This secure binding is used to send binary-encoded SOAP messages from one WCF computer to another. It uses Transmission Control Protocol (TCP) and includes support for reliability, transactions, and security.

netNamedPipeBinding

This secure binding should be used on a single WCF computer. Binary-encoded SOAP messages are sent over named pipes.

netMsmqBinding

This queued binding is used to send binary-encoded SOAP messages over MSMQ. Communication should occur between two computers.

netPeerTcpBinding

This secure binding is used for peer-to-peer communication over TCP. Communication should occur between two or more computers.

msmqIntegrationBinding

This interoperable binding can be used for existing MSMQ applications that use COM and native C++ application programming interfaces (APIs).

basicHttpContextBinding

This binding provides support for HTTP cookies and enables SOAP headers to exchange context.

netTcpContextBinding

This secure binding enables SOAP headers to be used in the exchange of content.

wsHttpContextBinding

This secure and interoperable binding enables SOAP headers to exchange context while also supporting reliability, transactions, and security.

*Table Taken from MCTS 70-503 Windows Communication Foundation By Microsoft Press, Copyright GrandMasters and Microsoft Corporation.

Choosing a Binding for WCF Service may seem confusing, initially, for developers but here is a flow diagram that will help you in selecting binding depending upon your scenario.

clip_image001
Reference: Programming WCF Services by Juwal Lovy- Oreilly

Perhaps the most commonly used in the market are basicHttpBinding and wsHttpBinding which uses SOAP 1.1 and SOAP 1.2 respectively. A good comparison of both these is done by Kurt CLAEYS on his blog. I hope this post cleared the picture in your mind 🙂

Have a Good Day with Services!

Beginning WCF

Windows Communication Foundation (WCF) is an integral part of .NET Framework 3.*. “It provides a unified framework for rapidly building service-oriented applications that makes it easy to build and consume secure, reliable, and transacted Web services. It unifies the capabilities in ASMX, WSE, Remoting, COM+, and MSMQ; therefore developers need to learn only one programming model.” -MSDN

And Today we are going to see a very very basic example of using Windows Communication Foundation(WCF). So let’s begin.

Pre-Requisites:

The first thing you need is .NET framework 3.*, 3.5 SP1 in particular 🙂 which you can download from Microsoft Download Center. Okay, the next thing is IDE. If you don’t have Visual Studio, there are express edition(s) available that are free to download and use. In particular, I’ve just downloaded Visual C# 2008 Express Edition which seems cool 🙂

vcsharpIDE

Get Set Go!
Service

First of all we need to create a Service and for that I’m going to create a new project i.e. Class Library with name RegistrationService as shown below:

projectType

Now we need to add reference of System.ServiceModel which is main dll required for WCF.

reference

Next we need to create a contract of Service i.e. the interface of the service having required attributes as shown below:

[ServiceContract(Namespace="http://adil.com/RegistrationService/2009")]
public interface IRegistrationService
{
[OperationContract]
string RegisterName(string name);
}

Notice that the interface is having ServiceContractAttribute which is mandatory and indicates that an interface defines a service contract in a WCF application. The namespace parameter is optional and is used to define unique namespace to the service and by default its set to http://tempuri.org/. Also notice that OperationContractAttribute is marked on the method(s) need to be exposed to the client.

Next we are going to add a class with name RegistrationService.cs which will implement this interface.

public class  RegistrationService: IRegistrationService
{
public string RegisterName(string name)
{
return string.Format("Registered Name : " + name);
}
}

All right, till this point our service is ready. We have contract to be exposed and we have class implementing that contract. Now we need to have a Host Application (Executable). Every service need to be hosted either on IIS or WinApp or Window Service etc. So, for this example, we will create a Console Application to Host our Registration Service.

serviceHost

Also you need to add System.ServiceModel reference to this host (executable) application as well. The Host application need to define the ABC of WCF which is

  • A-> Address (Address where service will be hosted)
  • B-> Binding (For now, take it as underlying protocol like HTTP, TCP etc)
  • C-> Contract (The interface of the service)

We will create a class Host for hosting this RegistrationService.

public class Host
{
ServiceHost host;
public void StartService()
{
try
{
host = new ServiceHost(typeof(RegistrationService));
host.AddServiceEndpoint(typeof(IRegistrationService),
new BasicHttpBinding(),
"http://localhost:8000/RegistrationService");
host.Open();
Console.WriteLine("Service Started Successfully");
Console.ReadLine();
}
catch (System.Exception exception)
{
Console.WriteLine("Unable to start service n " + exception.Message);
}
}
public void StopService()
{
if (host != null)
host.Close();
}
}

Notice that the line

host.AddServiceEndpoint(typeof(IRegistrationService),
new BasicHttpBinding(),
"http://localhost:8000/RegistrationService");

basically adds an Endpoint where service will be hosted defining the type of contract i.e. IRegistrationService, the underlying protocal i.e. BasicHttpBinding and the Address. Let’s hit F5 and run it.

serviceStarted

That is all for the service.

Client

The client need to have proxy of the service, in general, ABC of the service. For proxy we will copy the contract of the service at the client side and create proxy using ChannelFactory class of WCF. Further the type of contract, Binding and Endpoint Address is passed to ChannelFactory constructor. Consider the code snippet below:

[ServiceContract(Namespace = "http://adil.com/RegistrationService/2009")]
public interface IRegistrationService
{
[OperationContract]
string RegisterName(string name);
}
class Program
{
static void Main(string[] args)
{
IRegistrationService proxy = ChannelFactory.CreateChannel
(new BasicHttpBinding(), new EndpointAddress("http://localhost:8000/RegistrationService"));
Console.WriteLine("nCalling Service...n");
Console.WriteLine(proxy.RegisterName("Adil"));

Console.ReadLine();

}
}

That’s it. Let hit F5,

callingRegService

So we have created a simple client/server application using WCF. Please note that this is very simple example in which both client and server know the address, contract and binding. In real scenario, the service information is exposed to client using WSDL (Web Services description Language).