如何为IIS7集成Custom HttpModule

时间:2013-11-27 18:02:51

标签: asp.net iis-7 exception-handling httpmodule

我在IIS 7.0 webserver上配置了asp.net webapplication。我在将自定义HTTPModule集成到web.config时遇到问题。然而,该代码适用于Web服务器中的Visual Studio构建。有人可以看看,告诉我我可能做错了什么?

using System;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Web;

namespace Realpage.HTTPModule.UnhandledException
{
    using System.Configuration;
    using System.Reflection;

    using Elmah;

    public class ElmahLogger : IHttpModule
    {
        static int unhandledExceptionCount;

        static readonly object InitLock = new object();
        static bool initialized;

        private static string elmahDirectory;
        private static readonly FieldInfo elmahLogPathField =
            typeof(XmlFileErrorLog).GetField("_logPath", BindingFlags.NonPublic | BindingFlags.Instance);
        public void Init(HttpApplication httpApplication)
        {
            // Do this one time for each AppDomain.
            if (initialized)
            {
                return;
            }
            lock (InitLock)
            {
                if (initialized)
                {
                    return;
                }
                var webenginePath = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "webengine.dll");
                if (!File.Exists(webenginePath))
                {
                    throw new Exception(String.Format(CultureInfo.InvariantCulture, 
                        "Failed to locate webengine.dll at '{0}'.  This module requires .NET Framework 2.0.", webenginePath));
                }

                AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
                httpApplication.BeginRequest += Application_BeginRequest;
                initialized = true;
                elmahDirectory = ConfigurationManager.AppSettings["ElmahLogPath"];
            }
        }

        static void Application_BeginRequest(Object sender, EventArgs e)
        {
            var xmlFileErrorLog = (XmlFileErrorLog)ErrorLog.GetDefault(HttpContext.Current);
            elmahLogPathField.SetValue(xmlFileErrorLog, elmahDirectory);
        }

        public void Dispose()
        {
        }

        static void OnUnhandledException(object o, UnhandledExceptionEventArgs e)
        {
            // Let this occur one time for each AppDomain.
            if (Interlocked.Exchange(ref unhandledExceptionCount, 1) != 0)
            {
                return;
            }

            var xmlFileErrorLog = (XmlFileErrorLog)ErrorLog.GetDefault(HttpContext.Current);
            elmahLogPathField.SetValue(xmlFileErrorLog, elmahDirectory);

            var exception = (Exception)e.ExceptionObject;
            var baseException = exception.GetBaseException();

            var error = new Error(baseException);
            xmlFileErrorLog.Log(error);
        }
    }
}

实施模块应该很简单:

<configuration>
<system.web>
<httpModules>
      <add name="Realpage.HTTPModule.UnhandledException" type="Realpage.HTTPModule.UnhandledException.ElmahLogger" />
            <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
            <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/>
            <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah"/>
            <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah"/>
        </httpModules>
</system.web>

<system.webServer>
        <modules runAllManagedModulesForAllRequests="true">
            <remove name="ScriptModule"/>
      <add name="RealpageHTTPModuleUnhandledException" type="Realpage.HTTPModule.UnhandledException.ElmahLogger, Realpage.HTTPModule.UnhandledException"
           preCondition="managedHandler"/><!--This is the handler causing the issue-->
      <add name="ScriptModule" preCondition="managedHandler" 
           type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler"/>
            <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler"/>
            <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler"/>
        </modules>
    </system.webServer>

</configuration>

但是我收到以下错误:

[NullReferenceException: Object reference not set to an instance of an object.]
   System.Web.PipelineModuleStepContainer.GetEventCount(RequestNotification notification, Boolean isPostEvent) +30
   System.Web.PipelineStepManager.ResumeSteps(Exception error) +332
   System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb) +113
   System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +616

如果有人能帮我解决这个问题,我会很高兴。希望这篇文章能够帮助其他程序员在他们需要的日子里。

1 个答案:

答案 0 :(得分:0)

问题在于应用程序池。我将“ManagedPipelineMode”属性从“Integrated”更改为“Classic”并修复了该问题。