The Danger of using
Posted: Thursday, August 12, 2004 12:58 AM
by
bruce
Filed under: SOAP, Tips
It is well known that the C# using statement is quite handy, especially when the object including in the using statement needs to be disposed. However, there is a danger associated with having certain tasks done for you. That is, that it is easy to forget exactly what is going on.
The scenario is that an HttpModule was being created by a client of ours to log incoming requests and outgoing responses to a web service. I've done this before and it is not exceptionally difficult. We created a handler for the BeginRequest event and accessed the Request.InputStream attribute. This stream was used as the basis for a StreamReader, as can be seen in the following code.
HttpApplication app = (HttpApplication)sender;
using (StreamReader sr = new StreamReader(app.Request.InputStream))
{
string content = sr.ReadToEnd();
// Write content to a log file
}
app.Request.InputStream.Position = 0;
Seems innocuous enough. But it's not. The result of a call to a web service in which this HttpModule is installed results in an System.Xml.XmlException. The text of the message indicates that the root element of the XML document is missing. For those unfamiliar with streaming problems, this particular error message is frequently caused by an empty stream being processed by ASP.NET.
The root cause can be found in what the using statement does. In particular, when the sr variable goes out of scope, it is disposed. This is the non-obvious behavior I'm going about. Not that it should be surprising that using causes the object to be disposed you understand. That's the purpose of using after all. But because you don't see an explicit Dispose or Close method, the solution to the problem is not obvious. If you look at the definition of the Dispose method on the StreamReader, you will find that the underlying stream is closed. Not good, as it means that the remaining HttpModules and ASP.NET get nothing to work with. The solution, for those who are interested (as pointed out to me by Marc Durand at Agfa during our debugging session), is to use the GetBytes method on the InputStream. This keeps the stream open and the data flowing.
If you would like to receive an email when updates are made to this post, please register here