Introduction
If you have recently upgraded your .NET application to .NET 2.0 or have written any new .NET 2.0 client applications which call webservices, you may have noticed a strange problem that occurs once in a while. You will get an error occassionally with the exception:
System.Net.WebException : The underlying connection was closed: A connection that was expected to be kept alive was closed by the server
Cause of the problem
In .NET 1.1, Microsoft introduced a feature called "KeepAlive". When you make web requests, the server will keep the connection open for a short time to serve multiple requests using the same connection. This will improve the performance a lot by reusing the same connection avoiding the overhead involved in opening and closing the connections repeatedly for the service call.
However, in .NET 2.0 there seem to be some issues with this flag. The default value is 'TRUE' and occasionally the connection gets closed, but the client continue to use the connection. The client requests server to keep the connection open, but the server closes it sometimes leaving the client in trouble! This will cause a System.Net.WebException and you will get the above error message.
How to solve the problem ?
Until Microsoft fix the issue, you have to do some workaround with your web request calls. You must explicitly set the KeepAlive property to FALSE so that the connection will be closed by itself and re opened for every request. This will avoid the issue of attempting to use a closed connection.
There is no direct way you can set the KeepAlive to FALSE. This is a 'Protected' property on the WebRequest. When you use web services, you must first derive a class from your webservice class and then set this flag to FALSE in the inherited class.
Assume you have a web reference with the name 'Banking' and a webservice class called 'Transaction'. Typically, you will use the class as follows in your client:
dim obj as new Banking.Transaction() obj.MakeTransaction()
To set the KeepAlive property, you must inherit a class from Banking.Transaction in your client. Create a new class called "BankTransaction" in the client project. Now inherit the "GetWebRequest" method in this class as shown below:
Public Class BankTransaction Inherits Banking.Transaction
Protected Overrides Function GetWebRequest(ByVal uri As Uri) As System.Net.WebRequest Dim webRequest As System.Net.HttpWebRequest webRequest = CType(MyBase.GetWebRequest(uri), System.Net.HttpWebRequest) ' Setting KeepAlive to false webRequest.KeepAlive = False
return webRequest End Function
End Class
We are explicitly setting the property KeepAlive to FALSE in the above inherited method. Now, use the inherited class to make the webservice calls. This will solve the error A connection that was expected to be kept alive was closed by the server.
Note that the KeepAlive = FALSE will have some performance impact.
|
| Author: Sujitha Antony 17 Oct 2007 | Member Level: Bronze Points : 0 |
Very good explanation on Keep Alive property. Give a sample code also which will compel us to keep this property to False
|