Posts Tagged ‘POX’

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…