简体   繁体   中英

Catching IIS-level unhandled exceptions

I'm trying to implement error handling on one of our ASP.NET Web API (not core) projects (running .NET 4.7.2) to avoid running into an error in the future, that we had a couple of days ago.

The error was that this code in the Web.Config file had not been updated, but the DLL that came with the project when it was published was updated, so there was a mismatch between the versions.

  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs"
        type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701"/>
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb"
        type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+"/>
    </compilers>
  </system.codedom>

The Version=2.0.1.0 in both compiler lines were set to Version=1.0.8.0 , and the version of the DLL that was published was 2.0.1.0. This gives an error that looks like this:

显示异常的图像

Now, I would like to handle this exception in the code, and log it to our logging stack. I have searched around and found a couple of different methods of catching exceptions in a web.api project, but none of them seem to have worked. The ones I have tried are:

In the global.asax.cs file:

        void Application_Error(object sender, EventArgs e)
        {
            Exception ex = Server.GetLastError();

            if (ex != null)
                Logger.WriteToFile(ex.Message, ex);
        }

Also in the global.asax.cs file:

        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);

            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
        }

        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            Exception ex = (e.ExceptionObject as Exception);

            if (ex != null) 
                Logger.WriteToFile(ex.Message, ex);
        }

In the WebApiConfig.Register function that is automatically added to the Web.API (that handles routing setup, for example):

        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Filters.Add(new GlobalExceptionFilterAttribute()); // <-- this line

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }

    public class GlobalExceptionFilterAttribute : ExceptionFilterAttribute
    {
        public override void OnException(HttpActionExecutedContext context)
        {
            var exceptionType = context.Exception.GetType().ToString();
            var exception = context.Exception.InnerException ?? context.Exception;

            try
            {
                if (exception != null)
                    Logger.WriteToFile(exception.Message, exception);
            }
            finally
            {
                base.OnException(context);
            }
        }
    }

And in the web.config file, I added a module that should (in theory) handle the IIS level errors (taken from Catch IIS level error to handle in ASP.NET ):

  <system.webServer>
    <modules>
      <add type="ErrorHttpModule" name="ErrorHttpModule"/>
    </modules>
  </system.webServer>
public class ErrorHttpModule : IHttpModule
{
    private HttpApplication _context;

    public ErrorHttpModule() { }

    public void Init(HttpApplication context)
    {
        _context = context;
        _context.Error += new EventHandler(ErrorHandler);
    }

    private void ErrorHandler(object sender, EventArgs e)
    {
        Exception ex = _context.Server.GetLastError();

        if (ex != null)
            Logger.WriteToFile(ex.Message, ex);
    }

    public void Dispose()
    {
    }
}

And none of these seem to catch the error, and log it. How do I catch this error?

I have reproduced this error in a completely blank Web.API project in addition to our main project. The blank Web.API project can be found at https://github.com/Loyalar/IISExceptionCapture .

Troubleshooting:

  1. enabled stdoutLogEnabled and checked IIS log.

  2. You may also check window log events.

Refer - https://weblog.west-wind.com/posts/2020/Jan/14/ASPNET-Core-IIS-InProcess-Hosting-Issues-in-NET-Core-31

You could use below code at the start of your application. In Program.cs, Startup.cs or your Global.asax file.

AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) =>
{
    Debug.WriteLine(eventArgs.Exception.ToString());
};

refer this below link for more detail:

https://stackify.com/csharp-catch-all-exceptions/

catch all unhandled exceptions in ASP.NET Web Api

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM