Showing posts with label Business Logic Layer. Show all posts
Showing posts with label Business Logic Layer. Show all posts

Monday, April 09, 2012

More On Closing WCF Connections

Some time ago I blogged about how to implement a WCF client in C# using VS2008. In particular I mentioned that implementing the client side code with a using statement may potentially lead to problems as – against their own advice – Microsoft chose to implement the Dispose() method of class System.ServiceModel.ClientBase<TChannel> in such a way that it can throw exceptions. (Dispose() implementations should not throw exceptions.) This implementation that violates Microsoft’s own guideline is also described in an article where Microsoft recommends not to use “using” when working with WCF clients.

In this blog post I’ll revisit the options for handling client side code. In the meantime I’ve moved to VS2010 and I’m using .NET 4.0. To get started let’s recall the code from back then:

var client = new PondServiceClient();

try {
   _pondStatusMessage.Text = _pondNameTextBox.Text +
      (client.IsFrozen(_pondNameTextBox.Text) ?
      " is frozen." : " free of ice.");
   client.Close();
}
catch (CommunicationException ex) {
   // Handle exception
   client.Abort();
}
catch (TimeoutException ex) {
   // Handle exception
   client.Abort();
}
catch (Exception ex) {
   // Handle exception
   client.Abort();
}

So the canonical form (also described on MSDN) is to check for CommunicationException and TimeoutException. If the service defines Service Fault's you may want to catch those exceptions (FaultException<T>) as well.

It would be great if there were ways to fix this problem as there is one more issue with using the canonical way. Imagine you have lots of touch points between your client and a service. Wouldn’t it be nice if you could avoid all that try-catch business? It looks like a lot of code duplication after all.

Marc Gravell’s Solution

One possible solution is described by Marc Gravell in his blog. He makes extensive use of generics. Using Marc’s solution the above code would look something like this:

using (var client = new Proxy().Wrap()) {
   _pondStatusMessage.Text = _pondNameTextBox.Text +
      (client.BaseObject.IsFrozen(_pondNameTextBox.Text) ?
      " is frozen." : " free of ice.");
}

I agree with Marc that this solution would be safe, easy to call and would eliminate the code duplications. His solution calls the service client’s Dispose() method (ClientBase<TChannel>.Dispose()) but wraps it inside a try-catch construct. If an exception is thrown by the Dispose() it is swallowed.

The first concern I have with this solution is that it doesn’t call Abort() and Close() respectively as per Microsoft’s recommendation. It just swallows the exception that might be thrown by the Dispose method.

The second concern I have is that the expression “new Proxy().Wrap()” doesn’t appear very intuitive and easy to understand. This is probably a minor point as with more experience in using this solution one can will become used to it.

Jeremy Jameson’s Solution

Another option can be found at Jeremy Jameson’s blog. Jeremy suggests to derive a class and add a new implementation for Dispose(). To stay with the pond service example, that new class would then look as follows:

public class PondServiceClientWithDisposeFix 
   : PondServiceClient, IDisposable {
   void IDisposable.Dispose() {
      if (this.State == CommunicationState.Faulted) {
         this.Abort();
      }
      else if (this.State != CommunicationState.Closed) {
         this.Close();
      }
   }
}

With this class in place the implementation of the client side could then be re-written as follows:

using(var client = new PondServiceClientWithDisposeFix()) {
   _pondStatusMessage.Text = _pondNameTextBox.Text +
      (client.IsFrozen(_pondNameTextBox.Text) ?
      " is frozen." : " free of ice.");
}

Very elegant, easy to understand and correct by the looks of it. I was tempted to use this option if it wasn’t for a concern that I have with this. With reverse engineering it is possible to find out what ClientBase<TChannel>.Dispose() does. When Jeremy wrote his blog (March 2010) the Dispose() implementation simply called Close().

My concern is that the new implementation doesn’t call the base class implementation at all. By the way the PondServiceClient class is declared partial so the Dispose method could probably be implemented as an extension method as well. As long as the base class implementation is not called, this couldn’t resolve my concern, though. What if Microsoft at any time decides to change the implementation of ClientBase<TChannel>.Dispose()? This kind of change typically happens – thanks, Murphy! – we we expect it the least.

Even if the implementation was never changed, there is a small thing that concerns me. Microsoft has included a little note regarding the use of the ClientBase<TChannel>.State property:

image

So, Jeremy’s solution probably will work. But it is against Microsoft’s recommendation of not using the State property. In particular I get nervous because of the term “race condition”. If problems occur because of race conditions these are typically hard to find and resolve, therefore a very expensive type of issue.

Therefore if we want to follow that recommendation we are back to square one. We would have to surround the use of ClientBase<TChannel> derived objects with boilerplate try-catch statements.

Using Anonymous Methods

Basically the problem is that in order to remove the code duplication a pair of code snipped has be executed before and after the service invocation. Proper handling of communication objects almost sounds like an aspect… so for a moment I even considered looking into libraries like DynamicProxy2 or Ninject. On second thought, though, these felt like overkill for something that appears very simple.

Enter anonymous methods. Basically you can pass a block of code to a different method that does things, executes the block of code, maybe does other things, then returns. How does this apply to the code snippet for the pond service example above. Let’s try to highlight with colors what the boiler plate code is and what the code is that is different:

image

The code within green rectangles is the actual implementation while the code in the orange rectangles is the boilerplate code. Note, how the orange pieces surround the second green piece.

The way to simply this is using a class that works like an interceptor. I implemented a class called ServiceClientInterceptor and it’s main method now looks as follows, again using green and orange rectangles as above:

image

As you can see the green rectangle simply invokes the function that was passed in. With the ServiceClientInterceptor in place you can now write the client side code as follows:

using (var client = new PondServiceClient()) {
   new ServiceClientInterceptor(client).Invoke(() => {
      _pondStatusMessage.Text = _pondNameTextBox.Text +
         (client.IsFrozen(_pondNameTextBox.Text) ?
         " is frozen." : " free of ice.");
   });
}

Line 2 in this example show the beginning of an anonymous method that is passed in as a parameter to the Invoke() method. The cool thing is that inside of the anonymous method you have access to the variables that are accessible at the point of where the anonymous method is defined. It is not limited to where the intercept invokes the execution of that anonymous method.

As a result you can now wrap service invocations with try-catch statements without code duplication.


With this general concept working there are of course further questions that I haven’t covered in this blog post. For example, what if you want reuse the service client for further invocations in the same using block? What if you had multiple service clients that are used within the same anonymous method? I’ll leave these to you for further explorations as there several options in each case.

The solution presented here meets the following requirements:

  • Allows use of using construct
  • Properly closes or aborts WCF connections depending on exception thrown
  • Avoids code duplication
  • Does not make use of ClientBase<TChannel>.State property as per Microsoft’s recommendation

To complete this blog post, below is the full source for the ServiceClientInterceptor class. In that case I have changed the parameter type of the Invoke method to Action. In the screenshots above I still used ServiceMethod which had an identical definition but was the result of earlier experimentation. The Action delegate encapsulates a method that has no parameters and does not return a value. As always you are welcome to use this code at your own risk.

If you know of a solution better than any of the ones mentioned in this post I'd like to hear from you. Happy coding!

public class ServiceClientInterceptor {
   public ServiceClientInterceptor(
         ICommunicationObject serviceClient) {
      _serviceClient = serviceClient;
   }

   public void Invoke(Action func) {
      try {
         func.Invoke();
         _serviceClient.Close();
      }
      catch (CommunicationException ex) {
         _serviceClient.Abort();
         // Handling and/or re-throwing exception is 
         // application specific
      }
      catch (TimeoutException ex) {
         _serviceClient.Abort();
         // Handling and/or re-throwing exception is 
         // application specific
      }
      catch (Exception ex) {
         _serviceClient.Abort();
         // Handling and/or re-throwing exception is 
         // application specific
      }
   }

   private ICommunicationObject _serviceClient;
}

Tuesday, February 16, 2010

Consuming a WCF Service

In one of my recent posts I demonstrated how to implement a simple WCF service using Visual Studio 2008. This time I’ll look at how to implement the client. In doing so I’ll highlight an important oversight of quite a few examples on the internet include at least one provided my Microsoft (see references)!

I’ll continue where I left the solution last time:

image

I’ll add a service client next. Many different options are possible, a Forms-base native application, a WPF-based client, an ASP.NET site, command line, and many more. For this example I’ll use an ASP.NET front-end.

Creating the ASP.NET Application

I’ll use add a new project to the solution. Here is the recipe:

  1. Select from the solution context menu “Add”, then “New Project…”
  2. In the tree on the left expand the “Visual C#” node, then click “Web”
  3. On the right select “ASP.NET Web Application”
  4. As a name enter “DuckWeb”.

Here is how it should look like just before you click “OK”:

image Click OK and your solution should now look like this (I collapsed the DuckServiceLibrary to save some space):

imageOpen the file Default.aspx in source mode and add a label, a text box and a button as follows:

    1 <%@ Page Language="C#" AutoEventWireup="true"

    2     CodeBehind="Default.aspx.cs" Inherits="DuckWeb._Default" %>

    3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

    4          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    5 <html xmlns="http://www.w3.org/1999/xhtml" >

    6 <head runat="server">

    7     <title></title>

    8 </head>

    9 <body>

   10     <form id="form1" runat="server">

   11     <div>

   12     <asp:Label ID="_pondNameLabel" runat="server" Text="Pond Name:">

   13     </asp:Label>

   14     <asp:TextBox ID="_pondNameTextBox" runat="server"></asp:TextBox>

   15     <asp:Button ID="_submitButton" runat="server" Text="Submit"

   16           onclick="_submitButton_Click" />

   17        <br />

   18        <br />

   19        <asp:Label ID="_pondStatusMessage" runat="server" Text="Status unknown.">

   20        </asp:Label>

   21     </div>

   22     </form>

   23 </body>

   24 </html>

When you view this in a browser it looks like this:

image

It doesn’t do anything yet, however. Next I’ll add an event handler to clicking the button. In the Design view of Visual Studio for Default.aspx I simply double-click the button which gives me the following handler:

   14 protected void _submitButton_Click(object sender, EventArgs e) {

   15 

   16 }

In this I’ll add the the code for the service. However, in order to consume the service the web application needs a reference to it. That’s easy to do by doing a right mouse click in the solution explorer on the project “DuckWeb” and then selecting “Add Service Reference…”:

imageIn the “Add Service Reference” dialog I click the “Discover” button and then enter as namespace at the bottom “PondServiceReference”:

image

Upon clicking “OK” the service reference will be added and I can start using the service as if it was just another .NET library.

image Let’s return to the _submitButton_Click() event handler. Since I now have the service reference available I can write my first implementation:

    1 using System;

    2 using System.Web.UI;

    3 

    4 using DuckWeb.PondServiceReference;

    5 

    6 namespace DuckWeb {

    7    public partial class _Default : Page {

    8       protected void Page_Load(object sender, EventArgs e) {

    9 

   10       }

   11 

   12       protected void _submitButton_Click(object sender, EventArgs e) {

   13          var client = new PondServiceClient();

   14 

   15          _pondStatusMessage.Text = _pondNameTextBox.Text +

   16             (client.IsFrozen(_pondNameTextBox.Text) ?

   17                                     " is frozen." : " free of ice.");

   18       }

   19    }

   20 }

Note that I added a using statement for the namespace that contains the generated classes for the service reference. Please also note that this code is far from production ready but I’ll come back to this shortly. First let’s see whether this already works as expected. After setting the DuckWeb project as the startup project the browser is launched and I give it a test run:

image Just what I wanted! So all good, right? Not quite! Return to the code where I create the PondServiceClient instance:

   13 var client = new PondServiceClient();

In this line I also create a connection to the service. However, nowhere in the remainder of the code do I close this connection. Of course at some point the instance will be subject to garbage collection and of course the connection will eventually be closed. However, if I rely on this mechanism I have very little control over when that happens. In this simple example it may not be a big issue. However, if the service implementation uses other resources per connection, e.g. a database connection, or if the service is configured to service only a certain number of open connections, e.g. 10, then your system will get into trouble very quickly. Unfortunately some examples on MSDN or similar sites don’t close WCF connections either (see references below), so chances are that we’ll see service clients that won’t be implemented correctly.

Therefore let’s add a line that closes the connection:

   13 protected void _submitButton_Click(object sender, EventArgs e) {

   14    var client = new PondServiceClient();

   15 

   16    _pondStatusMessage.Text = _pondNameTextBox.Text +

   17                              (client.IsFrozen(_pondNameTextBox.Text)

   18                                  ?

   19                                     " is frozen."

   20                                  : " free of ice.");

   21    client.Close();

   22 }

Now this looks already better. But it is still not good enough!

What if we cannot connect to the service for whatever reason? If that is the case the generated code will throw different types of exceptions depending on the error. The recommended way (or canonical way if you like) of handling the exception looks as follows:

   23 protected void _submitButton_Click(object sender, EventArgs e) {

   24    var client = new PondServiceClient();

   25 

   26    try {

   27       _pondStatusMessage.Text = _pondNameTextBox.Text +

   28                                 (client.IsFrozen(_pondNameTextBox.Text)

   29                                     ?

   30                                        " is frozen."

   31                                     : " free of ice.");

   32       client.Close();

   33    }

   34    catch (CommunicationException ex) {

   35       // Handle exception

   36       client.Abort();

   37    }

   38    catch (TimeoutException ex) {

   39       // Handle exception

   40       client.Abort();

   41    }

   42    catch (Exception ex) {

   43       // Handle exception

   44       client.Abort();

   45    }

   46 }

In all exception handlers I call client.Abort() to cancel the connection. In a real application I would also present a message to a user along the lines “Cannot answer your request as a required service is temporarily not available. Please try again later.”

How about using a using(var client = new PondServiceClient()) contruct:

   49 protected void _submitButton_Click(object sender, EventArgs e) {

   50    using(var client = new PondServiceClient()) {

   51       _pondStatusMessage.Text = _pondNameTextBox.Text +

   52                                 (client.IsFrozen(_pondNameTextBox.Text)

   53                                     ?

   54                                        " is frozen."

   55                                     : " free of ice.");

   56    } // Dispose will be called here.

   57 }

Dispose will be called at the end of the using-block. However, this code doesn’t handle the exceptions yet that you might encounter in the invocation of the service. Furthermore, an exception can also happen when Close() is called from Dispose(). How would you handle those exceptions? The using-construct would lead to very ugly code. For a more detailed discussion see the references at the end of this blog.

This concludes this step of the blog post series on WCF services. There will be at least one more on how to propagate error conditions from a service to a consumer.

Update 09 April 2012: In a newer blog post I’m discussing various options for simplifying the client side. The discussion includes ways for handling everything according to Microsoft’s recommendations while at the same time avoiding code duplication.

References

Some examples for WCF client code that doesn’t close the connection to the service:

It is correctly mentioned and demonstrated at:

Friday, April 03, 2009

Membership Provider Implementation using NHibernate

ASP.NET allows selectively replacing provider implementations with your own custom implementation, e.g. when you want to store membership information in a database other than aspnetdb.mdf. There are more details provided on MSDN. Microsoft provides one such example implementation for ODBC in C# here. For VB.NET a sample membership provider implementation can be found here. While the provider concept is essentially nothing more than Microsoft's flavor of service trays, it is not a surprise that by default Microsoft has a preference for their own products, in particular Microsoft SQL Server. And as long as you don't have a good reason to get into the details of a custom implementation it probably is a good choice to go with what comes out of the box. However, I (and my customers) would like a little more flexibility. Since I'm also experimenting with Fluent NHibernate I am attempting to implement a custom membership provider for ASP.NET based on NHibernate. The idea is that I could use in-memory databases for testing and SQL Server or PostgreSQL for production without having to change a single line of code. All I would need is changing four lines in web.config. So goes the theory. Let's see whether practice proves it right. So far the code looks much simpler than the ODBC sample implementation and yet easier to read and understand. I'll keep you posted.

Saturday, February 28, 2009

Designing Service Interfaces For Silverlight Clients

When designing a service interfaces based on WCF you might be considering indicating service errors via service faults. By and large that might be a good choice but in the case of Silverlight clients consuming that service you may want to read Eugene's blog first. Eugene describes very detailed the technical background for why a Silverlight client running in a web browser may not be able to see the fault with all details. He also provide a few suggestions for how to get around that limitation - which is not Silverlight's fault! - including code examples. In some cases have a separate set of services for Silverlight client's might be an option worth exploring as well. That way you can give service clients, which are not hampered by browser's 'filtering', the best possible experience.