你的位置:首页 > ASP.net教程

[ASP.net教程]ASP.NET MVC自定义异常处理


1.自定义异常处理过滤器类文件

新建MyExceptionAttribute.cs异常处理类文件

MyExceptionAttribute.cs代码如下:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;namespace WebApp.Models{  public class MyExceptionAttribute : HandleErrorAttribute  {    public static Queue<Exception> exceptionQueue = new Queue<Exception>(); //异常处理队列对象    /// <summary>    /// 控制器方法中出现异常,会调用该方法捕获异常    /// </summary>    /// <param name="filterContext"></param>    public override void OnException(ExceptionContext filterContext)    {      exceptionQueue.Enqueue(filterContext.Exception);//将捕获的异常信息写到队列中      filterContext.HttpContext.Response.Redirect("/Error.html");//跳转到错误页面      base.OnException(filterContext);    }  }}

 

2.将错误处理过滤器修改为自定义的异常处理过滤器

修改如下:

using System.Web;using System.Web.Mvc;using WebApp.Models;namespace WebApp{  public class FilterConfig  {    public static void RegisterGlobalFilters(GlobalFilterCollection filters)    {      //filters.Add(new HandleErrorAttribute());      filters.Add(new MyExceptionAttribute());//使用自定义异常处理的过滤器    }  }}

 

3.修改Global.asax文件,在程序首次加载的时候,开启线程扫描异常队列,处理异常信息

using Spring.Web.Mvc;using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Text;using System.Threading;using System.Web;using System.Web.Http;using System.Web.Mvc;using System.Web.Optimization;using System.Web.Routing;using WebApp.Models;namespace WebApp{  // 注意: 有关启用 IIS6 或 IIS7 经典模式的说明,  // 请访问 http://go.microsoft.com/?LinkId=9394801  public class MvcApplication : SpringMvcApplication //System.Web.HttpApplication  {    protected void Application_Start()    {      AreaRegistration.RegisterAllAreas();      WebApiConfig.Register(GlobalConfiguration.Configuration);      FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);      RouteConfig.RegisterRoutes(RouteTable.Routes);      BundleConfig.RegisterBundles(BundleTable.Bundles);      #region 开启线程扫描异队列,处理异常信息      string fileLogPath = Server.MapPath("/Log/");//知道用来保存错误日志文件的文件夹路径      //开启一个线程扫描日志队列      ThreadPool.UnsafeQueueUserWorkItem((a) =>      {        while (true)        {          if (MyExceptionAttribute.exceptionQueue.Count > 0) //判断队列中是否有数据          {            Exception ex = MyExceptionAttribute.exceptionQueue.Dequeue();//出队            if (ex != null)            {              string fileName = DateTime.Now.ToString("yyyy-MM-dd") + ".txt";              File.AppendAllText(fileLogPath + fileName, ex.ToString(), Encoding.Default);//将异常追加写入到文件中            }            else            {              Thread.Sleep(3000);            }          }          else          {            Thread.Sleep(3000);//如果队列中没有数据,让当前线程休息3秒钟,避免造成CPU空转,避免CPU的浪费          }        }      }, fileLogPath);      #endregion    }  }}

 

4.测试:

  public ActionResult Index()    {      int a = 2;      int b = 0;      int c = a / b;      return Content(c.ToString());    }

 

5.效果

 

6.其他说明:

1.解决高并发错误日志问题:
   1.1用传统lock方式,如果并发量很大的话,用户会出现卡顿的情况。
   1.2.在服务器开辟一个队列,存储用户错误信息,然后单独开启一个线程来处理,就不会有卡顿情况。(队列是在内存中,写入速度很快)
   这就是生产者消费者模式

2.Global下Application_Start()方法只在程序首次执行时调用

3.ThreadPool线程池线程性能很好,比我们自己创建线程的效率要高很多。

4.池用来解决对象频繁创建的问题,频繁创建消耗性能。

5.Queue是线程安全的,内部对多线程进行处理了,不会出现并发问题。

 

7.源码下载:

点击下载>>