Monday, November 19, 2012

C#: Handling the “The remote host closed the connection” exception in WCF REST

In a recent project, I was involved in developing WCF Restful services for mobile clients. There were some services where the clients send files as multi-part POST requests. In some cases the file data parsing on the server fails due to missing form data fields or missing file data but those scenarios ended up throwing exception on the server. It was the most common communication exception 'The remote host closed the connection'.

The WCF method signature looked like this:
public bool SaveImage(Stream stream)

And inside the method, there is absolutely nothing special I am doing when parsing fails. I am returning true when parsing failed and false otherwise. But when it fails, it throws this exception for no reason.
After much of Googling, I found that when client is no longer connected to the service this exception may occur on the server. And the solution was to check Response.IsClientConnected property and act accordingly if its false. When I checked it, to my surprise it was false even when the method itself gets called! That is only when the parsing failed. So my conclusion was that the WCF infrastructure takes care of those requests which are not legit at the very beginning of its pipeline and releases the client to free its connection pool. But I still wonder why it passes the context to the method, if it is not willing to listen for the response.
So to fix this I added this method to my base service class:
protected bool IsClientConnected
{
    get { return HttpContext.Current.Response.IsClientConnected; }
}
In every method which takes in a Stream, I call this method and make sure client is still listening and return the response. So what do I return when client is not connected? Just null. This gets rid of getting the nasty 'remote host' exception and you can save you logs from overflowing with that.
Happy coding!
PS: The downside of using this method is that you have to use HttpContext which forces you to use AspNetCompatibilityRequirementsMode.Required, in your service which will prevent you from self-hosting it. But then again I don think clients would be disconnected in this fashion unless in that case. So I guess it's fair enough :)

No comments:

Post a Comment