笨鸟先飞之ASP.NET MVC系列之过滤器(06异常过滤器)

时间:2022-11-01 02:46:19

概念介绍

异常过滤器主要在我们方法中出现异常的时候触发,一般我们用 异常过滤器 记录日志,或者在产生异常时做友好的处理

如果我们需要创建异常过滤器需要实现IExceptionFilter接口。

namespace System.Web.Mvc
{
//
// 摘要:
// 定义异常筛选器所需的方法。
public interface IExceptionFilter
{
//
// 摘要:
// 在发生异常时调用。
//
// 参数:
// filterContext:
// 筛选器上下文。
void OnException(ExceptionContext filterContext);
}
}

我们看到该接口里只有一个方法OnException,这个方法在在我们调用需要过滤的方法出现异常时触发。

OnException

我们已经知道了OnException方法是在动作方法抛出异常时被调用的那么我们就可以利用这个方法在这里对异常进行处理,比如记录日志,比如重定向在OnException方法中传递的参数是一个ExceptionContext对象,它继承于ControllerContext类,它的属性如下:

名称 类型 说明
Exception Exception 获取或设置异常对象。
ExceptionHandled bool 获取或设置一个值,该值指示是否已处理异常。。
Result ActionResult 获取或设置操作结果。

执行OnException方法

下面我将演示OnException方法,首先我们还是在之前的Filter文件夹下添加一个名为 ErrorExceptionFilterAttribute.cs 的过滤器类,我们继承 FilterAttribute 类和 IExceptionFilter 接口,为了方便演示,我们简单处理,我们会在调用的方法中抛出一个异常并记录我请求的json数据

这里我们直接引用log4net来实现记录日志的功能

这是我们在 ErrorExceptionFilterAttribute.cs 文件中编写的代码

 public class ErrorExceptionFilterAttribute : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
Stream inputStream = filterContext.HttpContext.Request.InputStream;
inputStream.Position = 0;
var contentEncoding= filterContext.HttpContext.Request.ContentEncoding;
var streamReader = new StreamReader(inputStream,contentEncoding);
var errorMsg = streamReader.ReadToEnd();
var logger = LogManager.GetLogger(typeof(ErrorExceptionFilterAttribute));
logger.Error(errorMsg);
var Url = new UrlHelper(filterContext.RequestContext);
var url = Url.Action("Login", "Account");
filterContext.Result = new RedirectResult(url);
}
}

在我们的动作方法抛出异常时我们在这里从接受的请求中取出json数据并保存到日志里,并把页面从新定向到登录页。

过滤器写好了接着我们去相应的方法里加上我们的异常过滤器,并且使该动作方法抛出异常

        [ErrorExceptionFilter]
public ActionResult Index()
{
throw new ArgumentNullException();
}

好了我们运行程序,并且在浏览器里直接请求我们这个方法,我们看看效果

笨鸟先飞之ASP.NET MVC系列之过滤器(06异常过滤器)

咦,我们发现页面并没有重定向到登录页而且抛了黄页这是为什么呢?这是因为我们在异常过滤器中少了一步操作我们需要把它的ExceptionHandled属性设置为true,表示我们处理过这个异常了,这样我们就能得到应用的效果了,接着我们把少的那句话加上

 public class ErrorExceptionFilterAttribute : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
Stream inputStream = filterContext.HttpContext.Request.InputStream;
inputStream.Position = 0;
var contentEncoding= filterContext.HttpContext.Request.ContentEncoding;
var streamReader = new StreamReader(inputStream,contentEncoding);
var errorMsg = streamReader.ReadToEnd();
var logger = LogManager.GetLogger(typeof(ErrorExceptionFilterAttribute));
logger.Error(errorMsg);
filterContext.ExceptionHandled = true;
var Url = new UrlHelper(filterContext.RequestContext);
var url = Url.Action("Login", "Account");
filterContext.Result = new RedirectResult(url);
}
}

我们再来看看

笨鸟先飞之ASP.NET MVC系列之过滤器(06异常过滤器)

笨鸟先飞之ASP.NET MVC系列之过滤器(06异常过滤器)

果然还是我们熟悉的那个登录页面

接着我们去模拟一条请求,向我们的抛异常的地址发送一条json数据接着我们去看看我们的日志

笨鸟先飞之ASP.NET MVC系列之过滤器(06异常过滤器)

总结

异常过滤器个人感觉也是很重要,毕竟我们都会犯错而一个完善的日志系统或者一个良好的处理页面,都是对错误最好的补救措施,毕竟防范于未然,我们可以在Global中配置异常过滤器让其在全局都生效。

我们如果新建一个MVC的项目我们会发现在Global中有这么一句话FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 这个表示注册全局过滤器,GlobalFilters是全局过滤器的集合,也就是说我们所有的过滤器都能通过在GlobalFilters中Add来做到全局适配。