Search code examples
c#asp.netlogginghttphandlerhttpmodule

IHttpModule problems


I've asked a question regarding creating an IIS logger, but am still having a couple of issues:

  1. Original message is lost
  2. Response message is not captured

Would it be at all possible to get these 2 sorted out?

IHttpHandler:

using System.Web;
using System.IO;

namespace MyLogger
{
    public class MyHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            context.Response.Write("The page request is " + context.Request.RawUrl.ToString());
            StreamWriter sw = new StreamWriter(@"C:\requestLog.txt", true);
            sw.WriteLine("Page requested at " + DateTime.Now.ToString() + context.Request.RawUrl);
            sw.Close();
        }

        public bool IsReusable
        {
            get
            {
                return true;
            }
        }
    }
}

IHttpModule:

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.IO;

namespace MyLogger
{
    public class MyModule : IHttpModule
    {
        public InterceptorModule()
        { }
        public void Init(HttpApplication objApplication)
        {
            // Register event handler of the pipe line
            objApplication.BeginRequest += new EventHandler(this.ContextBeginRequest);
            objApplication.EndRequest += new EventHandler(this.ContextEndRequest);
        }
        public void Dispose()
        {
        }
        public void ContextEndRequest(object sender, EventArgs e)
        {
            StreamWriter sw = new StreamWriter(@"C:\requestLog.txt", true);
            sw.WriteLine("End Request called at " + DateTime.Now.ToString()); sw.Close();
        }
        public void ContextBeginRequest(object sender, EventArgs e)
        {
            StreamWriter sw = new StreamWriter(@"C:\requestLog.txt", true);
            sw.WriteLine("Begin request called at " + DateTime.Now.ToString()); sw.Close();
        }
    }
}

My previous post: IIS API Monitor in a web application Thanks in advance!


Solution

  • I'm not sure what the point of the HTTPHandler is, but all of the logging can be performed from the HTTPModule. However, your code needs some substantial improvement in order to survive.

    1) You should have try/catch blocks around the streamwriters to ensure unhandled exceptions aren't thrown, especially if you are trying to be unobtrusive.

    2) The streamwriter code should be wrapped in a using block to ensure you don't strand resources.

    3) Since you could potentially have multiple threads trying to write to the file simultaneously, you need to wrap the write code in a lock block.

    4) You can use HttpContext.Current.Request to access the current request, which I suspect may be what you had done in the HttpModule. If this wasn't the intention, we will need additional clarification.

    5) If you start the application in debug mode and the Init method isn't hit, then your web.config entries are incorrect. The type must be fully qualified (i.e. include the namespace) and you should add both the integrated and class mode configuration:

    Classic mode (IIS 6, IIS 7+ classic)

    <configuration>
      <system.web>
        <httpModules>
          <add name="MyModule" type="MyNamespace.MyModule"/>
         </httpModules>
      </system.web>
    </configuration>
    

    Integrated mode (IIS 7+ integrated)

    <configuration>
      <system.webServer>
        <modules>
          <add name="MyModule" type="MyNamespace.MyModule"/>
        </modules>
      </system.webServer>
    </configuration>
    

    Here is the rewritten code:

       static Object m_LockObject = new Object();
    
        public void Init(HttpApplication objApplication)
        {
            // Register event handler of the pipe line
            objApplication.BeginRequest += new EventHandler(this.ContextBeginRequest);
            objApplication.EndRequest += new EventHandler(this.ContextEndRequest);
        }
        public void ContextEndRequest(object sender, EventArgs e)
        {
            try
            {
                lock (m_LockObject)
                {
                    using (StreamWriter sw = new StreamWriter(@"C:\requestLog.txt", true))
                    {
                        sw.WriteLine("End request called at " + DateTime.Now.ToString() + "; URL: " + HttpContext.Current.Request.RawUrl.ToString());
                    }
                }
    
                // Write the response back to the caller
                HttpContext.Current.Response.Write("The page request is " + HttpContext.Current.Request.RawUrl.ToString());
    
            }
            catch
            {
            }
        }
        public void ContextBeginRequest(object sender, EventArgs e)
        {
            try
            {
                lock (m_LockObject)
                {
                    using (StreamWriter sw = new StreamWriter(@"C:\requestLog.txt", true))
                    {
                        sw.WriteLine("Begin request called at " + DateTime.Now.ToString() + "; URL: " + HttpContext.Current.Request.RawUrl.ToString());
                    }
                }
            }
            catch
            {
            }
        }