Click here to monitor SSC

Software Engineer - Red Gate Software

Exceptional service

Published 28 July 2006 10:54 am
A constant niggle in the arena of computing is the way in which nobody takes responsibility. If your computer crashes whilst you’re, say, playing an online game, and you call the manufacturer, they’ll explain it’s probably a software problem, perhaps a driver you, the user, stupidly installed. If you call the driver vendor, they’ll explain that it’s probably some other driver you, the user, stupidly installed; or perhaps some other hardware (not theirs, of course) is causing you problems; or perhaps your game has a bug in it. If you call the game publisher, they’ll explain that it’s clearly a hardware problem, or you need to upgrade your drivers. Nobody will hold their hand up and say, “Sorry, my bad, we screwed up. Our product is inferior, and we will rectify that for you, right now.”

On a microscopic level, the same situation occurs when a contract breaks down between the caller and callee of an interface. The case which I wish to briefly whine about is that of web services.

I’m working on a .NET 2.0 desktop application which uses a third party web service. Now it generally works nicely. Much to my surprise, however, I periodically notice the application cough, gasp for air, and finally collapse spreadeagled on the floor. By the time I can attend it, I observe that it has written me a final message with one trembling finger, using its own vital fluids as ink:

System.Net.WebException : The underlying connection was closed: A connection that was expected to be kept alive was closed by the server.

How nice of it.

Googling around revealed a few more facts. It appears that .NET and the web service implementation are having a disagreement over the lifetime of the HTTP connection which they’re using to talk. .NET asked for the connection to be kept up, if you don’t mind, so that it can avoid the overhead of reopening it all the time. The remote server agreed, but at some stage this became impossible. This may be because the remote server is a lying son of a VAX; or because there are inconvenient firewalls between my client and the server, interfering with the keepalive; or because the server encountered a minor problem which .NET didn’t understand, and this issue got blown out of proportion until it finally manifested as a dropped connection. Opinion on the internet seems divided; all of these are cited as plausible reasons. Meantime, .NET, for its part, doesn’t like the internet failing to work flawlessly. In its idealistic view, this simply should not happen! What is the world coming to? And, it reasons, if this is occurring, surely someone should be alerted so they can a) fix the internet; and/or b) rewrite the server code? Overall, the best thing to do from .NET’s point of view is not to, say, reopening the offending connection and try again; no no, the best plan is to throw an exception.

Now the thing that vexes me is not that .NET likes throwing exceptions whenever anything even vaguely unconventional occurs; such as, for example, if I were to come to work wearing a hat. I’ve grown accustomed to its idiosyncracies in this regard. What vexes me is that .NET has deliberately set itself up to work under a theoretical and idealistic optimal case (where keepalive connections are always kept alive), and then complains bitterly when its lofty ideal is not upheld by the cruel world.

In any case, there is a solution to this problem. One simply has to find the web service’s generated code within the client application, which derives from WebClientProtocol or one of its subclasses. One then overrides the GetWebRequest method as follows, to tell .NET not to bother trying to keep connections alive:

        protected override System.Net.WebRequest GetWebRequest(Uri uri)
        {
            WebRequest request = base.GetWebRequest(uri);
            (request as HttpWebRequest).KeepAlive = false;
            return request;
        }


Simple stuff. But there are a few little niggles; the .cs file in which one is supposed to override this method is generated code. So, if the web service’s documented interface changes (which has been known to occur rather regularly on the internet), the code needs to be regenerated. Now I personally object to trawling through generated code each time I regenerate it, adding in hacks here and there. It’s just wrong.

So, a slightly more tasteful solution was required. Instead, I derive a class from the generated code for the web service, called eg. SafeWebService. Inside this class, I override the GetWebRequest method. I then be sure to make use of SafeWebService rather than the original generated code. This way, I can regenerate the code and not have to make any changes, since my modifications are not contained therein.

6 Responses to “Exceptional service”

  1. Anonymous says:

    I tried the “keepalive” solution, and it didn’t work. Neither did setting various timeout and idletime values, nor did assigning a ConnectionGroup name and closing it. I’ve decided that there is no way to prevent the error from the client side. So far, simply catching the error and re-trying the WebService method has been successful.

  2. Anonymous says:

    Very good Dan, but what’s this got to do with the price of fish?

  3. Anonymous says:

    Dan,

    Thanks for this. I was having some trouble figuring this error out. Was it my .NET app (a nasty and ugly proof of concept/R&D/prototype app that is serving as a demo until we can get the beta developed a bit more) that was failing? Was it the mysterious ruby that was providing the web service? Was it just the internet trying to make me angry?

    A simple solution to a seemingly complicated issue. If you come my way I owe you a beer.

  4. Joe Cheng MSFT says:

    (I work at Microsoft but not on the .NET Framework)

    Tricky problem. It’s often impossible or inadvisible for low-level components to retry operations that fail. In this case, retrying could be a very bad idea if the operation is not safely repeatable (in theory this should never be the case with a GET, but in practice…).

    For example, if the request is to create a new blog post; when the first request fails, it may not always be possible for the client to know whether the call made it to the server before the connection was dropped. If it was in fact successful, then a second request would cause a duplicate post to be made.

    There are other situations where HttpWebRequest is downright touchy, such as when servers return headers separated by n, not rn as requested by the spec–it’ll throw an exception by default. Turns out this is to prevent “response splitting” attacks which can happen if server app developers aren’t careful to scrub user-generated content. Every time so far I have come across an exception that seems spurious there’s turned out to be a similarly good reason for it.

  5. IrishLadd says:

    I’m working on a WebService that gets an RSS Feed and sends the content back to the client. I get this error about every other time I request the page, although this is hit and miss at times.

    I’ve been looking around the web and you solution seems to be the most commonly used, but I can’t for the life of me figure out where the generated .cs file is. Is there something I’m missing?

  6. tjuni says:

    Dan – you write ” I then be sure to make use of SafeWebService rather than the original generated code. “. where do you “tell” the app to use your derived class instead of reference.cs?

Leave a Reply