-1

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!

Community
  • 1
  • 1
Raytrace
  • 5
  • 4
  • 2
    Are you *serious* about working with a single physical file in a heavily multi-threaded environment *this way*? – Ondrej Tucny Jan 01 '12 at 23:20
  • Please be sure to mark your answer in your other question so future readers can learn from your experiences. – M.Babcock Jan 01 '12 at 23:31
  • I'm just putting it up there for simplicity. My questions do not relate to multi-threading, which is why I left it out. In any case, I did mark the answer useful, but for some reason it did not reflect on the page. And I did leave my findings in the comments section for future reference. – Raytrace Jan 02 '12 at 06:42

1 Answers1

1

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
        {
        }
    }
competent_tech
  • 44,465
  • 11
  • 90
  • 113
  • Thank you for your response, however it does not address my need for the original message to be logged and forwarded to the calling client. Would this be possible at all with HttpModule and/or HttpHandler? – Raytrace Jan 02 '12 at 06:46
  • @Raytrace: Yes, this can absolutely be done using `HttpContext.Current.Response.Write`. Sorry I missed that in the original httpmodule. I have updated the answer so that this is done in `ContextEndRequest` and as such, it appears at the bottom of the page. – competent_tech Jan 02 '12 at 17:40
  • Found my answer here for future reference: http://forums.asp.net/post/2417324.aspx – Raytrace Jan 03 '12 at 00:09