Programming4us
         
 
 
Programming

Programming WCF Services : The Response Service (part 2) - Client-Side Programming

3/8/2012 11:27:21 AM

9.9.2. Client-Side Programming

My HeaderClientBase<T,H> proxy base class is designed to automate passing information in the headers from the client to the service:

public abstract class InterceptorClientBase<T> : ClientBase<T> where T : class
{
   protected virtual void PreInvoke(ref Message request)
   {}
   //More members
}
public abstract partial class HeaderClientBase<T,H> : InterceptorClientBase<T>
                                                      where T : class
{
   public H Header
   {get;protected set;}

   public HeaderClientBase(H header);
   public HeaderClientBase(H header,string endpointName);

   //More members
}

					  
However, when it comes to the response context, there are differences compared with the raw headers management: specifically, changing the context (that is, the headers) on each call as opposed to setting it only at construction time, generating method IDs and providing them to the client, and enqueuing rather than merely invoking the service call. While the client can easily use my HeaderClientBase<T,H> to do all that, all clients will have to repeat such code for every contract and proxy they have. It is better to automate and encapsulate these steps in a dedicated proxy base class such as my ClientResponseBase<T>, shown in Example 3.
Example 3. The ClientResponseBase<T> class
public abstract class ClientResponseBase<T> :
                               HeaderClientBase<T,ResponseContext> where T : class
{
   protected readonly string ResponseAddress;

   public ClientResponseBase(string responseAddress)
   {
      ResponseAddress = responseAddress;
      Endpoint.VerifyQueue();
   }
   public ClientResponseBase(string responseAddress,string endpointName)
   {...}
   public ClientResponseBase(string responseAddress,
                             NetMsmqBinding binding,EndpointAddress address)
   {...}

   /* More constructors */

   protected override void PreInvoke(ref Message request)
   {
      string methodId = GenerateMethodId();
      Header = new ResponseContext(ResponseAddress,methodId);
      base.PreInvoke(ref request);
   }
   protected virtual string GenerateMethodId()
   {
      return Guid.NewGuid().ToString();
   }
}

					  

The constructors of ClientResponseBase<T> accept the response address and the regular proxy parameters, such as the endpoint name, address, and binding. The constructors store the response address in the read-only public field ResponseAddress. In addition, the constructors use the VerifyQueue() endpoint extension method to verify that the service queue (and the DLQ) exists and to create it if necessary.

ClientResponseBase<T> provides the virtual GenerateMethodId() method, which by default uses a GUID for the method ID. However, your subclasses of ClientResponseBase<T> can override it and provide their own unique strings, such as an incremented integer.

The heart of ClientResponseBase<T> is the overridden PreInvoke() method. PreInvoke() is defined as virtual in the InterceptorClientBase<T> base class of HeaderClientBase<T,H>. InterceptorClientBase<T> is part of a generic interception framework I wrote  that enables you to perform custom pre-call and post-call interception steps. For every operation invoked by the client, PreInvoke() generates a new method ID, provides it to a new ResponseContext object (along with the response address supplied to the constructor), and assigns the new ResponseContext object to the Header property of HeaderClientBase<T,H>. Thanks to generics, Header is of the type ResponseContext.

2.1. Using ClientResponseBase<T>

You use ClientResponseBase<T> like a regular proxy; for example, given this calculator contract:

[ServiceContract]
interface ICalculator
{
   [OperationContract(IsOneWay = true)]
   void Add(int number1,int number2);
   //More operations
}

Example 4 shows the matching service proxy.

Example 4. Deriving from ClientResponseBase<T>
class CalculatorClient : ClientResponseBase<ICalculator>,ICalculator
{
   public CalculatorClient(string responseAddress) : base(responseAddress)
   {}
   public CalculatorClient(string responseAddress,string endpointName) :
                                                 base(responseAddress,endpointName)
   {}
   public CalculatorClient(string responseAddress,
                           NetMsmqBinding binding,EndpointAddress address) :
                                             base(responseAddress,binding,address)
   {}
   //More constructors

   public void Add(int number1,int number2)
   {
      Channel.Add(number1,number2);
   }

   //More operations
}

					  

Using the proxy in Example 9-24 yields this straightforward client code:

string responseAddress = "net.msmq://localhost/private/MyCalculatorResponseQueue";

CalculatorClient proxy = new CalculatorClient(responseAddress);
proxy.Add(2,3);
proxy.Close();

					  

Note how closely the client that provides the response address to the proxy corresponds to a client that provides a duplex callback object to a proxy. In the queued services world, the response service address is the equivalent callback reference.


Note:

A queued response service is not limited to being used only with a queued service. You can use the same technique to pass the address and method ID to a connected service and have that service respond to a client-provided queued response service. You will need to rework ClientResponseBase<T> so that it uses only Binding.


When managing the responses on the client side using a ClientResponseBase<T>-derived proxy, it is often very handy to have the invoking client obtain the method ID used to dispatch the call. You can do this easily with the Header property:

CalculatorClient proxy = new CalculatorClient(responseAddress);
proxy.Add(2,3);
string methodId = proxy.Header.MethodId;
proxy.Close();
Other -----------------
- Programming WCF Services : Queued Versus Connected Calls - Requiring Queuing
- Programming WCF Services : Queued Services - Playback Failures
- DotNetNuke Skinning : Package and Deploy
- Unit Testing in Visual Studio 2010 (part 2) - Running a battery of tests
- Unit Testing in Visual Studio 2010 (part 1) - Creating unit tests
- Microsoft ASP.NET 3.5 : AJAX-Enabled Web Services - Remote Calls via Page Methods
- Microsoft ASP.NET 3.5 : WCF Services for ASP.NET AJAX Applications
- Mobile Game Networking Essentials : Network Programming and J2ME
- Mobile Game Networking Essentials : Multiplayer Game Basics & Network Game Problems and Solutions
- Software Testing with Visual Studio Team System 2008 : Debug and running web test (part 2) - Running the test
- Software Testing with Visual Studio Team System 2008 : Debug and running web test (part 1) - Settings for .testrunconfig file
- Visual Studio Team System 2008 : Web test editor (part 3) - Toolbar properties
- Visual Studio Team System 2008 : Web test editor (part 2) - Other request properties
- Visual Studio Team System 2008 : Web test editor (part 1) - Web test properties & Web test request properties
- Build Mobile Websites and Apps for Smart Devices : Design for Mobile - Standing on the Shoulders of Giants
- Build Mobile Websites and Apps for Smart Devices : Design for Mobile - Build a Better Mouse
- Developing BlackBerry Tablet Applications with Flex 4.5 : Create a Flex Mobile Project (part 4) - Reading and setting author information for debug
- Developing BlackBerry Tablet Applications with Flex 4.5 : Create a Flex Mobile Project (part 3) - Setup Device
- Developing BlackBerry Tablet Applications with Flex 4.5 : Create a Flex Mobile Project (part 2) - Setup Simulator
- Developing BlackBerry Tablet Applications with Flex 4.5 : Create a Flex Mobile Project (part 1)
 
 
Most View
- Exchange Server 2010 : Manage Web-Based Email Access (part 1) - Configure OWA URLs
- Windows Server 2008 : Use Initial Configuration Tasks
- BizTalk Server 2009 : The core principles of a service-oriented architecture (part 3)
- Windows 7 : Working with Network Files Offline (part 2) - Changing the Amount of Disk Space Used by Offline Files
- Programming for Aero Glass Functionality : WORKING WITH THE WINDOWS 7 TASK DIALOGS
- Using XML in SQL Server 2008: Relational Data As XML - The FOR XML Modes (part 4) - EXPLICIT Mode
- Installing Systems Management Server Installer
- Microsoft Exchange Server 2003: Configuring Recipient Objects (part 7) - Moving Mailboxes with the Exchange Task Wizard
- Exchange 2007 : Enable Local Continuous Replication
- Windows Server 2008 : Installing the Web Server Role (part 7)
Top 10
- Implementing Edge Services for an Exchange Server 2007 Environment : Utilizing the Basic Sender and Recipient Connection Filters (part 3) - Configuring Recipient Filtering
- Implementing Edge Services for an Exchange Server 2007 Environment : Utilizing the Basic Sender and Recipient Connection Filters (part 2)
- Implementing Edge Services for an Exchange Server 2007 Environment : Utilizing the Basic Sender and Recipient Connection Filters (part 1)
- Implementing Edge Services for an Exchange Server 2007 Environment : Installing and Configuring the Edge Transport Server Components
- What's New in SharePoint 2013 (part 7) - BCS
- What's New in SharePoint 2013 (part 6) - SEARCH
- What's New in SharePoint 2013 (part 6) - WEB CONTENT MANAGEMENT
- What's New in SharePoint 2013 (part 5) - ENTERPRISE CONTENT MANAGEMENT
- What's New in SharePoint 2013 (part 4) - WORKFLOWS
- What's New in SharePoint 2013 (part 3) - REMOTE EVENTS