The Inquisitive Coder – Davy Brion's Blog

Trying to walk that thin line between intelligence and ignorance

Request/Response Service Layer: Requests And Responses

Posted by Davy Brion on November 8th, 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 :)

11 Responses to “Request/Response Service Layer: Requests And Responses”

  1. Aaron Fischer Says:

    Why pass the exception parameters in every response? Since you have OO, you can return a strongly typed ErrorResponse.

  2. Davy Brion Says:

    @Aaron

    that would work if the client would retrieve its response based on the index of the corresponding request, but you’ll see in a future post that we retrieve the response based on its expected type, not the index.

  3. Awkward Coder Says:

    How does the client of the (WCF) service generate a proxy for all the different message types?

    In other words how does the client know about the structure of ‘GetProductOverviewsRequest’ when it is not explicitly exposed\declared on the interface.

  4. Awkward Coder Says:

    DOH!

    Ignore my last comment…

  5. Awkward Coder Says:

    ‘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…’

    Should mention you need to use the ‘KnownType’ attributes on the base ‘Request’ & ‘Response’ types to include all derived types in the client side proxy.

  6. Davy Brion Says:

    no i have a better solution for that, which you’ll see in the Exposing Through WCF post :)
    (which is currently scheduled for wednesday)

  7. Aaron Fischer Says:

    Fetching by response means one request type to one response type, I am not sure in the long term that’s good. It does interfere with generic entity requests/responses for example.

  8. Davy Brion Says:

    You can add multiple requests of the same type, but then you’d have to add them with a specific key value, and retrieve the responses of that type with the correct key value

    that’s also covered in a future post :)

    what exactly do you mean with generic entity requests/responses?

  9. Awkward Coder Says:

    let me guess you’re going to expose the message schemas via the actual service…

  10. Aaron Fischer Says:

    generic like

    EntityListRequest : Request
    {
    Criteria{get;set}
    Id{get;set}
    }
    EntityListResponse : Response
    {
    IList Entities
    }

  11. Davy Brion Says:

    @Aaron

    oh that would work with the keyed adding/retrieving of the requests/responses… guess you have to wait on the posts about client-side usage ;)

    @Awkward Coder

    Instead of using the KnownType attribute all over the place, we just register them once before the service starts up and then use WCF’s ServiceKnownType to dynamically fetch the list of known types once before the service is first used.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>