I needed a basic logging feature in order to debug IIS on our client's machine.
This is probably the most forward way to log the request and the matching response. It can be done using the IIS logging features, but it requires touching places we don't want to disturb.
So how does it work?
First build a HTTPModule:
public class LogHTTP : System.Web.IHttpModule
IHttpModule requires 2 methods:
Dispose() - The clean up method, needed only when the GC can't do the cleaning.
Init(System.Web.HttpApplication context) - called upon initialization phase. The common use for it is the hooking of event handlers and setting global variables. Its code is as follows:
public void Init(System.Web.HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
An event handler for each incoming request.
Note: I didn't use PreRequestHandlerExecute because of AJAX. When an AJAX request enters it doesn't reach this phase.
The event handler method code is:
private void context_BeginRequest(object sender, EventArgs e)
{
if (sender is System.Web.HttpApplication)
{
string l_ID = Guid.NewGuid().ToString();
System.Web.HttpApplication app = (System.Web.HttpApplication)sender;
System.Web.HttpRequest request = app.Context.Request;
request.SaveAs(Base_Dir + l_ID + ".req", true);
System.Web.HttpResponse response = app.Context.Response;
response.Filter = new CaptureResponse(response.Filter, Base_Dir + l_ID + ".res");
}
}
Pretty straight forward, except for the response.Filter. What is it?
In order to save the response, I had to use the filter stream. CaptureResponse is a class which creates a copy of the written data to a local file.
internal class CaptureResponse : System.IO.MemoryStream
{
private readonly string l_filename;
private readonly System.IO.Stream _stream;
public CaptureResponse(System.IO.Stream stream, string filename)
{
l_filename = filename;
_stream = stream;
}
public override void Write(byte[] buffer, int offset, int count)
{
System.IO.StreamWriter sw = new System.IO.StreamWriter(l_filename, true);
sw.BaseStream.Write(buffer, offset, count);
sw.Flush();
sw.Close();
_stream.Write(buffer, offset, count);
}
}
Note: In order to use the same Write method I used the BaseStream rather than the normal call to Write.
The resulting module can easily be added to any site by putting the DLL in the path (or /bin) and adding the following line to web.config, under configuration/system.web/httpModules:
<add name="DLL-NAME" type="NAMESPACE.LogHTTP"/>
Thursday, April 28, 2011
Subscribe to:
Posts (Atom)