Request/Response Service Layer

Request/Response Service Layer: Synchronous Client-Side Usage

4 commentsWritten on November 12th, 2009 by
Categories: Request/Response Service Layer

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.

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

14 commentsWritten on November 11th, 2009 by
Categories: Request/Response Service Layer

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 ;)

Request/Response Service Layer: Handling Requests

9 commentsWritten on November 10th, 2009 by
Categories: Request/Response Service Layer

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.

Request/Response Service Layer: Processing Requests

9 commentsWritten on November 9th, 2009 by
Categories: Request/Response Service Layer

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.

Request/Response Service Layer: Requests And Responses

11 commentsWritten on November 8th, 2009 by
Categories: Request/Response Service Layer

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 :)