The Inquisitive Coder – Davy Brion's Blog

Trying to walk that thin line between intelligence and ignorance

Archive for the 'Request/Response Service Layer' Category

Introducing: The Agatha Project

Posted by Davy Brion on 19th November 2009

As i mentioned earlier in some of the comments, i’ve received permission from my employer (Item Solutions) to release our Request/Response Service Layer implementation in a new open source library named Agatha.

If you’re interested in trying it out, be sure to download it because i’ve already made a 1.0 beta 1 release available. Why 1.0 already? Well, because we have been using it in production for over a year now, so it’s definitely ready for serious usage already. The only thing that kept me from releasing an official 1.0 version already is that i want to add some small examples in the project: a service layer with 3 different clients (synchronous, asynchronous through Silverlight, and asynchronous through a regular .NET application). The example will be very small, basically just a hello world example but it should be enough to get you going very quickly.

The other thing that is still missing is an abstraction of the logging framework that is used. It’s currently still using log4net directly but that’s going to change soon. The IOC container usage has already been changed so it doesn’t directly depend on Castle Windsor anymore, and it should be very easy to plug in your preferred IOC container. Configuration of the library should be very easy as well, and if you look at the source code you’ll notice pretty quickly how easy it can be done. I do plan to make it even easier to configure the thing though. Unfortunately, you still need your typical WCF configuration although i’m going to try to reduce that as much as possible in a future version.

Also, if you look at the source code you’ll notice that there are no tests included. I do have tests for it, but i’ve chosen not to include them in this library since i really want to cover most of it with QuickNet. Regular unit tests will only be written for stuff that really doesn’t benefit from using QuickNet.

You’re obviously more than welcome to contribute to this project, though i hope you understand that i won’t just give anyone commit access right away (apart from the 2 people that already have access at this point) and that you sort of need to earn it. I will happily accept and apply patches, as long as they don’t break backwards compatibility, which is obviously pretty important considering the fact that we have quite a few projects that already depend on this. You’re obviously also welcome to join the mailinglist where both the usage and the further development of the library can be discussed.

Again, thanks to Item Solutions for allowing me to use the Request/Response Service Layer in a commercial project back when it was still merely a proof of concept… we certainly did run into a few issues with it at first, but all of that has been straightened out and it’s been working great for us ever since. Hopefully, you’ll now get to enjoy the same benefits it’s given us :)

Posted in Request/Response Service Layer, agatha | 4 Comments »

Request/Response Service Layer: Conclusions

Posted by Davy Brion on 16th November 2009

Note: This post is part of a series. Be sure to read the introduction here.

Now that you’ve learned everything there is to know about the Request/Response Service Layer (RRSL), i’d like to repeat the benefits of the RRSL that i stated in a previous post:

  • Since we only have one service contract with one service operation, we don’t need to spend time thinking about how to design and implement our service contracts and our operations. After all, every operation that the service layer must support is a specific request type that can be added, together with its requesthandler.
  • We can keep our operations as fine-grained as we want (which increases reusability and overall flexibility), without having to pay the cost for chatty network communication by batching multiple requests per roundtrip as much as possible in a transparent manner.
  • The actual implementation of our service is very minimal. It’s just a small class which resolves the appropriate requesthandler through the IOC container, based on the type of the incoming request. It then delegates to the requesthandler by passing the request to it, and it returns the response to the client. We can simply add ‘operations’ by adding request types and requesthandlers to our assemblies… everything gets registered automatically when the application starts up
  • We avoid repetitive code for cross cutting concerns by putting it in a base requesthandler class that the other ones inherit from. That kind of code now only occurs once, and we can plug in custom code at any point of the execution by simply using the Template Method pattern.
  • The implementation of our requesthandlers doesn’t contain any code that doesn’t have to be there. Each requesthandler simply implements the Handle method to handle the incoming request, and can do as it pleases to fulfill the request. All dependencies are injected automatically by the IOC container. It’s usually nothing more than using the dependencies to execute the necessary business logic and then returning a response-derived object.
  • Since we only have one service, we only need one client proxy which never needs to be updated (technically, we have 2: one which is entirely asynch and mostly used in Silverlight clients, and one which is strictly synchronous and is mostly used by ASP.NET applications and Windows Services or command line tools.
  • This single client proxy implementation can make sure that underlying WCF resources are utilized as efficiently as possible and cleaned up properly throughout the client application(s).
  • The client proxy is easy to stub during unit tests which increases the testability of our client side code.
  • Very little configuration. We only have to configure one client-side endpoint, and one server-side endpoint. That’s it.
  • All of this is very easy to put in some kind of reusable library. Our applications simply reference the library, inherit from the base requesthandler types, make sure everything is registered properly upon application startup, add a couple of lines of XML and we can start the development of our service layer without any friction.

One of the goals of this series was to convince people that those benefits are indeed real. I really wanted to prove each and every one of those listed benefits and i hope that i succeeded at that. I also hope you realized how cleanly we can write our client code, as well as our actual service layer logic. I definitely recommend that you consider this entire approach for your future applications. While i won’t claim that it is the best solution for every project, it’s definitely one that can give you quite a few tremendous benefits.

Since i really don’t have much more to say about this entire topic, i’m just going to leave it at that :)

Posted in Request/Response Service Layer | 17 Comments »

Request/Response Service Layer: Testing Asynchronous Client-Side Usage

Posted by Davy Brion on 16th November 2009

Note: This post is part of a series. Be sure to read the introduction here.

Writing automated tests for asynchronous operations in general can be pretty cumbersome. In the case of the Request/Response Service Layer (RRSL), we basically need to be able to verify that our client code is sending the correct requests, and see how it deals with prepared responses that we send back to the client code through the provided callback. This actually makes it very easy to test the asynchronous usage of the RRSL. We basically just need a different implementation of the IAsyncRequestDispatcher interface, which stores the added requests so we can inspect them later on, and which simply holds a reference to the ResponseReceiver and gives us a specific way to trigger the execution of the ResponseReceiver’s logic to call the correct callback from the client code. I’ll show the AsyncRequestDispatcherStub class later on, but first we’ll take a look at its interface to see which extra methods it provides:

    public interface IAsyncRequestDispatcherStub : IAsyncRequestDispatcher

    {

        void SetResponsesToReturn(params Response[] responses);

        void AddResponseToReturn(Response response, string key);

        bool HasRequest<TRequest>() where TRequest : Request;

        bool HasRequest<TRequest>(string key) where TRequest : Request;

        TRequest GetRequest<TRequest>() where TRequest : Request;

        TRequest GetRequest<TRequest>(string key) where TRequest : Request;

        void ClearRequests();

        void ReturnResponses();

    }

Note that this interface doesn’t really exist… it’s just shown here to give you a clear view on what specific testing-related functionality the AsyncRequestDispatcherStub offers on top of the regular AsyncRequestDispatcher.

As you can see, we have two methods to add some prepared responses which will be returned to the client code once we call the ReturnResponses method in our test. We also have some methods to inspect the requests that were added by the client code.

And here’s the actual code of the AsyncRequestDispatcherStub class:

    public class AsyncRequestDispatcherStub : Disposable, IAsyncRequestDispatcher

    {

        private readonly Dictionary<Type, string> unkeyedTypesToAutoKey;

        private readonly Dictionary<string, Request> requests;

        private readonly Dictionary<string, int> responseKeyToIndexPosition;

        private readonly List<Response> responsesToReturn;

        private ResponseReceiver responseReceiver;

 

        public AsyncRequestDispatcherStub()

        {

            unkeyedTypesToAutoKey = new Dictionary<Type, string>();

            requests = new Dictionary<string, Request>();

            responseKeyToIndexPosition = new Dictionary<string, int>();

            responsesToReturn = new List<Response>();

        }

 

        public void SetResponsesToReturn(params Response[] responses)

        {

            responsesToReturn.Clear();

            responsesToReturn.AddRange(responses);

        }

 

        public void AddResponseToReturn(Response response, string key)

        {

            responsesToReturn.Add(response);

            responseKeyToIndexPosition.Add(key, responsesToReturn.Count - 1);

        }

 

        public bool HasRequest<TRequest>() where TRequest : Request

        {

            return unkeyedTypesToAutoKey.ContainsKey(typeof(TRequest));

        }

 

        public bool HasRequest<TRequest>(string key) where TRequest : Request

        {

            return requests.ContainsKey(key) && (requests[key] is TRequest);

        }

 

        public TRequest GetRequest<TRequest>() where TRequest : Request

        {

            var autoKey = unkeyedTypesToAutoKey[typeof(TRequest)];

            return (TRequest)requests[autoKey];

        }

 

        public TRequest GetRequest<TRequest>(string key) where TRequest : Request

        {

            return (TRequest)requests[key];

        }

 

        public void ClearRequests()

        {

            unkeyedTypesToAutoKey.Clear();

            requests.Clear();

        }

 

        public void Add(Request request)

        {

            var autoKey = Guid.NewGuid().ToString();

            unkeyedTypesToAutoKey.Add(request.GetType(), autoKey);

            requests.Add(autoKey, request);

        }

 

        public void Add(params Request[] requestsToAdd)

        {

            if (requestsToAdd != null)

            {

                foreach (var request in requestsToAdd)

                {

                    Add(request);

                }

            }

        }

 

        public void Add(string key, Request request)

        {

            requests.Add(key, request);

        }

 

        public void ProcessRequests(Action<ReceivedResponses> receivedResponsesDelegate, Action<ExceptionInfo> exceptionOccurredDelegate)

        {

            ProcessRequests(new ResponseReceiver(receivedResponsesDelegate, exceptionOccurredDelegate, responseKeyToIndexPosition));

        }

 

        public void ProcessRequests(Action<ReceivedResponses> receivedResponsesDelegate, Action<ExceptionInfo, ExceptionType> exceptionAndTypeOccurredDelegate)

        {

            ProcessRequests(new ResponseReceiver(receivedResponsesDelegate, exceptionAndTypeOccurredDelegate, responseKeyToIndexPosition));

        }

 

        private void ProcessRequests(ResponseReceiver responseReceiver)

        {

            this.responseReceiver = responseReceiver;

        }

 

        public void ReturnResponses()

        {

            responseReceiver.ReceiveResponses(new ProcessRequestsAsyncCompletedArgs(new[] { responsesToReturn.ToArray() }, null, false, null));

        }

 

        public void Clear()

        {

            // has to be an empty implementation to be able to inspect the added requests

        }

 

        protected override void DisposeManagedResources()

        {

        }

    }

All of this is (once again) very straightforward and we can now very easily verify that our client code is using the RRSL correctly.

Since our client code always receives an IAsyncRequestDispatcher instance through an IAsyncRequestDispatcherFactory, we’ll need a different implementation of that factory to be used during our tests:

    public class AsyncRequestDispatcherFactoryStub : IAsyncRequestDispatcherFactory

    {

        private readonly AsyncRequestDispatcherStub asyncRequestDispatcherStub;

 

        public AsyncRequestDispatcherFactoryStub(AsyncRequestDispatcherStub asyncRequestDispatcherStub)

        {

            this.asyncRequestDispatcherStub = asyncRequestDispatcherStub;

        }

 

        public IAsyncRequestDispatcher CreateAsyncRequestDispatcher()

        {

            return asyncRequestDispatcherStub;

        }

    }

And that’s all folks.

Posted in Request/Response Service Layer | 1 Comment »

Request/Response Service Layer: Asynchronous Client-Side Usage

Posted by Davy Brion on 15th November 2009

Note: This post is part of a series. Be sure to read the introduction here.

First of all, i would like to mention that i am by no means an expert on WCF and asynchronous operations, so it is quite possible that some of the things in this post could be done easier by someone who knows more about it. Most of the code in this post wasn’t written by me either, but by my co-worker Tom Ceulemans (who unfortunately doesn’t have a blog that i can link to). What you’ll see in this post does work and it actually works very well. But as i said, there very well might be room for some nice improvements here. Anyways, let’s get to it.

As you know by now, our Service Contract for the Request/Response Service Layer (RRSL) looks like this:

    [ServiceContract]

    public interface IWcfRequestProcessor

    {

        [OperationContract(Name = "ProcessRequests")]

        [ServiceKnownType("GetKnownTypes", typeof(KnownTypeProvider))]

        Response[] Process(params Request[] requests);

    }

As you can see, this Service Contract doesn’t define any asynchronous operations. We don’t need to define them in the original contract, but we do have to use an asynchronous version of this Service Contract in the client from which we want to make asynchronous calls to our RRSL. So client-side, we use the following version of the IWcfRequestProcessor Service Contract:

    [ServiceContract(ConfigurationName = "Namespace.Of.Your.IWcfRequestProcessor")]

    public interface IWcfRequestProcessor : IDisposable

    {

        [OperationContract(AsyncPattern = true, Name = "ProcessRequests")]

        [ServiceKnownType("GetAllKnownTypes", typeof(KnownTypeProvider))]

        IAsyncResult BeginProcessRequests(Request[] requests, AsyncCallback callback, object asyncState);

 

        Response[] EndProcessRequests(IAsyncResult result);

 

        void ProcessRequestsAsync(Request[] requests, Action<ProcessRequestsAsyncCompletedArgs> processCompleted);

    }

This one only defines the asynchronous version of the ProcessRequests operation, which in our case is all we need since we use this in our Silverlight applications where you never make synchronous remote calls.

The ProcessRequestsAsyncCompletedArgs class looks like this:

    public class ProcessRequestsAsyncCompletedArgs : System.ComponentModel.AsyncCompletedEventArgs

    {

        private readonly object[] results;

 

        public ProcessRequestsAsyncCompletedArgs(object[] results, Exception exception, bool cancelled, object userState) :

            base(exception, cancelled, userState)

        {

            this.results = results;

        }

 

        public Response[] Result

        {

            get

            {

                RaiseExceptionIfNecessary();

                return ((Response[])(results[0]));

            }

        }

    }

Now we need a proxy class to implement the asynchronous version of the IWcfRequestProcessor interface. The code of the AsyncWcfRequestProcessorProxy code is somewhat low-level because it’s (obviously) dealing with all of the async stuff, so there’s not really a lot of need to get into the details of this piece of code. If you’re implementing your own RRSL, just copy this code and be glad that you didn’t have to write it ;)

    public class AsyncWcfRequestProcessorProxy : ClientBase<IWcfRequestProcessor>, IWcfRequestProcessor

    {

        public event EventHandler<AsyncCompletedEventArgs> OpenCompleted;

 

        public AsyncWcfRequestProcessorProxy() {}

 

        public AsyncWcfRequestProcessorProxy(string endpointConfigurationName, string remoteAddress)

            : base(endpointConfigurationName, remoteAddress) {}

 

        IAsyncResult IWcfRequestProcessor.BeginProcessRequests(Request[] requests, AsyncCallback callback, object asyncState)

        {

            return Channel.BeginProcessRequests(requests, callback, asyncState);

        }

 

        [System.Diagnostics.DebuggerHidden]

        Response[] IWcfRequestProcessor.EndProcessRequests(IAsyncResult result)

        {

            return Channel.EndProcessRequests(result);

        }

 

        private IAsyncResult OnBeginProcessRequests(object[] inValues, AsyncCallback callback, object asyncState)

        {

            var requests = ((Request[])(inValues[0]));

            return ((IWcfRequestProcessor)(this)).BeginProcessRequests(requests, callback, asyncState);

        }

 

        [System.Diagnostics.DebuggerHidden]

        private object[] OnEndProcessRequests(IAsyncResult result)

        {

            Response[] retVal = ((IWcfRequestProcessor)(this)).EndProcessRequests(result);

            return new object[] { retVal };

        }

 

        [System.Diagnostics.DebuggerHidden]

        private void OnProcessRequestsCompleted(object state)

        {

            var e = ((InvokeAsyncCompletedEventArgs)(state));

            ((Action<ProcessRequestsAsyncCompletedArgs>)(e.UserState)).Invoke(new ProcessRequestsAsyncCompletedArgs(e.Results, e.Error, e.Cancelled, e.UserState));

        }

 

        public void ProcessRequestsAsync(Request[] requests, Action<ProcessRequestsAsyncCompletedArgs> processCompleted)

        {

            InvokeAsync(OnBeginProcessRequests, new object[] { requests },

                        OnEndProcessRequests, OnProcessRequestsCompleted, processCompleted);

        }

 

        private IAsyncResult OnBeginOpen(object[] inValues, AsyncCallback callback, object asyncState)

        {

            return ((ICommunicationObject)(this)).BeginOpen(callback, asyncState);

        }

 

        private object[] OnEndOpen(IAsyncResult result)

        {

            ((ICommunicationObject)(this)).EndOpen(result);

            return null;

        }

 

        private void OnOpenCompleted(object state)

        {

            if ((OpenCompleted != null))

            {

                var e = ((InvokeAsyncCompletedEventArgs)(state));

                OpenCompleted(this, new AsyncCompletedEventArgs(e.Error, e.Cancelled, e.UserState));

            }

        }

 

        public void OpenAsync()

        {

            OpenAsync(null);

        }

 

        public void OpenAsync(object userState)

        {

            InvokeAsync(OnBeginOpen, null, OnEndOpen, OnOpenCompleted, userState);

        }

 

        private IAsyncResult OnBeginClose(object[] inValues, AsyncCallback callback, object asyncState)

        {

            return ((ICommunicationObject)(this)).BeginClose(callback, asyncState);

        }

 

        private object[] OnEndClose(IAsyncResult result)

        {

            ((ICommunicationObject)(this)).EndClose(result);

            return null;

        }

 

        private void OnCloseCompleted(object state)

        {

            var e = ((InvokeAsyncCompletedEventArgs)(state));

            CloseCompleted(new AsyncCompletedEventArgs(e.Error, e.Cancelled, e.UserState));

        }

 

        public void CloseCompleted(AsyncCompletedEventArgs args)

        {

            if (args.Error != null)

            {

                Abort();

            }

        }

 

        public void CloseAsync()

        {

            CloseAsync(null);

        }

 

        public void CloseAsync(object userState)

        {

            InvokeAsync(OnBeginClose, null, OnEndClose, OnCloseCompleted, userState);

        }

 

        protected override IWcfRequestProcessor CreateChannel()

        {

            return new WcfRequestProcessorClientChannel(this);

        }

 

        private class WcfRequestProcessorClientChannel : ChannelBase<IWcfRequestProcessor>, IWcfRequestProcessor

        {

            public WcfRequestProcessorClientChannel(ClientBase<IWcfRequestProcessor> client) :

                base(client)

            {

            }

 

            public IAsyncResult BeginProcessRequests(Request[] requests, AsyncCallback callback, object asyncState)

            {

                var _args = new object[1];

                _args[0] = requests;

                IAsyncResult _result = BeginInvoke("ProcessRequests", _args, callback, asyncState);

                return _result;

            }

 

            [System.Diagnostics.DebuggerHidden]

            public Response[] EndProcessRequests(IAsyncResult result)

            {

                var _args = new object[0];

                var _result = ((Response[])(EndInvoke("ProcessRequests", _args, result)));

 

                result.AsyncWaitHandle.Close();

 

                return _result;

            }

 

            public void ProcessRequestsAsync(Request[] requests, Action<ProcessRequestsAsyncCompletedArgs> processCompleted)

            {

                throw new NotImplementedException();

            }

        }

 

        public void Dispose()

        {

            CloseAsync();

        }

    }

All you would need to be able to make asynchronous calls to the RRSL right now, is the following client-side WCF configuration:

  <system.serviceModel>

    <bindings>

      <basicHttpBinding>

        <binding name="BasicHttpBinding_IWcfRequestProcessor_HTTP" maxBufferSize="2147483647"

          maxReceivedMessageSize="2147483647">

          <security mode="None"/>

        </binding>

      </basicHttpBinding>

    </bindings>

    <client>

      <endpoint binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IWcfRequestProcessor_HTTP"

        contract="Namespace.Of.Your.IWcfRequestProcessor" name="BasicHttpBinding_IWcfRequestProcessor_HTTP" />

    </client>

  </system.serviceModel>

Note, this is an example taken from a Silverlight client… in case of a regular .NET client the WCF configuration will be slightly bigger (and pretty much similar to the one in the example of synchronous RRSL usage).

That’s all you really need to be able to use the RRSL asynchronously from a client. Of course, using the AsyncWcfRequestProcessorProxy class would be even more clumsy and error prone than using the WcfRequestProcessorProxy (from the synchronous usage post) class directly. Ideally, we should be able to use something similar to the IRequestDispatcher, only asynchronously. And thus, the IAsyncRequestDispatcher interface was born:

    public interface IAsyncRequestDispatcher : IDisposable

    {

        void Add(Request request);

        void Add(params Request[] requestsToAdd);

        void Add(string key, Request request);

        void ProcessRequests(Action<ReceivedResponses> receivedResponsesDelegate, Action<ExceptionInfo> exceptionOccurredDelegate);

        void ProcessRequests(Action<ReceivedResponses> receivedResponsesDelegate, Action<ExceptionInfo, ExceptionType> exceptionAndTypeOccurredDelegate);

    }

Its usage is pretty similar to that of the IRequestDispatcher, except that you don’t access the received responses directly. Instead, you tell the IAsyncRequestDispatcher to process the requests and you can provide some callbacks. The first callback needs to be a method which accepts a ReceivedResponses instance as a parameter (we’ll get to that class later on in the post). The second callback is a method which either receives an ExceptionInfo object as a parameter, or both an ExceptionInfo and ExceptionType parameter. The last callback will obviously only be called if something went wrong.

Another big difference between the IAsyncRequestDispatcher and the IRequestDispatcher is that the IAsyncRequestDispatcher is not ment to be reused for multiple service calls. That is, you can obviously add as many requests as you like but you can only call the ProcessRequests method once, at which point all of the added requests will be sent to the RRSL through the AsyncWcfRequestProcessorProxy class. The reason why we chose to go the “You can only use it once”-route is to guarantee that the IAsyncRequestDispatcher and especially its AsyncWcfRequestProcessorProxy instance are always guaranteed to be disposed properly no matter when the responses are returned, which might be after the view-component has already been closed by the user, for instance.

Now, our implementation of the IAsyncRequestDispatcher interface is dependent upon 3 other classes that we wrote. The first is the AsyncWcfRequestProcessoryProxy class which we already covered. The other two are the ReceivedResponses class, and the ResponseReceiver class. I’ll show the implementations of those classes after i show the code of the AsyncRequestDispatcher so you might have to scroll back and forth between the code of these classes in order to grasp the code.

First of all, the AsyncRequestDispatcher:

    public class AsyncRequestDispatcher : Disposable, IAsyncRequestDispatcher

    {

        private readonly IWcfRequestProcessor requestProcessor;

        protected Dictionary<string, int> keyToResultPositions;

        private Dictionary<string, Type> keyToTypes;

 

        private List<Request> queuedRequests;

 

        public AsyncRequestDispatcher(IWcfRequestProcessor requestProcessor)

        {

            this.requestProcessor = requestProcessor;

            InitializeState();

        }

 

        public virtual Request[] QueuedRequests

        {

            get { return queuedRequests.ToArray(); }

        }

 

        public virtual void Add(params Request[] requestsToAdd)

        {

            foreach (var request in requestsToAdd)

            {

                Add(request);

            }

        }

 

        public virtual void Add(string key, Request request)

        {

            AddRequest(request, true);

            keyToTypes[key] = request.GetType();

            keyToResultPositions[key] = queuedRequests.Count - 1;

        }

 

        public virtual void Add(Request request)

        {

            AddRequest(request, false);

        }

 

        public virtual void ProcessRequests(Action<ReceivedResponses> receivedResponsesDelegate, Action<ExceptionInfo> exceptionOccurredDelegate)

        {

            ProcessRequests(new ResponseReceiver(receivedResponsesDelegate, exceptionOccurredDelegate, keyToResultPositions));

        }

 

        public virtual void ProcessRequests(Action<ReceivedResponses> receivedResponsesDelegate, Action<ExceptionInfo, ExceptionType> exceptionAndTypeOccurredDelegate)

        {

            ProcessRequests(new ResponseReceiver(receivedResponsesDelegate, exceptionAndTypeOccurredDelegate, keyToResultPositions));

        }

 

        private void ProcessRequests(ResponseReceiver responseReciever)

        {

            var requests = queuedRequests.ToArray();

            BeforeSendingRequests(requests);

            requestProcessor.ProcessRequestsAsync(requests, a => OnProcessRequestsCompleted(a, responseReciever));

        }

 

        protected virtual void BeforeSendingRequests(IEnumerable<Request> requestsToProcess) { }

 

        public virtual void OnProcessRequestsCompleted(ProcessRequestsAsyncCompletedArgs args, ResponseReceiver responseReciever)

        {

            Dispose();

            responseReciever.ReceiveResponses(args);

        }

 

        protected override void DisposeManagedResources()

        {

            if (requestProcessor != null) requestProcessor.Dispose();

        }

 

        private void AddRequest(Request request, bool wasAddedWithKey)

        {

            Type requestType = request.GetType();

 

            if (RequestTypeIsAlreadyPresent(requestType) &&

                (RequestTypeIsNotAssociatedWithKey(requestType) || !wasAddedWithKey))

            {

                throw new InvalidOperationException(String.Format("A request of type {0} has already been added. "

                                                                  + "Please add requests of the same type with a different key.", requestType.FullName));

            }

 

            queuedRequests.Add(request);

        }

 

        private bool RequestTypeIsAlreadyPresent(Type requestType)

        {

            return QueuedRequests.Count(r => r.GetType().Equals(requestType)) > 0;

        }

 

        private bool RequestTypeIsNotAssociatedWithKey(Type requestType)

        {

            return !keyToTypes.Values.Contains(requestType);

        }

 

        private void InitializeState()

        {

            queuedRequests = new List<Request>();

            keyToTypes = new Dictionary<string, Type>();

            keyToResultPositions = new Dictionary<string, int>();

        }

    }

There’s nothing complex or difficult about this class. You can basically add requests just as you could do with the synchronous RequestDispatcher, and when you call the ProcessRequests method, we create a ResponseReceiver which will also be passed into the method that will be called once the responses have returned from the asynchronous proxy. When those responses are returned, we dispose our own instance of the AsyncRequestDispatcher (which in turn disposes the AsyncWcfRequestProcessorProxy) and then we ask the ResponseReceiver to handle the received responses. Nothing complicated, but you might have to take a second look if you didn’t get it the first time (and you certainly wouldn’t be the first).

The implementation of the ResponseReceiver class looks like this:

    public class ResponseReceiver

    {

        private readonly Action<ReceivedResponses> responseReceivedCallback;

        private readonly Action<ExceptionInfo, ExceptionType> exceptionAndTypeOccuredCallback;

        private readonly Action<ExceptionInfo> exceptionOccurredCallback;

        private readonly Dictionary<string, int> keyToResultPositions;

 

        public ResponseReceiver(Action<ReceivedResponses> responseReceivedCallback, Action<ExceptionInfo> exceptionOccurredCallback,

            Dictionary<string, int> keyToResultPositions)

        {

            if (responseReceivedCallback == null) throw new ArgumentNullException("responseReceivedCallback");

            if (exceptionOccurredCallback == null) throw new ArgumentNullException("exceptionOccurredCallback");

 

            this.responseReceivedCallback = responseReceivedCallback;

            this.exceptionOccurredCallback = exceptionOccurredCallback;

            this.keyToResultPositions = keyToResultPositions;

        }

 

        public ResponseReceiver(Action<ReceivedResponses> responseReceivedCallback, Action<ExceptionInfo, ExceptionType> exceptionAndTypeOccuredCallback,

            Dictionary<string, int> keyToResultPositions)

        {

            if (responseReceivedCallback == null) throw new ArgumentNullException("responseReceivedCallback");

            if (exceptionAndTypeOccuredCallback == null) throw new ArgumentNullException("exceptionAndTypeOccuredCallback");

 

            this.responseReceivedCallback = responseReceivedCallback;

            this.exceptionAndTypeOccuredCallback = exceptionAndTypeOccuredCallback;

            this.keyToResultPositions = keyToResultPositions;

        }

 

        public void ReceiveResponses(ProcessRequestsAsyncCompletedArgs args)

        {

            if (HasException(args))

            {

                HandleException(args);

            }

            else

            {

                var disposable = responseReceivedCallback.Target as Disposable;

 

                if (disposable == null || !disposable.IsDisposed)

                {

                    responseReceivedCallback(new ReceivedResponses(args.Result, keyToResultPositions));

                }

            }

        }

 

        private void HandleException(ProcessRequestsAsyncCompletedArgs args)

        {

            var disposable = responseReceivedCallback.Target as Disposable;

 

            if (disposable == null || !disposable.IsDisposed)

            {

                var exception = GetException(args);

 

                if (exceptionOccurredCallback != null)

                {

                    exceptionOccurredCallback(exception);

                }

                else if (exceptionAndTypeOccuredCallback != null)

                {

                    var exceptionType = GetExceptionType(args);

 

                    exceptionAndTypeOccuredCallback(exception, exceptionType);

                }

                else

                {

                    responseReceivedCallback(new ReceivedResponses(args.Result, keyToResultPositions));

                }

            }

        }

 

        private static bool HasException(ProcessRequestsAsyncCompletedArgs args)

        {

            if (args.Error == null)

            {

                return args.Result.Any(r => r.Exception != null);

            }

 

            return true;

        }

 

        private static ExceptionInfo GetException(ProcessRequestsAsyncCompletedArgs args)

        {

            if (args.Error == null)

            {

                var responseWithException = GetFirstException(args.Result);

                if (responseWithException != null)

                {

                    return responseWithException.Exception;

                }

 

                return null;

            }

 

            return new ExceptionInfo(args.Error);

        }

 

        private static ExceptionType GetExceptionType(ProcessRequestsAsyncCompletedArgs args)

        {

            if (args.Error == null)

            {

                var responseWithException = GetFirstException(args.Result);

 

                if (responseWithException != null)

                {

                    return responseWithException.ExceptionType;

                }

            }

 

            return ExceptionType.Unknown;

        }

 

        private static Response GetFirstException(IEnumerable<Response> responsesToCheck)

        {

            return responsesToCheck.FirstOrDefault(r => r.Exception != null);

        }

    }

Pretty straightforward… it basically makes sure that either the callback from the original caller is called to handle the received responses, or that the callback is called to deal with exceptions. The callback to handle the received responses receives a ReceivedResponses instance, which again makes it possible to easily retrieve the response you need:

    public class ReceivedResponses

    {

        private readonly Response[] responses;

        private readonly Dictionary<string, int> keyToResultPositions;

 

        public ReceivedResponses(Response[] responses)

            : this(responses, new Dictionary<string, int>()) {}

 

        public ReceivedResponses(Response[] responses, Dictionary<string, int> keyToResultPositions)

        {

            this.responses = responses;

            this.keyToResultPositions = keyToResultPositions;

        }

 

        public virtual TResponse Get<TResponse>() where TResponse : Response

        {

            var responseType = typeof(TResponse);

            return (TResponse)responses.Single(r => r.GetType().Equals(responseType));

        }

 

        public virtual TResponse Get<TResponse>(string key) where TResponse : Response

        {

            return (TResponse)responses[keyToResultPositions[key]];

        }

 

        public virtual bool HasResponse<TResponse>() where TResponse : Response

        {

            return responses.OfType<TResponse>().Any();

        }

    }

Now, some of you will probably be thinking “isn’t all this more complex than it needs to be?”. Apart from the asynchronous proxy, i truly doubt it. The only thing that your code needs to know of is the API of the IAsyncRequestDispatcher interface and of the ReceivedResponses class which are both pretty clean, very easy to use and easy to grasp.

One final word about the fact that the IAsyncRequestDispatcher is only meant to be used once. Obviously, we don’t create each IAsyncRequestDispatcher instance manually. We can’t have the IOC container inject it whenever we want either, because then we’d only have one instance for the lifetime of the class that had the IAsyncRequestDispatcher injected. We inject the following factory instead:

    public interface IAsyncRequestDispatcherFactory

    {

        IAsyncRequestDispatcher CreateAsyncRequestDispatcher();

    }

The implementation of which looks like this:

    public class AsyncRequestDispatcherFactory : IAsyncRequestDispatcherFactory

    {

        public IAsyncRequestDispatcher CreateAsyncRequestDispatcher()

        {

            return IoC.Container.Resolve<IAsyncRequestDispatcher>();

        }

    }

One thing that you need to be very careful of: if your IAsyncRequestDispatcherFactory implementation happens to use Castle Windsor’s container (ours doesn’t because we have our own custom little container for our Silverlight apps) then you absolutely have to make sure that the Dispose method of the IAsyncRequestDispatcher implementation calls the Release method of the Windsor container. More information on why you’d need to do that can be found here and here.

That’s it for this post, which is probably the most difficult one to comprehend but again, the most important facts to remember are the ease of use of IAsyncRequestDispatcher and ReceivedResponses. Also, keep in mind that even though we use this primarily for Silverlight clients, you can just as well do this from WPF applications or any other .NET application for that matter.

Finally, i’d like to thank Tom Ceulemans for the implementation shown in this post. He happened to be the first one who needed to use the RRSL from a silverlight application and he did a great job with getting it to work :)

Posted in Request/Response Service Layer | 3 Comments »

Request/Response Service Layer: Testing Synchronous Client-Side Usage

Posted by Davy Brion on 13th November 2009

Note: This post is part of a series. Be sure to read the introduction here.

If you want to write automated tests for your client-side code, it’s often useful to replace the service proxy with a mock instance. With typical WCF services and their proxies, that’s pretty easy to do. With the Request/Response Service Layer (RRSL) and its IRequestDispatcher, it’s a bit more tricky. While you could provide a mock instance of IRequestDispatcher to your classes under test, we’ve learned that it’s easier to use a prepared stub class which inherits from the RequestDispatcher class and adds some extra methods to inspect the requests that were supposed to be sent, and to return response objects that you can easily prepare yourself.

If we go back to our implementation of the IRequestDispatcher interface, you’ll notice that the RequestDispatcher class has the following constructor:

        protected RequestDispatcher(IRequestProcessor requestProcessor)

        {

            this.requestProcessor = requestProcessor;

            InitializeState();

        }

As well as the following virtual method which is the only place where we actually use the IRequestProcessor to send requests to the Request Processor:

        protected virtual Response[] GetResponses(params Request[] requestsToProcess)

        {

            BeforeSendingRequests(requestsToProcess);

            return requestProcessor.Process(requestsToProcess);

        }

You’ll also notice that most of the public methods of the RequestDispatcher class are virtual and that many of its protected methods are virtual as well. While we don’t need to override all of them, there’s plenty of flexibility to do whatever you want to do. We’ll basically pass a null reference to the RequestDispatcher’s constructor (which takes an IRequestProcessor instance) and override the protected GetResponses method to simply return our prepared responses instead of actually sending them to the IRequestProcessor. We’ll also add a few methods so you can add prepared responses in your tests, as well as some methods which allow you to easily inspect whether certain requests were added by the code under test, and to retrieve the actual requests so you can verify that they contain the expected data.

There is no interface to define the added functionality of the stub, but this fictional interface might make it clearer what you’ll be able to do with the stub in your tests:

    public interface IRequestDispatcherStub : IRequestDispatcher

    {

        void AddResponsesToReturn(params Response[] responses);

        void AddResponsesToReturn(Dictionary<string, Response> keyedResponses);

        void AddResponseToReturn(Response response);

        void AddResponseToReturn(string key, Response response);

        TRequest GetRequest<TRequest>() where TRequest : Request;

        TRequest GetRequest<TRequest>(string key) where TRequest : Request;

        bool HasRequest<TRequest>() where TRequest : Request;

    }

Those added methods make it very clear to verify that your code under test is communicating with the RRSL in the way you intended it to.

So finally, this is the code of the RequestDispatcherStub class:

    public class RequestDispatcherStub : RequestDispatcher

    {

        private readonly List<Response> responsesToReturn = new List<Response>();

        private readonly Dictionary<string, Request> keyToRequest = new Dictionary<string, Request>();

 

        public RequestDispatcherStub() : base(null) { }

 

        public void AddResponsesToReturn(params Response[] responses)

        {

            responsesToReturn.AddRange(responses);

        }

 

        public void AddResponsesToReturn(Dictionary<string, Response> keyedResponses)

        {

            responsesToReturn.AddRange(keyedResponses.Values);

 

            for (int i = 0; i < keyedResponses.Keys.Count; i++)

            {

                var key = keyedResponses.Keys.ElementAt(i);

 

                if (key != null)

                {

                    keyToResultPositions.Add(key, i);

                }

            }

        }

 

        public void AddResponseToReturn(Response response)

        {

            responsesToReturn.Add(response);

        }

 

        public void AddResponseToReturn(string key, Response response)

        {

            responsesToReturn.Add(response);

            keyToResultPositions.Add(key, responsesToReturn.Count - 1);

        }

 

        public override void Clear()

        {

            // this Stub can't clear the state because we have to be able to inspect the sent requests

            // during our tests

        }

 

        public override void Add(string key, Request request)

        {

            base.Add(key, request);

            keyToRequest[key] = request;

        }

 

        public TRequest GetRequest<TRequest>() where TRequest : Request

        {

            return (TRequest)SentRequests.First(r => r.GetType().Equals(typeof(TRequest)));

        }

 

        public TRequest GetRequest<TRequest>(string key) where TRequest : Request

        {

            return (TRequest)keyToRequest[key];

        }

 

        public bool HasRequest<TRequest>() where TRequest : Request

        {

            return SentRequests.Count(r => r.GetType().Equals(typeof(TRequest))) > 0;

        }

 

        protected override Response[] GetResponses(params Request[] requestsToProcess)

        {

            return responsesToReturn.ToArray();

        }

 

        protected override void DealWithSecurityException(ExceptionInfo exceptionInfo)

        {

            throw new SecurityException("a security exception was thrown: " + exceptionInfo);

        }

 

        protected override void DealWithUnknownException(ExceptionInfo exceptionInfo)

        {

            throw new Exception("an unknown exception was thrown: " + exceptionInfo);

        }

    }

With this in place, you can very easily test whether the correct requests have been sent, whether they contain the expected data, and how your code reacts to the data in your prepared responses.

Posted in Request/Response Service Layer | 2 Comments »

Request/Response Service Layer: Synchronous Client-Side Usage

Posted by Davy Brion on 12th November 2009

Note: This post is part of a series. Be sure to read the introduction here.

One of my biggest issues with using typical WCF Services is that you always need to update your client-side proxies whenever a new operation is added to your service layer. I definitely wanted to avoid that with the Request/Response Service Layer, and that was easy to do because this is our only Service Contract:

    [ServiceContract]

    public interface IWcfRequestProcessor

    {

        [OperationContract(Name = "ProcessRequests")]

        [ServiceKnownType("GetKnownTypes", typeof(KnownTypeProvider))]

        Response[] Process(params Request[] requests);

    }

As you can see there’s only one Operation on this service, and because each ‘operation’ of our service layer is exposed as a Request/Response combination, we’ll never have to add anything else to this Service Contract and thus, we only need to create our proxy once and we’ll never have to update it.

Instead of generating a service proxy with SvcUtil, i chose to just inherit from WCF’s ClientBase class:

    public class RequestProcessorProxy : ClientBase<IWcfRequestProcessor>, IRequestProcessor

    {

        public RequestProcessorProxy() {}

 

        public RequestProcessorProxy(string endpointConfigurationName)

            : base(endpointConfigurationName) {}

 

        public RequestProcessorProxy(string endpointConfigurationName, string remoteAddress)

            : base(endpointConfigurationName, remoteAddress) {}

 

        public RequestProcessorProxy(string endpointConfigurationName, EndpointAddress remoteAddress)

            : base(endpointConfigurationName, remoteAddress) {}

 

        public RequestProcessorProxy(Binding binding, EndpointAddress remoteAddress)

            : base(binding, remoteAddress) {}

 

        public RequestProcessorProxy(InstanceContext callbackInstance)

            : base(callbackInstance) {}

 

        public RequestProcessorProxy(InstanceContext callbackInstance, string endpointConfigurationName)

            : base(callbackInstance, endpointConfigurationName) {}

 

        public RequestProcessorProxy(InstanceContext callbackInstance, string endpointConfigurationName, string remoteAddress)

            : base(callbackInstance, endpointConfigurationName, remoteAddress) {}

 

        public RequestProcessorProxy(InstanceContext callbackInstance, string endpointConfigurationName, EndpointAddress remoteAddress)

            : base(callbackInstance, endpointConfigurationName, remoteAddress) {}

 

        public RequestProcessorProxy(InstanceContext callbackInstance, Binding binding, EndpointAddress remoteAddress)

            : base(callbackInstance, binding, remoteAddress) {}

 

        public Response[] Process(params Request[] requests)

        {

            return Channel.Process(requests);

        }

 

        public void Dispose()

        {

            try

            {

                Close();

            }

            catch (Exception)

            {

                Abort();

            }

        }

    }

And that is it as far as the proxy is concerned. The implementation of the Dispose method isn’t very clean, but that is to work around an issue that WCF has where calling the Close method can throw an Exception (and as you know, your Dispose methods should never, ever throw an Exception) and when it does, you absolutely need to call the Abort method of the proxy. If you don’t, the Channel will remain open and once you hit the limit of concurrent open channels on your service, no requests will be able to be handled by the service. Why yes, we definitely learned that one the hard way ;)

Now, this proxy is already enough to be able to make synchronous calls to the RRSL from your client code, as long as you put the following WCF configuration in your web.config or app.config file:

  <system.serviceModel>

    <bindings>

      <wsHttpBinding>

        <binding name="RequestProcessorBindingConfiguration_HTTPS" maxReceivedMessageSize="2147483647" sendTimeout="00:30">

          <readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" />

          <security mode="Transport">

            <transport clientCredentialType="None"/>

          </security>

        </binding>

      </wsHttpBinding>

    </bindings>

    <behaviors>

      <serviceBehaviors>

        <behavior name="RequestProcessorBehavior">

          <dataContractSerializer maxItemsInObjectGraph="2147483647"/>

        </behavior>

      </serviceBehaviors>

    </behaviors>

    <client>

      <endpoint binding="wsHttpBinding" name="IRequestProcessor" bindingConfiguration="RequestProcessorBindingConfiguration_HTTPS"

                behaviorConfiguration="RequestProcessorServiceBehavior" contract="Namespace.Of.Your.IWcfRequestProcessor" />

    </client>

  </system.serviceModel>

In this example we’re connecting to a RRSL that is exposed through the wsHttpBinding over HTTPS. Obviously, you can use any of the other WCF bindings and configurations as well.

Also, you’ll need to register your Request and Response types with the KnownTypeProvider (just as you had to do in your service host) before you start sending requests to the service. You can do that with something like this:

        private static void RegisterRequestAndResponseTypes(Assembly assembly)

        {

            KnownTypeProvider.RegisterDerivedTypesOf<Request>(assembly);

            KnownTypeProvider.RegisterDerivedTypesOf<Response>(assembly);

        }

So, that is all you need to use the RRSL synchronously. But using the Process method of the RequestProcessorProxy is clumsy and even prone to errors because you’d have to keep track of the indexes of the requests and the responses. It certainly isn’t a nice API. So to fix that, we also have the IRequestDispatcher interface which offers a much cleaner and less error prone API:

    public interface IRequestDispatcher : IDisposable

    {

        IEnumerable<Response> Responses { get; }

 

        void Add(Request request);

        void Add(params Request[] requestsToAdd);

        void Add(string key, Request request);

        bool HasResponse<TResponse>() where TResponse : Response;

        TResponse Get<TResponse>() where TResponse : Response;

        TResponse Get<TResponse>(string key) where TResponse : Response;

        TResponse Get<TResponse>(Request request) where TResponse : Response;

        void Clear();

    }

The idea is that you can add requests to an IRequestDispatcher in a clean manner, and then simply retrieve the responses you want based on the type of the response. If you need to send multiple requests of the same type in a single batch, you need to provide a string key to identify its response because another response will be of the same type. You can add as many requests as you want, and the requests won’t be sent to the service until you actually try to retrieve one of the responses. Once you try to retrieve a response, all of the batched requests will be sent to the service in a single roundtrip and the responses are stored in the IRequestDispatcher until you retrieve them or until the IRequestDispatcher is cleared (or garbage collected).

The implementation of the IRequestDispatcher will use an IRequestProcessor instance to send the requests to the Request Processor (covered in an earlier post in this series). If you’re using the RRSL over WCF, then you better configure your IOC container to create instances of the RequestProcessorProxy class whenever an instance of IRequestProcessor is requested by your code. This also means that you can just as well run the RRSL within the same process as your client code if you don’t actually need it to run in a separate process (or service) and just want the architectural benefits of this approach. You could do this by simply configuring your IOC container to return the actual RequestProcessor implementation instead of the WCF proxy.

The implementation of the RequestDispatcher class looks like this:

    public abstract class RequestDispatcher : Disposable, IRequestDispatcher

    {

        private readonly IRequestProcessor requestProcessor;

 

        private Dictionary<string, Type> keyToTypes;

        protected Dictionary<string, int> keyToResultPositions;

        private List<Request> requests;

        private Response[] responses;

 

        protected RequestDispatcher(IRequestProcessor requestProcessor)

        {

            this.requestProcessor = requestProcessor;

            InitializeState();

        }

 

        private void InitializeState()

        {

            requests = new List<Request>();

            responses = null;

            keyToTypes = new Dictionary<string, Type>();

            keyToResultPositions = new Dictionary<string, int>();

        }

 

        public IEnumerable<Request> SentRequests

        {

            get { return requests; }

        }

 

        public IEnumerable<Response> Responses

        {

            get

            {

                SendRequestsIfNecessary();

                return responses;

            }

        }

 

        public virtual void Add(params Request[] requestsToAdd)

        {

            foreach (var request in requestsToAdd)

            {

                Add(request);

            }

        }

 

        public virtual void Add(Request request)

        {

            AddRequest(request, false);

        }

 

        public virtual void Add(string key, Request request)

        {

            AddRequest(request, true);

            keyToTypes[key] = request.GetType();

            keyToResultPositions[key] = requests.Count - 1;

        }

 

        public virtual bool HasResponse<TResponse>() where TResponse : Response

        {

            SendRequestsIfNecessary();

            return responses.OfType<TResponse>().Count() > 0;

        }

 

        public virtual TResponse Get<TResponse>() where TResponse : Response

        {

            SendRequestsIfNecessary();

            return responses.OfType<TResponse>().Single();

        }

 

        public virtual TResponse Get<TResponse>(string key) where TResponse : Response

        {

            SendRequestsIfNecessary();

            return (TResponse)responses[keyToResultPositions[key]];

        }

 

        public virtual TResponse Get<TResponse>(Request request) where TResponse : Response

        {

            Add(request);

            return Get<TResponse>();

        }

 

        public virtual void Clear()

        {

            InitializeState();

        }

 

        protected override void DisposeManagedResources()

        {

            if (requestProcessor != null) requestProcessor.Dispose();

        }

 

        protected virtual Response[] GetResponses(params Request[] requestsToProcess)

        {

            BeforeSendingRequests(requestsToProcess);

            return requestProcessor.Process(requestsToProcess);

        }

 

        protected virtual void BeforeSendingRequests(IEnumerable<Request> requestsToProcess) { }

 

        private void SendRequestsIfNecessary()

        {

            if (responses == null)

            {

                responses = GetResponses(requests.ToArray());

                DealWithPossibleExceptions(responses);

            }

        }

 

        private void DealWithPossibleExceptions(IEnumerable<Response> responsesToCheck)

        {

            foreach (var response in responsesToCheck)

            {

                if (response.ExceptionType == ExceptionType.Security)

                {

                    DealWithSecurityException(response.Exception);

                }

 

                if (response.ExceptionType == ExceptionType.Unknown)

                {

                    DealWithUnknownException(response.Exception);

                }

            }

        }

 

        protected abstract void DealWithUnknownException(ExceptionInfo exception);

        protected abstract void DealWithSecurityException(ExceptionInfo exceptionDetail);

 

        private void AddRequest(Request request, bool wasAddedWithKey)

        {

            Type requestType = request.GetType();

 

            if (RequestTypeIsAlreadyPresent(requestType) &&

                (RequestTypeIsNotAssociatedWithKey(requestType) || !wasAddedWithKey))

            {

                throw new InvalidOperationException(String.Format("A request of type {0} has already been added. "

                                                                  + "Please add requests of the same type with a different key.", requestType.FullName));

            }

 

            requests.Add(request);

        }

 

        private bool RequestTypeIsNotAssociatedWithKey(Type requestType)

        {

            return !keyToTypes.Values.Contains(requestType);

        }

 

        private bool RequestTypeIsAlreadyPresent(Type requestType)

        {

            return requests.Count(r => r.GetType().Equals(requestType)) > 0;

        }

    }

There’s nothing special about this class, except for 3 things maybe. First of all, it’s an abstract class with 2 abstract methods. So obviously, your application needs to inherit from this RequestDispatcher implementation (or can provide its own implementation as long as it implements the IRequestDispatcher interface) and implement the abstract DealWithSecurityException and DealWithUnknownException methods. We found this to be useful because most web applications will return you to a general “Oops, something went wrong” page or “You don’t have enough clout in this world to perform the task you were trying to do” page when unknown exceptions or security exceptions occur. If you don’t want any of that to happen and simply deal with the exception in the calling code, the implementations of these methods can just do nothing, or only do something in certain conditions or whatever else that fits your purpose or intentions.

There’s also a virtual BeforeSendingRequests methods which you can implement. We typically override that method to add authentication data (such as the current user’s username and password hash) to each request.

That’s pretty much all there is to using the RRSL from your client code in a synchronous manner with a pretty clean API.

Posted in Request/Response Service Layer | No Comments »

Request/Response Service Layer: Exposing The Service Layer Through WCF

Posted by Davy Brion on 11th November 2009

Note: This post is part of a series. Be sure to read the introduction here.

The previous posts in the series already covered everything there is to know about implementing the Request/Response Service Layer (RRSL). In this post, we’ll focus on hosting the RRSL through WCF and the next posts will show you how you can actually use the RRSL from your clients (both synchronously and asynchronously). First, let’s take another look at what our service actually exposes:

    public interface IRequestProcessor : IDisposable

    {

        Response[] Process(params Request[] requests);

    }

This interface doesn’t contain the necessary WCF attributes, but we’ll get to that in a minute. The first thing that we need to take care of is to make sure that WCF’s DataContractSerializer can handle the derived Request and Response types without us having to declare the KnownType attribute on each derived class. Luckily for us, WCF has a ServiceKnownType attribute where you can define a class that will provide the KnownTypes to WCF so it can properly serialize and deserialize them. But first, we’ll need a KnownTypeProvider class:

    public static class KnownTypeProvider

    {

        private static HashSet<Type> knownTypes = new HashSet<Type>();

 

        public static void ClearAllKnownTypes()

        {

            knownTypes = new HashSet<Type>();

        }

 

        public static void Register<T>()

        {

            Register(typeof(T));

        }

 

        public static void Register(Type type)

        {

            knownTypes.Add(type);

        }

 

        public static void RegisterDerivedTypesOf<T>(Assembly assembly)

        {

            RegisterDerivedTypesOf(typeof(T), assembly);

        }

 

        public static void RegisterDerivedTypesOf<T>(IEnumerable<Type> types)

        {

            RegisterDerivedTypesOf(typeof(T), types);

        }

 

        public static void RegisterDerivedTypesOf(Type type, Assembly assembly)

        {

            RegisterDerivedTypesOf(type, assembly.GetTypes());

        }

 

        public static void RegisterDerivedTypesOf(Type type, IEnumerable<Type> types)

        {

            knownTypes.UnionWith(GetDerivedTypesOf(type, types));

        }

 

        public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)

        {

            return knownTypes;

        }

 

        private static List<Type> GetDerivedTypesOf(Type baseType, IEnumerable<Type> types)

        {

            return types.Where(t => !t.IsAbstract && t.IsSubclassOf(baseType)).ToList();

        }

    }

Now we just have to make sure that all of our Request and Response types are registered before the application is initialized. You basically need to make sure that the following code is called before the first request is sent to the service:

        private static void RegisterRequestAndResponseTypes(Assembly assembly)

        {

            KnownTypeProvider.RegisterDerivedTypesOf<Request>(assembly);

            KnownTypeProvider.RegisterDerivedTypesOf<Response>(assembly);

        }

Now we can actually define our Service Contract. Instead of putting the WCF attributes on the IRequestProcessor interface, i decided to put a different interface next to it. The reason i chose to go that route is merely to make sure that the actual IRequestProcessor interface and it’s implementation isn’t tied to WCF. And that’s why we have the IWcfRequestProcessor interface:

    [ServiceContract]

    public interface IWcfRequestProcessor

    {

        [OperationContract(Name = "ProcessRequests")]

        [ServiceKnownType("GetKnownTypes", typeof(KnownTypeProvider))]

        Response[] Process(params Request[] requests);

    }

This is a ‘properly’ defined WCF Service Contract, and we also make sure that WCF knows where to get the list of known types by using the ServiceKnownType attribute and hooking it to our KnownTypeProvider. The implementation of this service contract looks like this:

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]

    public class WcfRequestProcessor : IWcfRequestProcessor

    {

        public Response[] Process(params Request[] requests)

        {

            return IoC.Container.Resolve<IRequestProcessor>().Process(requests);

        }

    }

As you can see, there’s nothing to it… The implementation of the Process method simply resolves the real IRequestProcessor implementation, calls the Process method and returns the Responses. That’s it.

Now we still need to host the service somewhere. I always host it through IIS but you can use any of the other WCF hosting options as well. In case you’re hosting it in a Web Application, add a RequestProcessorService.svc file to your Web Application with the following content:

<%@ ServiceHost Language="C#" Debug="true" Service="The.Namespace.Of.Your.WcfRequestProcessor" %>

In your web.config (or app.config if you’re hosting it yourself or through a windows service), add the following block:

  <system.serviceModel>

 

    <services>

      <service name="The.Namespace.Of.Your.WcfRequestProcessor" behaviorConfiguration="RequestProcessorBehavior">

        <endpoint address="" contract="The.Namespace.Of.Your.IWcfRequestProcessor"

        binding="customBinding" bindingConfiguration="binaryHttpBinding"/>

      </service>

    </services>

 

    <bindings>

      <customBinding>

        <binding name="binaryHttpBinding" receiveTimeout="00:30:00" sendTimeout="00:30:00" >

          <binaryMessageEncoding>

            <readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" />

          </binaryMessageEncoding>

          <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />

        </binding>

      </customBinding>

 

       <basicHttpBinding>

          <binding name="basicHttpBinding" receiveTimeout="00:30:00"

             sendTimeout="00:30:00" maxReceivedMessageSize="2147483647">

             <readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" />

             <security mode="None" />

          </binding>

       </basicHttpBinding>

    </bindings>

 

    <behaviors>

      <serviceBehaviors>

        <behavior name="RequestProcessorBehavior">

          <serviceMetadata httpGetEnabled="true" />

          <serviceDebug includeExceptionDetailInFaults="true"/>

          <dataContractSerializer maxItemsInObjectGraph="2147483647"/>

          <serviceThrottling maxConcurrentCalls="100" maxConcurrentInstances="100" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

 

  </system.serviceModel>

I included two binding configurations in this example, but you obviously only need one. In this case, the service endpoint is configured to use the custom binaryHttpBinding. This uses binary XML which (in most cases) is more compact and thus, has less bandwidth overhead. If you want to use a regular basicHttpBinding, just modify the service endpoint configuration to point to the other binding. Obviously, you can use wsHttpBinding or any other binding as well if you want to.

And that is it. That’s really all you need to do to host the RRSL through WCF. You’ll never have to edit or add anything to the xml configuration as you add more functionality to your service layer. It works now, and it will keep working.

Just keep in mind that you need to register the Request and Response types with the KnownTypeProvider before the service receives the first request ;)

Posted in Request/Response Service Layer | 5 Comments »

Request/Response Service Layer: Handling Requests

Posted by Davy Brion on 10th November 2009

Note: This post is part of a series. Be sure to read the introduction here.

We already covered how you can define your request/response types, and how they can be processed. Now it’s time to deal with how they can be handled by their respective Request Handlers. As shown in the previous post, we have the following 2 interfaces:

    public interface IRequestHandler : IDisposable

    {

        Response Handle(Request request);

        Response CreateDefaultResponse();

    }

 

    public interface IRequestHandler<TRequest> : IRequestHandler where TRequest : Request

    {

        Response Handle(TRequest request);

    }

Alright, let’s get started with their implementations. First we have the regular RequestHandler class:

    public abstract class RequestHandler : Disposable, IRequestHandler

    {

        public abstract Response Handle(Request request);

        public abstract Response CreateDefaultResponse();

 

        /// <summary>

        /// Default implementation is empty

        /// </summary>

        protected override void DisposeManagedResources() { }

    }

And then a generic RequestHandler class which inherits from the previous class:

    public abstract class RequestHandler<TRequest, TResponse> : RequestHandler, IRequestHandler<TRequest>

        where TRequest : Request

        where TResponse : Response

    {

        public override Response Handle(Request request)

        {

            var typedRequest = (TRequest)request;

            BeforeHandle(typedRequest);

            var response = Handle(typedRequest);

            AfterHandle(typedRequest);

            return response;

        }

 

        public virtual void BeforeHandle(TRequest request) {}

        public virtual void AfterHandle(TRequest request) {}

 

        public abstract Response Handle(TRequest request);

 

        public override Response CreateDefaultResponse()

        {

            return CreateTypedResponse();

        }

 

        public TResponse CreateTypedResponse()

        {

            return (TResponse)Activator.CreateInstance(typeof(TResponse));

        }

    }

When the Request Processor delegates the handling of a request to its Request Handler, it calls the Handle method which accepts a parameter of type Request. The implementation of that method will first call a virtual BeforeHandle method, then the typed Handle method which accepts a parameter of type TRequest, and then the virtual AfterHandle method. This gives each derived Request Handler the ability to put some custom logic before and after the actual handling of a request.

You’ll hardly ever inherit directly from the generic RequestHandler class. In most cases, you’ll put another class in between your actual handlers and this one. For our NHibernate applications, we have the following custom NhRequestHandler class that each application bases its handlers on:

    public abstract class NhRequestHandler<TRequest, TResponse> : RequestHandler<TRequest, TResponse>

        where TRequest : Request

        where TResponse : Response

    {

        private readonly ILog logger = LogManager.GetLogger(typeof(NhRequestHandler<TRequest, TResponse>));

 

        public IUnitOfWork UnitOfWork { get; set; }

 

        protected override void DisposeManagedResources()

        {

            if (UnitOfWork != null) UnitOfWork.Dispose();

        }

 

        public override Response Handle(Request request)

        {

            using (ITransaction transaction = UnitOfWork.CreateTransaction())

            {

                Response response;

 

                try

                {

                    response = base.Handle(request);

                    transaction.Commit();

                }

                catch (Exception handlerException)

                {

                    try

                    {

                        transaction.Rollback();

                    }

                    catch (Exception)

                    {

                        logger.Error("NhRequestHandler: Rollback after exception failed! Original exception (the one that caused the rollback) was: ", handlerException);

                        throw;

                    }

 

                    // note: there's no need to log the exception here, it will be logged by the RequestProcessor

                    throw;

                }

 

                return response;

            }

        }

    }

This class requires an IUnitOfWork instance which is injected automatically by the IOC container. I prefer to use Setter Injection for dependencies in base classes instead of Constructor Injection but you could obviously just as easily have the IUnitOfWork injected through the constructor if you’d prefer so.

The interesting part is that this class overrides the Handle(Request) method instead of the Handle(TRequest) method. It first creates a transaction through the UnitOfWork and will then call the base class’ Handle(Request) method. The ‘tricky’ part here is that the base implementation of Handle(Request) will in turn call the typed BeforeHandle(TRequest), Handle(TRequest) and AfterHandle(TRequest) methods in the derived class, all of which will be executed within the scope of the UnitOfWork’s transaction.

Should an exception occur, the transaction is automatically rolled back and otherwise it’s automatically committed. Each derived Request Handler can simply declare its dependencies in its constructor (or through property setters if that’s what you want) and only needs to implement the Handle(TRequest) method. It can of course also implement the BeforeHandle(TRequest) and AfterHandle(TRequest) methods when it makes sense.

This is a simple example of an NHibernate-enabled base class for Request Handlers. We also have one of these for projects that don’t use NHibernate but use our custom DAL instead. It’s virtually identical to this one though. The important part to remember is that these classes are very simple, yet still give you a lot of flexibility and power.

In fact, most of our applications’ Request Handlers don’t inherit directly from the NhRequestHandler (or the AdoNetRequestHandler). In most cases, we have another class in between the actual Request Handlers and the NhRequestHandler which adds custom logic for authentication, provides hooks (virtual methods) for authorization and whatever else that might make sense (like setting up the user’s context for the duration of the request).

In fact, here’s a simple, real world example:

    public abstract class BusinessRequestHandler<TRequest, TResponse> : NhRequestHandler<TRequest, TResponse>

        where TRequest : MyApplicationRequest

        where TResponse : Response

    {

        public IAuthenticator Authenticator { get; set; }

        public IUserCredentialRepository UserCredentialRepository { get; set; }

        public IUserContext UserContext { get; set; }

 

        public override void BeforeHandle(TRequest request)

        {

            var authenticatedRequest = request as AuthenticatedRequest;

 

            if (authenticatedRequest != null)

            {

                var userCredential = UserCredentialRepository.FindByLoginName(authenticatedRequest.LoginName);

 

                if (!Authenticator.Authenticate(authenticatedRequest.LoginName, authenticatedRequest.PasswordHash,

                    userCredential))

                {

                    throw new SecurityException(MessageKeys.RequestCouldNotBeAuthenticated);

                }

 

                UserContext.CurrentLanguage = authenticatedRequest.CurrentLanguage;

                UserContext.UserId = userCredential.Id;

                UserContext.LoginName = authenticatedRequest.LoginName;

            }

        }

    }

For this particular application, each Request Handler inherits from this BusinessRequestHandler and before the actual Handle(TRequest) method is called, the implementation of BeforeHandle(TRequest) will make sure that the current request is properly authenticated and if so, will store some user data in the UserContext instance so that each Request Handler can make use of it. This means that each single request gets authenticated (we obviously make use of caching here). If however you only want to authenticate say, the first request of each batch instead of all of them then you can inherit from the default RequestProcessor class (covered in the previous post in this series) and plug in the authentication logic at that point. The point is that this entire approach is extremely flexible.

Here’s another real world example:

    public abstract class BusinessRequestHandler<TRequest, TResponse> : NhRequestHandler<TRequest, TResponse>

        where TRequest : Request

        where TResponse : Response

    {

        public IAuthenticator Authenticator { get; set; }

        public IAuthenticationContext AuthenticationContext { get; set; }

        public IAuthorizationProvider AuthorizationProvider { get; set; }

        public IConfigurationProvider ConfigurationProvider { get; set; }

 

        protected override void DisposeManagedResources()

        {

            AuthorizationProvider = null;

            AuthenticationContext = null;

            ConfigurationProvider = null;

            base.DisposeManagedResources();

        }

 

        public override void BeforeHandle(TRequest request)

        {

            log4net.MDC.Set("Tenant", ConfigurationProvider.TenantName);

            base.BeforeHandle(request);

            Authenticate(request);

            Authorize(request);

        }

 

        public virtual void Authorize(TRequest request) {}

 

        private void Authenticate(TRequest request)

        {

            var emsRequest = request as EmsRequest;

 

            if (emsRequest != null)

            {

                if (Authenticator.AreValidCredentials(emsRequest.ApplicationUserId, emsRequest.ApplicationUserName, emsRequest.PasswordHash))

                {

                    AuthenticationContext.SetContextData(emsRequest.ApplicationUserId, emsRequest.ApplicationUserName);

                }

                else

                {

                    throw new SecurityException("request could not be authenticated!");

                }

            }

        }

    }

Very similar to the previous one, but this version includes a virtual Authorize(TRequest) method which each Request Handler can implement to perform Authorization in a uniform manner.

As you can see, we can deal with a lot of cross-cutting concerns in a single place without having to resort to Aspect Oriented Programming. That’s not to say that Aspect Oriented Programming is bad (in fact, i quite like it), but in a lot of cases you can achieve the same result with simple Object Oriented Programming.

Anyway, once you have this in place you can create very simple Request Handlers which simply inherit from your custom base handler class, declare their dependencies as either constructor arguments or as public properties so the IOC container can inject them, and can then focus on simply implementing whatever logic is required to handle a specific request. They can be sure that everything is properly set up for them to function in the environment that they are ment to function in, and that all of this set up only occurs in one place in the code.

Posted in Request/Response Service Layer | 1 Comment »

Request/Response Service Layer: Processing Requests

Posted by Davy Brion on 9th November 2009

Note: This post is part of a series. Be sure to read the introduction here.

The Request/Response Service Layer (RRSL) only defines one service operation, or entry point if you will:

    public interface IRequestProcessor : IDisposable

    {

        Response[] Process(params Request[] requests);

    }

The topic of this post is how we go from that interface, to some kind of mechanism that can actually process the incoming requests and send the appropriate responses back to the client. Note that i make a difference between processing requests and handling them. Processing the requests is done by the Request Processor, and each request will be handled by its very own Request Handler. The Request Processor accepts all incoming requests, delegates the actual handling of each request to the correct Request Handler and will then send back all of the responses to the client. Handling requests and how Request Handlers work is the topic of a different post, but you do already need to know that each Request Handler will implement the following interface:

    public interface IRequestHandler<TRequest> : IRequestHandler where TRequest : Request

    {

        Response Handle(TRequest request);

    }

Unfortunately, when trying to work with Generic types in .NET in a generic manner you typically need to resort to a non-generic version to be able to handle your generic usage (read that sentence a few more times if you didn’t get it):

    public interface IRequestHandler : IDisposable

    {

        Response Handle(Request request);

        Response CreateDefaultResponse();

    }

The Request Processor will make use of the non-generic IRequestHandler interface, while each Request Handler will simply implement the generic version.

We’ll begin with a relatively simple implementation of the Request Processor, which is the bare minimum that you’ll need to get this working. We’ll then work our way up to include exception handling and logging.

This is the simplest version of the Request Processor:

    public class RequestProcessor : IRequestProcessor

    {

        // the server-side implementation should be stateless, but the IRequestProcessor

        // interface defines the Dispose method, so we just provide an empty one here

        public void Dispose() { }

 

        public Response[] Process(params Request[] requests)

        {

            if (requests == null) return null;

 

            var responses = new List<Response>(requests.Length);

 

            foreach (var request in requests)

            {

                using (var handler = (IRequestHandler)IoC.Container.Resolve(GetHandlerTypeFor(request)))

                {

                    try

                    {

                        var response = GetResponseFromHandler(request, handler);

                        responses.Add(response);

                    }

                    finally

                    {

                        IoC.Container.Release(handler);

                    }

                }

            }

 

            return responses.ToArray();

        }

 

        private static Type GetHandlerTypeFor(Request request)

        {

            // get a type reference to IRequestHandler<ThisSpecificRequestType>

            return typeof(IRequestHandler<>).MakeGenericType(request.GetType());

        }

 

        private Response GetResponseFromHandler(Request request, IRequestHandler handler)

        {

            BeforeHandle(request);

            var response = handler.Handle(request);

            AfterHandle(request);

            return response;

        }

 

        protected virtual void BeforeHandle(Request request) { }

        protected virtual void AfterHandle(Request request) { }

    }

First of all, you’ll notice that the RequestProcessor has an empty Dispose method. The only reason it’s there is because the IRequestProcessor interface will also be used client-side, and it’s very important that client-side implementations of the IRequestProcessor interface are disposable. We’ll cover this in detail in a future post of this series though so let’s just focus on how the requests are processed.

As you can see, it’s pretty simple and straightforward. For each request that needs to be processed, we ask our IOC container to resolve the actual handler for it, based on the convention that each Request Handler must implement the generic IRequestHandler interface with the type of the request as the generic type argument. Once we have a reference to the correct handler, we can call the handler’s Handle method, but before we do that we call the protected virtual BeforeHandle method of the Request Processor. Then we call the actual Handle method on the handler, and after that we call the protected virtual AfterHandle method. Those 2 virtual methods are only there to make it easy to inherit from the Request Processor in your application to add something extra before and/or after the handler is called. After that, the responses are sent back to the client and that’s all there is to it.

Again, this is the simplest implementation. Its biggest limitation right now is that it doesn’t properly deal with failed requests. In its current form, once a request handler throws an exception, the exception will not be caught by the Request Processor and the call to the Request Processor will simply fail. And if you’re using this with WCF, the client’s channel will be faulted as well. The biggest question is of course: what should happen if one of the requests of the batch fails? Should the entire batch be considered a failure? Should default responses be returned for failed requests? If the second request of a batch fails, should we still attempt to handle the ones that follow the failed request in the batch?

Many people will have their own preference on how to deal with this, but it’s important to realize that each approach has it pro’s and con’s and i don’t consider any of them to be perfect. For instance, most of our applications use NHibernate. Each Request Handler will set up and manage its own Unit Of Work. If there is batch of 3 requests, and the second request fails, we have no way of rolling back the transaction of the first request because its Unit Of Work has already been completed (and thus, its transaction is already committed). That is a deliberate choice that we made. You could also implement your Request Processor in a way that a Unit Of Work is set up, and that each Request Handler shares the same Unit Of Work. This would give you the ability to roll back the transaction of the first request if the second one failed. It also means that each request could potentially be impacted by previous requests in the batch, depending on what a previous request left in the Session Cache of NHibernate and the thought of that doesn’t really sit well with me either.

I’ve chosen the following approach to dealing with exceptions, and after using this for over a year, i’m still happy with it:

  • The Request Processor has no knowledge of a Request Handler’s Unit Of Work.
  • The Request Processor must always return a response for each request it received.
  • If the handling of a request failed, the Request Processor must return a response object with the details of the actual exception.
  • If a previous request in a batch failed, the Request Processor must return a default response instance for the subsequent requests indicating that they couldn’t be handled because an earlier request in the batch already failed.

Our previously simple Process method now looks like this:

        public Response[] Process(params Request[] requests)

        {

            if (requests == null) return null;

 

            var responses = new List<Response>(requests.Length);

 

            bool exceptionsPreviouslyOccurred = false;

 

            foreach (var request in requests)

            {

                using (var handler = (IRequestHandler)IoC.Container.Resolve(GetHandlerTypeFor(request)))

                {

                    try

                    {

                        if (!exceptionsPreviouslyOccurred)

                        {

                            var response = GetResponseFromHandler(request, handler);

                            exceptionsPreviouslyOccurred = response.ExceptionType != ExceptionType.None;

                            responses.Add(response);

                        }

                        else

                        {

                            var response = handler.CreateDefaultResponse();

                            response.ExceptionType = ExceptionType.EarlierRequestAlreadyFailed;

                            response.Exception = new ExceptionInfo(new Exception(ExceptionType.EarlierRequestAlreadyFailed.ToString()));

                            responses.Add(response);

                        }

                    }

                    finally

                    {

                        IoC.Container.Release(handler);

                    }

                }

            }

 

            return responses.ToArray();

        }

It now uses a boolean to keep track of whether the batch can still be considered successful. Once a request failed, it will start adding default responses which indicate that a previous request in the batch failed. We also have to modify the GetResponseFromHandler method so that it can add the actual exception to the response in case of failure:

        private Response GetResponseFromHandler(Request request, IRequestHandler handler)

        {

            try

            {

                BeforeHandle(request);

                var response = handler.Handle(request);

                AfterHandle(request);

                return response;

            }

            catch (Exception e)

            {

                var response = handler.CreateDefaultResponse();

                response.Exception = new ExceptionInfo(e);

                SetExceptionType(response, e);

                return response;

            }

        }

 

        private static void SetExceptionType(Response response, Exception exception)

        {

            if (exception is BusinessException)

            {

                response.ExceptionType = ExceptionType.Business;

                return;

            }

 

            if (exception is SecurityException)

            {

                response.ExceptionType = ExceptionType.Security;

                return;

            }

 

            response.ExceptionType = ExceptionType.Unknown;

        }

I agree that it’s not pretty, but it works :)

Alright, we now have a Request Processor that can reroute each request to the appropriate Request Handler and can deal with exceptions in a manner that is sufficient for me. Again, if you want to use a different approach with regards to dealing with failed requests in a batch, you are obviously free to do whatever you prefer :)

I’d also like to point out that the exception handling that you just saw is the only exception handling that we need to implement in our service layer. We don’t need any repetitive error handling code and we don’t need any Aspect Oriented Programming tricks to deal with it all over the place either. We also don’t need to implement a clumsy interface which then has to be registered with WCF ;)

This version of the Request Processor is still not complete though. We still need proper logging. Every exception that occurs obviously has to be logged properly. I also want to log each handled request that took too long to process, or each batch of requests that took too long in its entirety. And as you can probably guess by now, the logging code will only need to be written once and it will work for the entire service layer :)

So to wrap up this post, here’s the final version of the Request Processor that we use for all our projects:

    public class RequestProcessor : IRequestProcessor

    {

        private readonly ILog logger = LogManager.GetLogger(typeof(RequestProcessor));

        private readonly ILog performanceLogger = LogManager.GetLogger("PERFORMANCE");

 

        // the server-side implementation should be stateless, but the IRequestProcessor

        // interface defines the Dispose method, so we just provide an empty one here

        public void Dispose() { }

 

        public Response[] Process(params Request[] requests)

        {

            if (requests == null) return null;

 

            var responses = new List<Response>(requests.Length);

 

            bool exceptionsPreviouslyOccurred = false;

 

            var batchStopwatch = Stopwatch.StartNew();

 

            foreach (var request in requests)

            {

                try

                {

                    using (var handler = (IRequestHandler)IoC.Container.Resolve(GetHandlerTypeFor(request)))

                    {

                        var requestStopwatch = Stopwatch.StartNew();

 

                        try

                        {

                            if (!exceptionsPreviouslyOccurred)

                            {

                                var response = GetResponseFromHandler(request, handler);

                                exceptionsPreviouslyOccurred = response.ExceptionType != ExceptionType.None;

                                responses.Add(response);

                            }

                            else

                            {

                                var response = handler.CreateDefaultResponse();

                                response.ExceptionType = ExceptionType.EarlierRequestAlreadyFailed;

                                response.Exception = new ExceptionInfo(new Exception(ExceptionType.EarlierRequestAlreadyFailed.ToString()));

                                responses.Add(response);

                            }

                        }

                        finally

                        {

                            requestStopwatch.Stop();

 

                            if (requestStopwatch.ElapsedMilliseconds > 100)

                            {

                                performanceLogger.Warn(string.Format("Performance warning: {0}ms for {1}", requestStopwatch.ElapsedMilliseconds, handler.GetType().Name));

                            }

 

                            IoC.Container.Release(handler);

                        }

                    }

                }

                catch (Exception e)

                {

                    logger.Error(e);

                    throw;

                }

            }

 

            batchStopwatch.Stop();

 

            if (batchStopwatch.ElapsedMilliseconds > 200)

            {

                StringBuilder builder = new StringBuilder();

 

                foreach (var request in requests)

                {

                    builder.Append(request.GetType().Name + ", ");

                }

                builder.Remove(builder.Length - 2, 2);

 

                performanceLogger.Warn(string.Format("Performance warning: {0}ms for the following batch: {1}", batchStopwatch.ElapsedMilliseconds, builder));

            }

 

            return responses.ToArray();

        }

 

        private static Type GetHandlerTypeFor(Request request)

        {

            // get a type reference to IRequestHandler<ThisSpecificRequestType>

            return typeof(IRequestHandler<>).MakeGenericType(request.GetType());

        }

 

        private Response GetResponseFromHandler(Request request, IRequestHandler handler)

        {

            try

            {

                BeforeHandle(request);

                var response = handler.Handle(request);

                AfterHandle(request);

                return response;

            }

            catch (Exception e)

            {

                logger.Error("RequestProcessor: unhandled exception while handling request!", e);

                var response = handler.CreateDefaultResponse();

                response.Exception = new ExceptionInfo(e);

                SetExceptionType(response, e);

                return response;

            }

        }

 

        private static void SetExceptionType(Response response, Exception exception)

        {

            if (exception is BusinessException)

            {

                response.ExceptionType = ExceptionType.Business;

                return;

            }

 

            if (exception is SecurityException)

            {

                response.ExceptionType = ExceptionType.Security;

                return;

            }

 

            response.ExceptionType = ExceptionType.Unknown;

        }

 

        protected virtual void BeforeHandle(Request request) { }

        protected virtual void AfterHandle(Request request) { }

    }

Yes, the logging and exception handling code looks ugly. I could clean it up and extract it to more methods, but since it only occurs in this single class i don’t really see the point and it might actually reduce readability in this particular case.

Posted in Request/Response Service Layer | 9 Comments »

Request/Response Service Layer: Requests And Responses

Posted by Davy Brion on 8th November 2009

Note: This post is part of a series. Be sure to read the introduction here.

In a typical WCF service, you’ll have one or more Service Contracts, and each Service Contract will define one or more Service Operations. These operations are just methods that you can call on the service. An operation can have parameters and it can have a return value. Most people typically expose multiple operations on their services for each piece of functionality they want their service to offer to consumers.

The Request/Response Service Layer (RRSL) takes a different approach. It has one service contract, with only one operation defined:

    public interface IRequestProcessor : IDisposable

    {

        Response[] Process(params Request[] requests);

    }

Notice the lack of the typical WCF attributes such as ServiceContract and OperationContract. The RRSL is actually completely independent from WCF and only uses WCF as a transport medium. That’s the topic of another post though, so let’s get back to the topic at hand: requests and responses.

As you can see, the Process method receives an array of Request objects and returns an array of Response objects. So what exactly is a Request and what is a Response? This is what they look like:

    public class Request

    {

    }

 

    public class Response

    {

        public ExceptionInfo Exception { get; set; }

        public ExceptionType ExceptionType { get; set; }

    }

Both are classes that you should derive specific Request and Response types from. The Response class automatically comes with an ExceptionInfo class (which is pretty much identical to WCF’s ExceptionDetail class and only exists because Silverlight 2 did not support ExceptionDetail) and an ExceptionType enum:

    public enum ExceptionType

    {

        None,

        Business,

        Security,

        EarlierRequestAlreadyFailed,

        Unknown

    }

The ExceptionInfo class (or ExceptionDetail if you would prefer to use that) does not contain the original Exception object, so the ExceptionType enumeration can be used to handle each type of exception differently on the client-side. Obviously, if a Request was handled without problems, the ExceptionInfo property of its Response will be null, and the ExceptionType property will be set to ExceptionType.None.

The idea is basically that instead of defining operations on your services, you create a specific Request class and a corresponding Response class for each operation that you would normally expose on your service. The request type is the operation, its properties are the operation’s parameters and the Response type is the operation’s return value. Note that you can define multiple properties on your Response types, effectively giving you the ability to support multiple return values for an operation without having to use out parameters.

A simple example of a Request and its Response can look like this:

    public class GetProductOverviewsRequest : Request

    {

        public string NamePattern { get; set; }

        public int? CategoryId { get; set; }

        public int? SupplierId { get; set; }

    }

 

    public class GetProductOverviewsResponse : Response

    {

        public ProductOverviewDto[] Products { get; set; }

    }

Note that by default, if you’re using at least .NET 3.5 SP1, you do not need to mark your Request/Response types as Serializable or apply the DataContract/DataMember attributes on them if the assembly containing the Request/Response types can be shared between both your service and your clients. If your service needs to be interoperable with other platforms or you can’t share the assembly containing the types, then you obviously do need to use the DataContract/DataMember attributes but if you’re only communicating with .NET clients and you can share the assembly, it’s not needed. Provided that all of the clients also use at least .NET 3.5 SP1 obviously.

At this point you might be wondering: “what exactly is the benefit of doing this?”. Well, at this point in the series there is only one benefit that you can see already: the fact that the Process method of the service receives an array of requests and returns an array of corresponding responses. That means that you can easily send multiple requests to the service with only one roundtrip, which can greatly reduce the network communication overhead that you can otherwise suffer with typical Service Contracts, especially if their interface is too chatty.

There are many more benefits to using the RRSL, but you’ll have to read the rest of the posts in the series to learn about those :)

Posted in Request/Response Service Layer | 11 Comments »