1.注册自己的异常过滤器
在MVC类型的项目中App_Start文件夹下的FilterConfig文件中存在一个异常处理的过滤器,我们要将其改写文我们自己的异常处理过滤器。将我们自己定义的捕获异常的类注册到项目中,即告诉项目调用我们自己定义的方法 即在 FilterConfig作如下配置。在Global.asax中可知该过滤器在项目启动时已经启动。
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//filters.Add(new HandleErrorAttribute());//原来的
filters.Add(new MyExceptionAttribute()); //自己写的
}
}
2.捕获异常
构建一个MyExceptionAttribute类继承HandleErrorAttribute
在HandleErrorAttribute中存在一个public virtual void OnException(ExceptionContext filterContext);虚方法
在我们自己构建的类中重载该方法,用于捕获异常信息
public class MyExceptionAttribute: HandleErrorAttribute
{
public static Queue<Exception> ExceptionQueue = new Queue<Exception>();//定义队列,一定要是静态的,静态才能共享
/// <summary>
/// 在该方法中捕获异常
/// </summary>
/// <param name="filterContext"></param>
public override void OnException(ExceptionContext filterContext)
{
base.OnException(filterContext);
Exception ex = filterContext.Exception;//捕获异常信息
//将异常信息写入队列中
ExceptionQueue.Enqueue(ex);
//跳转到错误页面
filterContext.HttpContext.Response.Redirect("/Errow.html");
}
}
3.将异常信息写入文本文件
在异常写入过程中要考虑并发问题,要利用生产者消费者模式考虑此问题,在将错误信息写入队列以后 在Global.ascx 的Application_Start()开辟一个线程将错误信息写入文件中,此线程从项目启动开始,一直扫描队列中是否有异常信息,有的话写入文件。
在项目中先建一个Log文件夹,在Global.ascx中Application_Start()修改成如下:
protected void Application_Start()
{
//开启一个线程,查看异常队列
string filePath = Server.MapPath("/Log/");
ThreadPool.QueueUserWorkItem((a) =>
{
while(true)//线程不能结束,否则后面写到队列中的数据没法处理
{
if(MyExceptionAttribute.ExceptionQueue.Count()>0)
{
Exception ex = MyExceptionAttribute.ExceptionQueue.Dequeue();//出队列
if(ex!=null)
{
string fullPath = filePath + DateTime.Now.ToString("yyy-MM-dd") + ".txt";
File.AppendAllText(fullPath, ex.ToString());
}
else
{
Thread.Sleep(3000);
}
}
else
{
Thread.Sleep(3000);//避免造成cpu空转
}
}
},filePath);//WaitCallback是一个委托 执行一个线程就是执行一个方法
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}