Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Design Patterns for ASP.NET Developers, Part 1: Basic Patterns : Page 4

Most Design Pattern documentation targets desktop applications or discusses pattern theory, but in this series you'll find a discussion and examples of patterns specifically targeted at ASP.NET.


advertisement

Visual Studio and the Service Agent and Proxy Patterns
The Proxy and Broker patterns provide a natural technique for connecting to and using remote services without forcing the use of O/S or application-specific protocols such as DCOM. In particular, they are ideal for use with Web services. In Visual Studio, when developers add a Web Reference to a project, Visual Studio automatically collects the Web service description (including a WSDL contract file). This lets the code generate a suitable proxy class that exposes the methods of the remote service to code in the application. Code in the application can then use the remote service by creating an instance of the proxy class and calling the exposed methods defined in the contract. For example, here's the code used in the sample application to call the CustomerName method of the DemoService service:

   protected void btn_WSProxy_Click(object sender, EventArgs e)
   // display name of specified customer using the web service 
   {
      try
      {
         // get details from web service
         // use 'using' construct to ensure disposal after use
         using (LocalDemoService.Service svc = new 
            LocalDemoService.Service())
         {
            Label1.Text += "Customer name from web service: " 
               + svc.CustomerName(txtID_WSProxy.Text);
         }
      }
      catch (Exception ex)
      {
         Label1.Text += "PAGE ERROR: " + ex.Message;
      }
      Label1.Text += "<p />";
   }

One issue with using Web services is the difficulty in raising exceptions that the client can handle. The usual approach is to return a specific value that indicates the occurrence of an exception or failure. Therefore, one useful feature that a Service Agent (which wraps the Web Reference to add extra functionality) can offer is detecting exceptions by examining the returned value and raising a local exception to the calling code.

The following code, from the ServiceAgent.cs class in the sample application, contains a constructor that instantiates the local proxy for the service and stores a reference to it. Then the GetCustomerName method can call the CustomerName method of the Web service and examine the returned value. If the return value starts with the text "ERROR:" the code raises an exception that the calling routine can handle.

The GetCustomerName method also performs additional processing on the value submitted to it. The Web service only matches on a complete customer ID (five characters in the example), and supports partial matches only if the customer ID ends with a wildcard character. The GetCustomerName method in the Service Agent checks for partial customer ID values and adds the wildcard character so that the service will return a match on this partial value:



   // wraps the Web Reference and calls to web service
   // to perform auxiliary processing
   public class ServiceAgent
   {
      LocalDemoService.Service svc = null;
   
      public ServiceAgent()
      {
         // create instance of remote web service
         try
         {
            svc = new LocalDemoService.Service();
         }
         catch (Exception ex)
         {
            throw new Exception(
               "Cannot create instance of remote service", ex); 
         }
      }
   
      public String GetCustomerName(String custID)
      {
         // add '*' to customer ID if required
         if (custID.Length < 5)
         {
            custID = String.Concat(custID, "*");
         }
         // call web service and raise a local exception
         // if an error occurs (i.e. when the returned
         // value string starts with "ERROR:")
         String custName = svc.CustomerName(custID);
         if (custName.Substring(0,6) == "ERROR:")
         {
            throw new Exception(
               "Cannot retrieve customer name - " + custName);       
         }
         return custName;
      }
   }

To use this simple example of a Service Agent, code in the Default.aspx page of the sample application instantiates the Service Agent class and calls its GetCustomerName method. It also traps any exception that the Service Agent might generate, displaying the message from the InnerException generated by the agent:

   protected void btn_WSAgent_Click(object sender, EventArgs e)
   // display name of specified customer using the Service Agent
   // extra processing in Agent allows for match on partial ID
   {
      try
      {
         // get details from Service Agent
         ServiceAgent agent = new ServiceAgent();
         Label1.Text += "Customer name from Service Agent: " 
            + agent.GetCustomerName(txtID_WSAgent.Text);
      }
      catch (Exception ex)
      {
         Label1.Text += "PAGE ERROR: " + ex.Message + "<br />";
         if (ex.InnerException != null)
         {
            Label1.Text += "INNER EXCEPTION: " + 
               ex.InnerException.Message;
         }
      }
      Label1.Text += "<p />";
   }


Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap