【问题标题】:IHttpModule problemsIHttpModule 问题
【发布时间】:2012-01-01 23:10:13
【问题描述】:

我问过一个关于创建 IIS 记录器的问题,但仍有几个问题:

  1. 原始消息丢失
  2. 未捕获响应消息

有没有可能解决这两个问题?

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();
        }
    }
}

我之前的帖子:IIS API Monitor in a web application 提前致谢!

【问题讨论】:

  • 您是否认真在高度多线程的环境中以这种方式处理单个物理文件?
  • 请务必在您的其他问题中标记您的答案,以便未来的读者可以从您的经验中学习。
  • 为了简单起见,我只是把它放在那里。我的问题与多线程无关,这就是我忽略它的原因。无论如何,我确实将答案标记为有用,但由于某种原因它没有反映在页面上。我确实将我的发现留在了 cmets 部分以供将来参考。

标签: c# asp.net logging httphandler httpmodule


【解决方案1】:

我不确定 HTTPHandler 的意义是什么,但是所有的日志记录都可以从 HTTPModule 执行。但是,您的代码需要一些实质性的改进才能生存。

1) 您应该在流编写器周围设置 try/catch 块,以确保不会引发未处理的异常,尤其是在您试图不引人注意时。

2) 流写器代码应包装在 using 块中,以确保您不会占用资源。

3) 由于您可能有多个线程同时尝试写入文件,因此您需要将写入代码包装在锁定块中。

4) 您可以使用 HttpContext.Current.Request 访问当前请求,我怀疑这可能是您在 HttpModule 中所做的。如果这不是本意,我们需要进一步澄清。

5) 如果您在调试模式下启动应用程序并且未命中 Init 方法,则您的 web.config 条目不正确。类型必须是完全限定的(即包括命名空间)并且您应该添加集成模式和类模式配置:

经典模式(IIS 6、IIS 7+ 经典)

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

集成模式(IIS 7+ 集成)

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

这是重写的代码:

   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
        {
        }
    }

【讨论】:

  • 感谢您的回复,但它不能满足我记录原始消息并将其转发给呼叫客户端的需求。使用 HttpModule 和/或 HttpHandler 是否有可能?
  • @Raytrace:是的,这绝对可以使用HttpContext.Current.Response.Write 完成。抱歉,我在原始 httpmodule 中错过了这一点。我已经更新了答案,以便在ContextEndRequest 中完成,因此它出现在页面底部。
  • 在这里找到我的答案以供将来参考:forums.asp.net/post/2417324.aspx
猜你喜欢
  • 2012-10-07
  • 2010-10-20
  • 1970-01-01
  • 1970-01-01
  • 2011-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-06
相关资源
最近更新 更多