Archive for October, 2008

WCF Web Model – POX/JSON Support

Posted: October 28, 2008 in .NET, WCF
Tags: , , , ,

For the past few days I was studying the details of the Web Programming Model of WCF.This feature enables WCF services to be called using simple HTTP requests i.e. without the messages wrapped in SOAP format.The messages can be POX(Plain Old XML) or JSON(JavaScript Object Notation).So the client for this kind of services does not need any specific proxy or WSDL.But how client is made aware of the service metadata is still a question to me.However parking that question aside for now let us get into, step by step how this feature is built using the extensibility points provided by WCF infrastructure.

Client Side

Let us first think of what the client is going to send to the service?Just a HTTP request.The method may be GET or POST.Suppose I am trying to access a service operation Add(int i,int j) .The client code in C# will be something like as shown below:

HttpWebRequest  request =  HttpWebRequest.Create(http://localhost:9001/Test/Add/?i=1&j=1) as HttpWebRequest;
request.AuthenticationLevel = System.Net.Security.AuthenticationLevel.None;
request.Method = “GET”;
request.ContentType = “text/xml”;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();

Before we proceed into the details of the service side let me note the down the questions that initially occurred to my mind.

  1. How the HTTP message will read and parsed in the service side?
  2. How from the URI the name of the method Add will be read and request will be dispatched to the correct operation?
  3. How the parameters will be parsed from the querystring?

In the subsequent sections I will try to answer these questions.

Service Side

Binding

In the server side there should be some program listening to a particular socket waiting for bytes to arrive.This is the job of the ChannelListener as I had discussed in one of my earlier posts titled ServiceHost & Channels.This ChannelListener should be able to read raw bytes and create channels to process the HTTP requests.But the channels are created by the specified binding.So we need a binding which can handle HTTP Transport and encode/decode POX and JSON messages.For this we have a binding provided by WCF called WebHttpBinding.This binding is primarily composed of HttpTransportBindingElement and WebMessageEncodingBindingElement.This WebMessageEncodingBindingElement inherits from TextMessageEncodingBindingElement and is a composite encoder which can handle plain text,XML,JSON and raw binary data.

So to make WCF Services available for basic HTTP clients we need to expose an endpoint with WebHttpBinding.

Endpoint

Now we have an service endpoint ,message is processed by channels created by WebHttpBinding and routed to the EndpointDispatcher via the ChannelDispatcher.But who reads the URI of the message and decides which service operation this is intended for?How the parameters values are parsed from the querystring?

The parsing of URI and determination of operation is done by public string SelectOperation( ref Message message ) method of a  WebHttpDispatchOperationSelector class implementing the IDispatchOperationSelector interface.

The querystring parsing and parameter processing is done by a dispatch formatter class implementing the IDispatchFormatter interface with methods:

void DeserializeRequest(Message message, object[] parameters)
Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)

How these two classes gets attached to the DispatchRuntime of the EndpointDispatcher.WCF allows to modify the behaviour of an endpoint using endpoint behaviours.The classes intending to so needs to implement the IEndpointBehavior interface.WCF provides WebHttpBehavior class for modifying the endpoint behavior to suit the needs of POX/JSON messages.This class has three methods to get the operation selector and formatters.

protected virtual WebHttpDispatchOperationSelector GetOperationSelector(ServiceEndpoint endpoint)
protected virtual IDispatchMessageFormatter GetReplyDispatchFormatter(OperationDescription operationDescription,ServiceEndpoint endpoint)
protected virtual IDispatchMessageFormatter GetRequestDispatchFormatter(OperationDescription operationDescription,ServiceEndpoint endpoint)

In the operation ApplyDispatchBehavior these components are added to the DispatchRuntime

public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher)
{

      endpointDispatcher.DispatchRuntime.OperationSelector = …
}

How the WebHttpBehavior is added to the ServiceEndPoint??

Host

WCF provides a class called WebServiceHost to host services for web based clients send POX/JSON messages.This class inherits from the ServiceHost class.This class makes sure that WebHttpBinding is properly used and attaches the WebHttpBehavior to the ServiceEndPoint.

Now the last things that I need to mention is the two Operation Behavior attributes that need to be applied to the Service operations:WebInvokeAttribute and WebGetAttribute.These two attributes are passive operation behavior and adds some additional metadata to the operation description.This information is used by the WebHttpBehavior for processing.WebGetAttribute allows only HTTP GET requests whereas WebInvokeAttribute has one Method parameter.This parameter is set to POST by default and can accept GET and PUT as well.

The method signature of the Service operation will look something like:

[OperationContract]
[WebGet/WebInvoke]
int Add(int x, int y);

We have covered almost the entire flow of POX/JSON messages from client to service.

In the next post I will discuss how to extend this framework and plug in custom functionalities…

Advertisements

WCF Proxy and Channels

Posted: October 12, 2008 in .NET, WCF
Tags: ,

In my last post I had discussed about what is happening in the channels at the service end and how they are related to the ServiceHost class that we normally use.In this post we will take a look at what is happening at the client side channels.In the server side we have channel listeners listening for incoming requests similarly at the client end we have channel factories to create the channels as the client initiates the connection.For sake of simplicity we will not consider the duplex channels for now.In short we need to the following to send messages to the service from client:

  1. Create a binding
  2. Create a ChannelFactory.
  3. Create a Channel
  4. Send/Receive messages over that channel.

Now let us take a closer look into the class ChannelFactory.The class definition : public class ChannelFactory<TChannel> : ChannelFactory, IChannelFactory<TChannel>, IChannelFactory, ICommunicationObject where TChannel is either IOutputChannel or IRequestChannel type.

  1. Create a ChannelFactory by it’s constructor .At this point State of the factory is Created.
  2. We need to Open the ChannelFactory via it’s Open() method.At this point State of the factory is Opened.
  3. Create a channel by calling ChannelFactory.CreateChannel() method.At this point State of the channel is Created.CreateChannel will return an instance of type IRequestChannel.
  4. Open the channel by calling IRequestChannel.Open() method.At this point State of the channel is Opened.
  5. Invoke IRequestChannel.Request() method to send the message to the desired endpoint and receive the reply back.
  6. Close the channel and the channel factory respectively after use.

But we do not do all this when we generate a proxy using svcutil or .NET IDE “Add Service Reference” menu option.So these tools provides us with a higher level abstraction with the above mentioned steps taken care under the hood.

If you take a look at the class generated in the Reference.cs file in the ServiceReference folder you will find that the custom proxy class inherits a class ClientBase<TChannel> : ICommunicationObject, IDisposable where TChannel : class.This class encapsulates the functionality of channel factory and channels.This class exposes the ChannelFactory and Channel via ChannelFactory and InnerChannel properties.Prior to invoking the Service methods we need to open the proxy via it’s Open() method.

This is the sequence in which ClientBase,ChannelFactory and InnerChannel works:

  1. When the proxy is instantiated via the ClientBase constructor the ChannelFactory is in “Created” state.
  2. When the Open method of the proxy or ClientBase is called then the ChannelFactory is “Opened”.
  3. After that the ClientBase/Proxy state is transitioned to “Opened”.
  4. Then the InnerChannel is “Opened”.
  5. Similarly when Close() method of the proxy is invoked then things happen in reverse order i.e. InnerChannel is closed,then Proxy/ClientBase finally followed by ChannelFactory.

Service Host & Channels

Posted: October 2, 2008 in .NET, WCF

In this post I will list down my understanding of the WCF Channel Model and how it is related to the ServiceHost class.This is the class we frequently use to host our services in a console program/windows service.First quickly let us take a look into the base class of the ServiceHost.It is an abstract class called ServiceHostBase which in turn derives from the CommunicationObject.CommunicationObject implements the ICommunicationObject interface which is the contract for providing all the state machine functionality in WCF.State machine receives various signals/events and moves from one state to another.For example a TCP socket can be a very good case of a state machine.

The possible states are defined by the CommunicationState enumeration are

  1. Created  – Indicates the object is instantiated but not yet opened.
  2. Opening – Object is moving from Created to Opened
  3. Opened  – Object is successfully opened
  4. Closing   – Object is about to close
  5. Closed    – Object is closed
  6. Faulted   – Object has encountered an error and is not usable any more.

The state transition is done by the methods Open,Close & Abort and following events are raised

  1. Opening
  2. Opened
  3. Closing
  4. Closed
  5. Faulted

We can add some event handlers and check this out easily using a code as shown below:

host = new ServiceHost(typeof(SampleHost.TestService));
host.Opening += new EventHandler(host_Opening);
host.Opened += new EventHandler(host_Opened);
host.Closed += new EventHandler(host_Closed);
host.Closing += new EventHandler(host_Closing);
host.Faulted += new EventHandler(host_Faulted);

Now with fair understanding of CommunicationObject let us take look into what is happening in the Channel Layer.WCF channels are layers stacked over one another.Each channel provides some kind of abstraction to the channels above.The lowest layer is the Transport Channel which receives that raw bytes from the network sockets and convert them into an instance of the Message object.This Message object is passed to the channels above which are known as the Protocol Channels.These channels perform various tasks related encoding,formatting etc. and alters the Message.

At present we will concentrate only the channels in the server side i.e. the service channels.The two important interface in this respect are the IChannel and IChannelListener.Channel Listeners listen to the network or the underlying channels for messages and creates a channel upon receiving a message.The custom channel listeners needs to inherit from ChannelListenerBase class which implements the IChannelListener interface.ChannelListenerBase inherits CommunicationObject and implements the functionality of a state machine like the ServiceHost.ChannelListenerBase<TChannel> provides the AcceptChannel method which waits for and accepts an incoming channel.

Now we have understood that there is a series of channels processing the incoming messages.But how they are ultimately send to the appropriate operation in the service type?How they are related to the ServiceHost hosting the service?

Now we have to take a look at the dispatchers in the service model.

  1. ChannelDispatchers – ChannelDispatchers (ChannelDispatcher) accept incoming messages.Each ChannelDispatcher is associated with exactly one ChannelListener.ChannelListener receives the message as mentioned and the message is processed by channels.After the message is processed by the associated channels then ChannelDispatcher passes it on to a suitable EndpointDispatcher
  2. EndPointDispatchers – EndPointDispatchers are responsible for taking a message out of the channel stack and passing them to the right service operation.One of the key element of the EndpointDispatcher is the DispatchRuntime.DispatchRuntime provides facility to alter default service behaviour using custom classes to provide enhanced functionality related to Service Instancing,Error Handling,Security etc. The extended behaviour using DispatchRuntime are all applicable at the service level i.e. for all the operations of the service.DispatchRuntime contains the DispatchOperation which is responsible for routing the message to the right operation and providing customizations facilities applicable at the operation level.

Now the last piece of the puzzle is how they are related to the ServiceHost.

When we call ServiceHost.Open the following things happen:

  1. ChannelDispatchers are created and opened.There will be one ChannelDispatcher per URI using which service can be accessed including the endpoints exposing the metadata.
  2. Listeners associated with each ChannelDispatcher is created and opened.They wait to accept the incoming channels.

Similarly when ServiceHost.Close is called first the Listeners are closed and then the associated Dispatchers.