简体   繁体   English

ASP.NET C#捕获类中的所有异常

[英]ASP.NET C# Catch all exceptions in a class

I know this is not the way to do it, and it isn't clean at all. 我知道这不是这样做的方式,而且根本不干净。 I just wonder if it's possible. 我只是想知道是否可能。

If I have a class with a bunch of methods 如果我有一个带有一堆方法的类

public class Foo {

   methodA() {}

   methodB() {}

   methodC() {}

}

Is it possible to catch all exceptions that could possibly occur without having to write a try/catch in each method? 是否有可能捕获所有可能发生的异常而无需在每个方法中编写try / catch?

Yes it is. 是的。 The simplest way would be a Attribute for this class like this one: 最简单的方法是这个类的属性,如下所示:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class HandleErrorAttribute : FilterAttribute, IExceptionFilter
{

    public void OnException(ExceptionContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        if (filterContext.ExceptionHandled)
        {
            return;
        }

        var exception = filterContext.Exception;

        // that need to be your current request object. In this case I use a custom one so I must fetch it from the items collection of the current request, where I had stored it before.
        var request = filterContext.HttpContext.Items[Request.RequestKey] as Request;

        if (request != null)
        {
            // overwrite ErrorResponse with a response object of your choice or write directly to the filterContext.HttpContext.Response
            var errorResponse = new ErrorResponse(request, exception); 
            errorResponse.Write(filterContext.HttpContext.Response);
            filterContext.ExceptionHandled = true;
        }
    }
}

// Or a just slightly modified version of the default ASP.Net MVC HandleError Attribute
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
    public class CustomHandleErrorAttribute : FilterAttribute, IExceptionFilter
    {
        // Fields
        private const string _defaultView = "Error";
        private string _master;
        private readonly object _typeId = new object();
        private string _view;

        // Methods
        public virtual void OnException(ExceptionContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }
            if (!filterContext.IsChildAction && (!filterContext.ExceptionHandled && filterContext.HttpContext.IsCustomErrorEnabled))
            {
                Exception innerException = filterContext.Exception;
                if ((new HttpException(null, innerException).GetHttpCode() == 500))
                {
                    string controllerName = (string)filterContext.RouteData.Values["controller"];
                    string actionName = (string)filterContext.RouteData.Values["action"];
                    HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
                    ViewResult result = new ViewResult();
                    result.ViewName = this.View;
                    result.MasterName = this.Master;
                    result.ViewData = new ViewDataDictionary<HandleErrorInfo>(model);
                    result.TempData = filterContext.Controller.TempData;
                    filterContext.Result = result;
                    filterContext.ExceptionHandled = true;
                    filterContext.HttpContext.Response.Clear();
                    filterContext.HttpContext.Response.StatusCode = 500;
                    filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
                }
            }
        }

        public string Master
        {
            get
            {
                return (this._master ?? string.Empty);
            }
            set
            {
                this._master = value;
            }
        }

        public override object TypeId
        {
            get
            {
                return this._typeId;
            }
        }

        public string View
        {
            get
            {
                if (string.IsNullOrEmpty(this._view))
                {
                    return "Error";
                }
                return this._view;
            }
            set
            {
                this._view = value;
            }
        }
    }

Usage (untested cause I used it in context of controller that already implement all required interfaces) 用法(未经测试的原因我在已经实现所有必需接口的控制器的上下文中使用它)

[HandleErrorAttribute]
public class Foo : IExceptionFilter // (I am not sure about this one IActionFilter)
{

    public void MethodA() 
    {
        // body
    }

    public void MethodB() 
    {
        // body
    }

    public void MethodC()
    {
        // body
    }

}

Or you can do something like this: 或者你可以这样做:

public class ExecuteHelper
{
    public static void Catch(Action action)
    {
        try
        {
            action();
        }
        catch (Exception ex)
        {
            // Do what you want
        }
    }
}

And use it in a Function body: 并在函数体中使用它:

public void Foo(string something)
{
    ExecuteHelper.Catch(() =>
    {
        // Do something with something or without something
    });
}

You could write a higher order function to handle the exceptions, which would make it somewhat cleaner. 您可以编写更高阶的函数来处理异常,这会使它更清晰一些。

private T FooExceptionHandler(Func<T> function)
{
   try
   {
      return function();
   }
   catch
   {
      //handle it
   }
}

You can replace Func with Action if you don't have a return value. 如果没有返回值,可以将Func替换为Action。 You can use it in two ways, outside of the function: 您可以在功能之外以两种方式使用它:

FooExceptionHandler(MethodA);

or inside each function: 或在每个功能内:

MethodA()
{
   return FooExceptionHandler(()=>
      {
         //Function body goes here
      });
}

No, there isn't. 不,没有。 try / catch blocks can only occur in methods. try / catch块只能在方法中出现。 You could use some sort of AOP framework however to automatically generate those blocks. 但是,您可以使用某种AOP框架来自动生成这些块。 postcrap is a pretty lightweight AOP component. postcrap是一个非常轻量级的AOP组件。

您可以在调用这些方法的函数中处理它...

By default, in ASP.NET you can override the OnError method and then do Server.ClearError to dispose of the exception. 默认情况下,在ASP.NET中,您可以覆盖OnError方法,然后执行Server.ClearError以处置异常。

I'm not sure if it applies to your case (only works in Page and Global.asax ) 我不确定它是否适用于您的情况(仅适用于PageGlobal.asax

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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