Search This Blog

Loading...

Friday, January 13, 2012

Creating a SOAP/REST – based WCF Service with Custom Binding/Behaviors


Introduction
Ok, basically the title says it all. This post shows a WCF service with a method exposed both as a SOAP-based and REST-based endpoint. For the SOAP-based endpoint I found that there is no binding that satisfy my needs (yep, I am picky!) so I will create a custom binding – explaining what are custom bindings and what is the Channel layer in general.
Also In order to enable logging operations, I will create two custom behaviors – again explaining what are custom behaviors and what is the ServiceModel layer in general.

The code can be downloaded from here: http://www.devlifestyle.net/media/p/1177/download.aspx

So let’s start with the basics. I have an IIS 7 (you can also go with IIS 6 – no Net-based bindings here) hosted WCF service which exposes a single operation. My simple target is to expose this operation on SOAP-based and REST-based endpoints at the same time.
Lets add a twist: for the SOAP-based endpoint I want to use the basicHttpBinding but I want to have the calls authenticated via a username/password however I do not want any on-the-wire security (i.e. encryption) since all calls are inside my intranet and I do not want the overhead of SSL – so in short I want the same basic behavior of good old ASMX services, just using WCF! Now here is the bump: there is no way to do so out of the box in WCF.

Enter Custom Bindings and the Channel layer.

WCF Architecture…the Channel Layer
WCF is made up of two architectural layers: the Service Model and the Channel layers. Service Model is the higher-level abstraction that you deal with most of the time. Most of developers know it by the famous name of “proxy” at the client side (and less commonly by the name of “dispatcher” at the service side). In its most simple form, when acting as the proxy the Service Model converts our “objects” (data contracts) into the proper message format that the Channel layer understands and hands it down to the Channel layer (known commonly as “serialization”); while when acting as the dispatcher the Service Model gets the message from the low level Channel layer and puts it back into the “objectized” format that our code understands (known commonly as “deserialization”).
While we focus on extending the Service Model later when we create the inspectors, let’s focus now on the low-level Channel layer and creating the custom binding.

So, now we know that the Channel layer is the low-level devil that we all hate to get near to. But anytime you deal with WCF bindings, all what you are actually doing is controlling the creation of WCF channel stack! You are just doing it in the higher-level abstraction courtesy of predefined WCF bindings. But what happens when the out of the box bindings are not enough? Simple: you write down your own binding. In order to do so, you must understand some essentials about WCF bindings and the channel stack.
Bindings (simply) produce a set of ordered BindingElement objects at runtime depending on the type of binding you chose. These binding elements form the entire channel stack (thus the Channel layer). Memorizing all the available BindingElements is difficult unless writing custom bindings (and at times custom BindingElements) is your daily work. Luckily this is not my case! Unluckily though, everytime I have to deal with the channel stack I have to pay a visit for MSDN (http://msdn.microsoft.com/en-us/library/aa347793.aspx) to refresh my memory about the BindingElements and what each does.
So once you get yourself familiar with the type of BindingElements, all what is left for you is to create a custom binding that utilizes these elements in a predefined order…and that’s all what you need to know about the (scary) channel stack.
So what is a BindingElement exactly? Simply it’s a processing step. So simply a binding stacks a set of BindingElements on top of each other where a WCF message passes through each step of this stack and “something” happens to the message. For example, a message security binding element provides message encryption (and other stuff), encoding binding element sets message encoding (text, binary, etc…), a transport encoding sets the protocol (TCP, HTTP, HTTPs, etc…)…you got the point.

Custom Binding
So, back to our custom binding implementing. Recall what are my requirements? I just want to have username/password authentication over HTTP and without any SSL. Here is the part of the code that adds up the proper BindingElements:
public override BindingElementCollection CreateBindingElements()
        {
            var res = new BindingElementCollection();

            XmlDictionaryReaderQuotas rqMax = XmlDictionaryReaderQuotas.Max;
            TextMessageEncodingBindingElement textBE = new TextMessageEncodingBindingElement() { MessageVersion = MessageVersion.Soap12WSAddressing10, MaxReadPoolSize = int.MaxValue, MaxWritePoolSize = int.MaxValue };
            rqMax.CopyTo(textBE.ReaderQuotas);
            res.Add(textBE);

            TransportSecurityBindingElement transportSec = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
            transportSec.LocalServiceSettings.MaxClockSkew = new TimeSpan(10, 0, 0); //allow clock difference between client and service
            transportSec.LocalClientSettings.MaxClockSkew = new TimeSpan(10, 0, 0);
           

            res.Add(transportSec);
            res.Add(new AutoSecuredHttpTransportElement() { MaxReceivedMessageSize = int.MaxValue, MaxBufferPoolSize = int.MaxValue, MaxBufferSize = int.MaxValue });
           
            return res;
        }


Once the custom binding is done, I want to expose my SOAP-based endpoint using this new binding instead of the basicHttpBinding. That’s the easy part. Let’s see the service configuration:
First we create a binding extenstion element and supply and custom binding dll:
<extensions>
      <bindingExtensions>
        <add name="customHttpBinding" type="MOHE.CustomHttpBinding.CustomHttpCollectionElement, CustomHttpBinding"/>
      bindingExtensions>
    extensions>

Then we create the binding element itself:
<bindings>
      <customHttpBinding>
        <binding name="myCustomHttpBinding">
        binding>
      customHttpBinding>
    bindings>

Finally, we define our SOAP endpoint using the new binding, as follows:
<services>
      <service name="Service" behaviorConfiguration="ServiceBehavior">
        <endpoint address="soap" binding="customHttpBinding" bindingConfiguration="myCustomHttpBinding" contract="IService" />
      service>
    services>


Needless to say that the binding must also be used at the client side…since now you know what the configuration elements mean you can check the client configuration yourself.

Custom Username/Password Validator
Before wrapping up, while we are in the “customization” mode, lets do one final thing: now that we have a custom binding that supports username/password authentication, lets a create a custom username/password validator and plug that into our service to isolate that authentication logic from the service logic. The code is rather simple:
Public Class UsernameValidator
    Inherits UserNamePasswordValidator

    Public Overrides Sub Validate(ByVal userName As String, ByVal password As String)
        Try
            If userName <> "mohamad" Or password <> "halabi" Then
                Throw New Exception("Unknown Username or Password")
            End If
        Catch ex As IndexOutOfRangeException
            Throw New FaultException("Unknown Username or Password")
        End Try
    End Sub
End Class
Needless to say, I hardcoded my username/password…you will authenticate against your favorite user store; be it SQL, AD, etc…

Again, lets see how to add the custom username/password validator to the WCF config file:
<serviceBehaviors>
        <behavior name="ServiceBehavior">
          <dataContractSerializer maxItemsInObjectGraph="10000000"/>
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="CustomUsernameValidator.UsernameValidator,
CustomUsernameValidator"/>
          serviceCredentials>
        behavior>
      serviceBehaviors>
The “userNameAuthentication” tag is supplied with the dll holding my custom validation logic.

Just in case you’re wondering about the other configurations, here’s a quick look:
--dataContractSerializer: if you want to parse large messages in WCF (http://thedotnethub.blogspot.com/2009/10/passing-large-messages-in-wcf.html) there are some attributes you want to set. One of those is maxItemsInObjectGraph which sets how many objects can be serialized and passed around.
--serviceMetadata: enables metadata publishing which grants access to the wsdl
--serviceDebug: enables exception details to be propagated to callers; handy in development

REST-enabling the service
So, let’s think about this: we have a WCF-SOAP service that is using an HTTP based binding. What SOAP-features are we exactly using here? Besides SOAP envelopes…nothing! We aren’t using message security, we aren’t using addressing, we aren’t using routing, we aren’t using transactions…in short we aren’t using any of the WSE standards. Frankly, SOAP is an overhead here! Why? try passing an array of – say 500 – objects from a SOAP service to a client. Now pass the same exact objects in REST style. You will find that the size of the REST request is at least 50% less than the size of the SOAP request. Now that’s some saving.
Moral of the story: unless you need SOAP (i.e. any of the WSE standards), REST is the way to go. Its reliance on HTTP verbs makes it perfect for interoperability (SOAP also supports interoperability), it supports caching, and makes it a perfect fit for client-side invoking via JavaScript, jQuery, or Ajax. Even if you need encryption, you can still enable SSL over REST-based services (but you cannot implement the fine-grained message level security that SOAP supports).

So, in our example I will enable the same operation to be invoked REST-style returning the result in JSON format. Why JSON? It’s the easiest to be parsed with client-side calls…although not shown here. Why JSON #2? Although it makes you sound cool to say “POX”, I just like Javascript more.

So, lets see our operation:
[OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "/PostPerson", ResponseFormat = WebMessageFormat.Json)]
    List<Person> PostPerson(Person person);
The OperationContract is for exposing the operation SOAP-style…what we seen before. The WebInvoke attribute is what enables REST magic. I will be using the “POST” verb; although I can also use the “PUT” verb but I will follow the analogy that POSTs are for inserts while PUTs are for updates. You also have DELETE and GET.

Simply, in the web.config we publish the same contract via a second binding, called webHttpBinding:
<endpoint address="rest" binding="webHttpBinding" contract="IService" />

Now there’s one important point to highlight here: in this example, I am using the webHttpBinding with the REST starter kit dlls (http://msdn.microsoft.com/en-us/netframework/cc950529) to REST-enable WCF. The updated way to do this is using WCF Web API dlls (http://wcf.codeplex.com/wikipage?title=WCF%20HTTP). While I am lazy to update the code, the idea – the concept – behind REST and the method of REST-enabling WCF remains largely the same.

So how do we actually call the REST-enabled operation from the client code? Recall there’s no proxy here, just plain simple HTTP requests. So here is a simple helper method that works with generics to be called from multiple places with different in/out objects.

public static Response Post(string username, string password, RESTService service, string uri, Content content, System.Xml.UniqueId messageId)
{
Response response;
using (HttpClient client = new HttpClient(GetRESTURL(service)))
{
if (string.IsNullOrEmpty(username)) throw new Exception("You must pass username");
if (string.IsNullOrEmpty(password)) throw new Exception("You must pass password");
if (messageId == null) throw new Exception("You must pass messageid");
client.TransportSettings.ConnectionTimeout = new TimeSpan(0, 3, 0);
client.DefaultHeaders.Add("username", username);
client.DefaultHeaders.Add("password", password);
client.DefaultHeaders.Add("clientmachinename", Environment.MachineName);
client.DefaultHeaders.Add("messageid", messageId.ToString());

HttpContent httpContent = HttpContentExtensions.CreateJsonDataContract(content);

using (HttpResponseMessage httpResponse = client.Post(uri, httpContent))
{
if (httpResponse.StatusCode == HttpStatusCode.BadRequest)
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(FaultContract));
FaultContract fault = (FaultContract)ser.ReadObject(httpResponse.Content.ReadAsStream());
throw new WebFaultException(fault, HttpStatusCode.BadRequest);
}
else if (httpResponse.StatusCode == HttpStatusCode.ServiceUnavailable)
throw new Exception("ServiceUnavailable");
else
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Response));
response = (Response)ser.ReadObject(httpResponse.Content.ReadAsStream());

return response;
}
}
}

}


WCF Architecture…the Service Layer
Enough easy stuff! Back to the architecture. So recall, that one of the targets of the example is to have logging feature to log every message in and out of the service. Sure we can do this inside the service itself. But this will be neither a good architecture nor cool enough for a post.
So, how do we create a module that catchs every single message into and out from our service, yet we want to do it as a reusable extension without touching our service?

Enter Custom Behaviors and the Service Layer.

Recall that the Service Layer is called “proxy” at the client side and “dispatcher” at the service side. Its job is simply to serialize and deserialize messages to and from the Channel Later respectively. Both the proxy and the dispatcher give you locations – called extensibility locations – that allow you to inject your own logic to inspect messages at various stages and possibly alter the default execution behavior. You can create this logic to inspect messages, operations, parameters, and you can even change serialization & deserialization behavior.
In our example, I am interested in a “message inspector” at the dispatcher side which simply intercepts messages coming in and returning back (requests & responses), and log them into a database. There is one catch here: I want to use the same inspector to log both SOAP and REST messages. SOAP messages are XML-based while REST messages are JSON based so there are some considerations to be taken.
At the proxy side, I also want to create a “client message inspector” to add some metadata to my SOAP message before it is handed on to the channel stack. (note: for variety of configurations, I will enable the client inspector to the SOAP endpoint only).

Message Inspector
Once a message is received, we need to differentiate if it is a SOAP message or a JSON message. Why? because the way to transform the stream into a string format for logging differs:
object IDispatchMessageInspector.AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, 
System.ServiceModel.IClientChannel channel, 
System.ServiceModel.InstanceContext instanceContext)
{
HttpRequestMessageProperty httpReq = (HttpRequestMessageProperty)
request.Properties[HttpRequestMessageProperty.Name];

if (!httpReq.Headers["Content-Type"].Contains("soap"))
return RESTAfterReceiveRequest(ref request, channel, instanceContext);
else
return SOAPAfterReceiveRequest(ref request, channel, instanceContext);
        }


Similarly, before sending the response back we again want to log it:
void IDispatchMessageInspector.BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
        {
            if (reply.Headers.Action == null)
                RESTBeforeSendReply(ref reply, correlationState);
            else
                SOAPBeforeSendReply(ref reply, correlationState);
        }

There are a lot of details in this inspector, such as reading HTTP headers, implementing authentication for REST calls based on these headers, using Task Parallel Libray (TPL) to log data without delaying moving the message down to the channel stack and up to the dispatch operations, and compressing the message before logging it…these are all enhancements however and should lay themselves clear when you download the code.

Now lets see the configuration to add the message inspector:

<extensions>
      <behaviorExtensions>
        <add name="messageInspector" type="MessageInspector.MessageBehaviorExtensionElement, MessageInspector, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
      behaviorExtensions>
      extensions>

<endpointBehaviors>
        <behavior name="RestBehavior">
          <messageInspector/>
          <webHttp helpEnabled="true" />
        behavior>
        <behavior name="SoapBehavior">
          <messageInspector/>
        behavior>
      endpointBehaviors>
    behaviors>

<services>
      <service name="Service" behaviorConfiguration="ServiceBehavior">
        <endpoint address="rest" binding="webHttpBinding" contract="IService" behaviorConfiguration="RestBehavior" />
        <endpoint address="soap" binding="customHttpBinding" bindingConfiguration="myCustomHttpBinding" contract="IService" behaviorConfiguration="SoapBehavior"/>
      service>
    services>

The inspector is added as a behavior extension…recall this means plugging it in the Service Layer. We then define two endpoint behaviors to add the message inspector to both SOAP and REST endpoints. And finally we update the endpoint definitions so that both endpoints now use the message inspector.

Client Message Inspector

Finally, I also said that I want to add a client inspector at the proxy side to add some metadata to the message. Basically, what I want is simply to log (I know, I have a thing for logging) the name of the machine from where the request is initiated:
object IClientMessageInspector.BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            // Prepare the request message copy to be modified
            MessageBuffer buffer = request.CreateBufferedCopy(int.MaxValue);
            request = buffer.CreateMessage();

            request.Headers.Add(MessageHeader.CreateHeader("MachineName", "http://machinename/CustomHeaders", System.Environment.MachineName));

            return null;
        }
And we then configure our client application to use this inspector for every SOAP message going out:
<extensions>
        <behaviorExtensions>
          <add name="clientMessageInspector" type="ClientMessageInspector.ClientMessageBehaviorExtensionElement, ClientMessageInspector, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
        behaviorExtensions>
extensions>

      <behaviors>
        <endpointBehaviors>
          <behavior name="EndpointBehavior">
            <clientMessageInspector/>
            <dataContractSerializer maxItemsInObjectGraph="10000000"/>
          behavior>
        endpointBehaviors>
      behaviors>

<client>
            <endpoint address="http://localhost/WCFService/Service.svc/soap"
                behaviorConfiguration="EndpointBehavior" binding="customHttpBinding"
                bindingConfiguration="myCustomHttpBinding" contract="SOAPRef.IService"
                name="CustomHttpBinding_IService" />
           
        client>










Tuesday, July 5, 2011

Azure AppFabric, Claims-based access, WIF Recording

Here is my recordings talking about Windows Azure AppFabric, Claims-based access, and Windows Identity Foundation(WIF)...this recording is a part of Devlifestyle June 2011 session held in PSU.
Note that this recording is in Arabic only.









Monday, June 20, 2011

Windows Azure Demo-Based Online Recording

Here is an online recording for my Devlifestyle Online June session about Windows Azure...I present the architecture behind Windows Azure and then dive into demos showing the various services from the Azure Platform













Monday, June 13, 2011

Parallel Task with ASP.NET HttpContext

When using .NET 4.0 Parallel Programming (Check my article) with ASP.NET, you will lose HttpContext once you jump in to another task.
In my case I wanted to get hold of the context from which I wanted to get the current page handler. So I came up with the below code.

HOWEVER, and as you can see this is BIG HOWEVER, although I tried the code and it did work I am not 100% sure about it because the idea of manually setting the context (as you will see in a moment) and messing up with the way threading works gives me the creeps! But anyway I thought I would share it:

Action<object> action = new Action<object>(dostuff);
Task.Factory.StartNew(action, obj);

where:

private void dostuff(object obj)
{
IHttpHandler han = ((HttpContext)obj).CurrentHandler;
//do stuff
}

or you can use delegates:

Task.Factory.StartNew(new Action<object>(
delegate(object objContext)
{
IHttpHandler han = ((HttpContext)objContext).CurrentHandler;
//do stuff
}
)
, obj);

or event better: lambda:

Task.Factory.StartNew(new Action<object>(
objContext =>
{
IHttpHandler han = ((HttpContext)objContext).CurrentHandler;
//do stuff
}
)
, obj);

Ok so it was a short post, and I thought I would spice it up with some code variations :)

Friday, June 3, 2011

Azure Storage Emulator: Process cannot access the file because it is being used by another process

If you are trying to run the services of the azure storage emulator (Blob, Queue, Table) and you ever get this error:
The process cannot access the file because it is being used by another process

Then continue reading...
As you might imagine it happened to me, and I found that the blob service is the one complaining:

I knew something was wrong with the endpoint, from the error message i could tell that most probably the problem was that the endpoint address being used by some other process.
So from the command prompt i ran Network Statistics tool (Netstat) and got the following:


As you can see, i had ports 10001 and 10002 saying "cannot obtain ownership information" but anyway I had no problems with these ports as they are associated with the Queue and Table services respectively and both are started. However, it is clear that port 10000 is occupied by BitTorrent on my machine (yes you caught me!) so that is why the Blob service could not be started.
Once I stopped BitTorrent I could start the Blob service.

Note: you would have another option which would be changing the ports the emulator use for the storage services. You could do that by navigating to:
C:\Program Files\Windows Azure SDK\v1.4\bin\devstore
(replace 1.4 with your SDK version) and openning DSService.exe.config. From there you could change the configuration and make your services listen to another ports.


Thursday, May 5, 2011

Utilizing WCF Power for Integrations - Devlifestyle May 2011 Session Demo

So, after a (very?) long time without a post (absolutely hectic period), I am back with a WCF post for WCF lovers out there...here are the session materials for a session I did for Devlifestyle (actually the session is due in 5 hours as of this writing)
http://www.devlifestyle.net/media/p/1173/download.aspx

The demo shows various WCF configurations using basic, net, and MSMQ bindings. The demo also tackles WCF custom bindings and shows a custom http-based binding created as well as custom extensions (behaviors)....ENJOY!

Tuesday, December 21, 2010

Second Riyadh Community Summit

I will speaking at the second Riyadh Community Summit, Thursday 23 December. Session will be about RESTful services tackling the popular SOAP vs. REST debate.
Hopefuly I will be able to post the video recordings of the event.
Full agenda here:

http://www.devlifestyle.net/rcs2/

Thursday, December 16, 2010

SharePoint 2010: Passing data from Workflow to Task Form

Implementing a state machine workflow project on a SharePoint 2010 Document Library (i will do a full post soon), I faced a situation where I wanted to pass data from the workflow instance to the ASP.NET task edit form.

Before I have many times done the reverse: passing data from the Task Edit forms to the workflow instance by defining custom content types and referencing their fields inside my workflow using the ExtendedProperties Hashtable.

So now I thought I could do the same to pass data into my task form: from inside the wf instance I used the ExtendedProperties hashtable to set a value to my field when creating the task as follows:
task.ExtendedProperties["myItemGUID"] = ".....";
Now in the task form i tried to access the same property using:
mytaskListItem.Properties["myItemGUID"] but it is always null.

I then "watched" over the Xml property of mytaskListItem and found that "myItemGUID" was actually populated inside as follows:
ows_ExtendedProperties = 'ows_myItemGUID=......'
Further if I use mytaskListItem.GetFormattedValue("ows_ExtendedProperties") i can get the same value "ows_myItemGUID=..." where parsing will be easier than having to parse the full Xml value.

Now of course this will make me move on for now, but this is hardly an optimum solution. Till now I do not know why I could not "strongly-type get" the value of the field the same way I can do when getting data from the wf instance...Needless to say, SharePoint is not exactly my thing (so far!)...workflows are :) so I could be missing some SharePoint related stuff...anyway will get back to this once I finish the business process...

Sunday, November 14, 2010

WCF MSMQ Transactions Explained – Part1

Introduction

Before starting, I advise you to read my detailed article about .NET transactions and WCF implementation for more in depth knowledge about how transactions work. However, you can still go through this post directly to get the required knowledge about WCF MSMQ transactions.
When working with MSMQ and WCF, you have two options for bindings: NetMsmqBinding and MsmqIntegrationBinding.
  • The NetMsmqBinding is intended to be used when both the client and service are WCF and communicate over the assigned endpoints.
  • MsmqIntegrationBinding on the other hand can be used with already-written native MSMQ applications that use MSMQ COM or the System.Messaging APIs.
I will be using the NetMsmqBinding.

Getting to the point…

I am going to show you the code directly explaining the concepts as we go.

The service contract of my service application is defined below:

[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void GetData(int value)
{
System.Diagnostics.EventLog.WriteEntry("WCF", value.ToString());
Transaction.Current.Rollback();
}

TransactionScopeRequired indicates that my operation must be enlisted within a transaction and TransactionAutoComplete indicates that the transaction will be committed automatically once the operation finishes.

In the operation body I simply print something to the event viewer and interestingly manually roll back the transaction. Why did I do that? This will become clear later.

The relevant service configuration is where the magic happens. It is shown below:

<services>
<service name="Service" behaviorConfiguration="ServiceBehavior">
<endpoint address="net.msmq://localhost/private/MSMQService/Service.svc" binding="netMsmqBinding" contract="IService" bindingConfiguration="MSMQ"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netMsmqBinding>
<binding name="MSMQ" maxRetryCycles="1" receiveRetryCount="1" retryCycleDelay="00:00:20" deadLetterQueue="System" receiveErrorHandling="Move" exactlyOnce="true" durable="true" timeToLive="1.00:00:00">
<security mode="None"></security>
</binding>
</netMsmqBinding>
</bindings>

First things first; I am using the netMsmqBinding and have set the address to a local TRANSACTIONAL private queue with the same name as my service application (check this post on how to set up WCF-MSMQ application on IIS 7). In this example, both the client and the service are hosted on the same machine so only the private queue will be used.

Now on to the binding configuration:

  • exactlyOnce: when set to true means that transaction is enabled and the queue must be marked as “Transactional” on creation. This means that each message is guaranteed to be delivered one and only one time and a batch of messages are delivered in order.
  • durable: indicates that messages are never lost. Messages are persisted to the disk so if the MSMQ service is restarted messages are preserved.
  • receiveRetryCount: this setting indicates how many times the service will try to receive and process the message
  • retryCycleDelay: specifies the time between retry counts. For example if receiveRetryCount is set to 2 and retryCycleDelay is set to 20 seconds, then the service will try to receive and process the message total of 2 times within an interval of 20 seconds between each try.
  • maxRetryCycles: the number of cycles the retryCycleDelay and receiveRetryCount are run. For example if maxRetryCycles is set to 2, receiveRetryCount is set to 2, and retryCycleDelay is set to 20 seconds then the service will try to receive and process the message 2 times within and interval of 20 seconds and the whole cycle will be repeated 2 times.
  • timeToLive: Indicates the maximum amount of time a message can live in the queue waiting to be delivered to the service. This value supersedes all retry logic; if the TTL is less that the total time the cycle is configured to process then the cycle terminates once the TTL is reached . The default value is 1 day.
So what happens if the cycle fails? One of two things depending on the reason of failure:

  • If the failure is caused by the fact that the message cannot be delivered to the service, then the message will be placed in a transactional dead-letter queue. Setting deadLetterQueue specifies that the system dead letter queue will be used. A better idea would be to use a custom dead letter queue in order not to mix messages from different services in the same system dead letter queue. This is done by selecting “Custom” value for the deadLetterQueue setting and then specifying the name of this custom queue using setting customDeadLetterQueue.
  • If the message is delivered to the service but the transaction fails while processing, then the message will be considered “poisoned” and setting receiveErrorHandling specifies what to do with the message. “Move” means putting the message in a special automatically created queue called “poison”. Other values for the receiveErrorHandling are:
    • Fault: sends a fault to the listener that caused the ServiceHost to fault. The message must be removed from the application queue by some external mechanism before the application can continue to process messages from the queue
    • Drop: drops the poison message and the message is never delivered to the application
    • Reject: MSMQ will send a negative acknowledgement back to the sending queue that the application cannot receive the message. The message is placed in the sending queue dead-letter queue.
So all in all I have configured my service to try to receive and process the message 1 time, wait 20 seconds and try to receive again. This ends the 1 cycle I have configured. If after this the message still cannot be received or processed then I want to either store my message in the system dead letter queue or store it in a poison queue depending on the reason of failure (error in delivery or error in processing – respectively).

In my operation code now you will understand why I did manually roll back my transaction. I am simulating the required conditions to fail message processing and placing the message in the poison queue.

Now create a console client application and add a service reference to the service. Then use the below code to invoke the service:

using (TransactionScope sc = new TransactionScope(TransactionScopeOption.Required))
{
proxy.GetData(1);
sc.Complete();
}

I am enlisting the client in a transaction and I send the message to the private queue. It is important to note that the transactions enlisted at the client and the service are not related. The client transaction ends once the message is delivered to the queue; then the service transaction is in play trying to deliver the message from the queue to the service.

Run the example and examine the complete process:

First: The client sends a message to the private queue. DTC is used internally to accomplish this. You can see the stats of the DTC by examining the Local DTC Transaction Statistics from the Component Services on Windows 7. See below:


The client transaction ends here. If the transaction fails sending the message to the queue, the client will be notified and the transaction will roll back. This will be most helpful when the client is sending a group of messages to the queue and it’s important for all the messages to be either delivered as a batch or none is delivered.

Second, the service picks the message from the main queue. The below image shows when the message first arrives at the queue:


The WCF service operation starts executing and then the transaction is rolled back. The message is placed back in the retry queue as shown below:


After 20 seconds the message is delivered again to the WCF service; yet the transaction is rolled back again. This time the message is placed in the poison queue for good as shown below:


What happens for messages placed in the dead-letter queue or the poison queue? Custom application logic must be written to compensate these messages and do “something” about them.
Note that messages would have ended in the Transactional Dead-letter system queue had the message been failed to be delivered as opposed to fail during processing. The system queue is shown below:


What will happen in case of Public/Private queues?

Part 2 of this series will show the structure where the client and service are on separate machines (also MSMQ will be on a Windows Server Cluster…). But in a nutshell, in this case the following will happen:

The client WCF endpoint will be configured to send the message to the destination queue on the service machine (actually in case of MSMQ cluster it will send to a virtual IP, but this is a separate issue to be discussed in part 2), however, since the service is on another machine then the client application will silently deliver the message to an automatically created private outgoing queue. This queue will then try to deliver the message to the real destination queue.

The client will engage in one DTC transaction to deliver the message to the temp outgoing queue. The service will then be engaged in a separate DTC transaction to retrieve the message from the destination queue.

The same retry rules and poison/dead-letter message discussions mentioned above still apply.

But isn’t DTC heavy on Performance? Do I really need it?

Sure! And it depends.

Again if you follow the link (at the start) of my transactions article, you know that DTC implements a two-phase commit protocol and that definitely has a performance hit. However, whether you can live with or without transactions is governed by the scenario.

Let’s start with the obvious: in the scenario I presented above DTC is not required! The client needed the transactions “only” to commit sending messages to the queue. The service also needed the transaction “only” to commit receiving messages from the queue. So why did the DTC kick in? Simply because – as of this writing – it seems that the netMsmqBinding is configured to use DTC and there seems to be no way of changing that. But I do need transactions you might say, only not DTC; so what is the alternative? The answer would be MSMQ Internal Transactions. This is a light weight transaction implemented internally for MSMQ that does not need DTC. However, this seems to be not supported when using WCF netMsmqbinding; the only way you can use it is to use the System.Messaging APIs to send and receive from MSMQ.

To use the Internal Transaction you would use classes MessageQueue and MessageQueueTransaction from the System.Messaging API to send and receive messages within a transaction.

So why would I bother going for DTC (and netMsmqBinding) when I can go with internal transactions? Well because netMsmqBinding rocks…just kidding! Consider this scenario: when you receive the message at the service you want to use it to perform an update on a SQL server DB. If the update fails however, you want to place the message back in the queue so that you can fix the problem and retry again. Meaning that you want to enlist the receiving of the message and the DB update in a single atomic transaction: either all succeeds or the transaction rolls back and the message is back safe in the queue. In this case DTC is a must because the transaction is spanning two resource managers (again for more details see link at the start).

Note: I could not find any official say from MS that the netMsmqBinding does not support MSMQ internal transactions. I rather tested it myself and it did work.