过滤器的简介
为什么要用过滤器
例如在生活中,乘坐火车、地铁、飞机等一般情况下要将行李进行安检,安检的主要作用:1.规范人们的出行行为。2.保证公共秩序的安全
- 调用动作方法之前,或方法调用之后执行的一些业务逻辑,比如“检查当前请求是否授权?方法执行后出现错误如何处理?”,本质就是对动作方法的执行过程进行干预,和Java中Struts里面拦截器有类似作用
- 提供了一种向控制器行为方法中添加“前行为(Pre-action)和后行为(Post-action)”的方法
过滤器的理解
- 在ASP.NET MVC中继承自拔FilterAttribute的类统称为过滤器
- 其实Authorize、HandleError、OutputCahce这些类都直接或者间接继承自FilterAttribute类
过滤器的分类
- Authorize(授权):该过滤器用来限制进入控制器的行为
- HandleError(处理错误):该过滤器用来限定一个行为,这个行为用来处理某个行为方法中跑出来的异常
- OutputCahce(缓存):该过滤器用来为行为方法提供输出缓存
- 自定义过滤器:开发者自己根据需要创建的过滤器,例如:日志、权限等
过滤器接口
接口类型 | 方法 | 说明 |
---|---|---|
IActionFilter | void OnActionExecuted void OnActionExecuting | 在执行动作方法后调用 在执行动作方法前调用 |
IResultFilter | void OnResultExecuted void OnResultExecuting | 在操作结果执行之后调用 在操作结果执行之前调用 |
IExceptionFilter | void OnException | 在发生异常的时候调用 |
IAuthorizationFilter | void OnAuthorization | 在需要授权的时候调用 |
这些接口在自定义过滤器的时候并非全部继承根据实际需求选择
自定义日志过滤器
条件
自定义过滤器的条件
- 实现任意一个或多个过滤器接口
- 继承FilterAttribute
自定义错误日志过滤器
实现系统发生异常后,将异常信息保存下来,便于追踪错误
/// <summary>
/// 自定义的错误日志过滤器
/// </summary>
public class LogExceptionFilter : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
//定义一个日志文件路径
string filepath = filterContext.HttpContext.Server.MapPath(@"~/Log/log.txt");
//写入日志信息
using (StreamWriter writer=File.AppendText(filepath))
{
writer.WriteLine($"时间:{DateTime.Now}");
writer.WriteLine($"控制器:{filterContext.RouteData.Values["Controller"]}");
writer.WriteLine($"动作方法:{filterContext.RouteData.Values["Action"]}");
writer.WriteLine($"异常信息:{filterContext.Exception.Message}");
writer.WriteLine("----------------------------------------------------------------------------------------------");
}
}
}
创建的过滤器只要是继承了FilterAttribute类,我们创建的对象就是一个特性,使用方式和.NET中提供的常用的特性使用方式一致
在需要添加错误过滤的地方使用
[HttpPost]
[HandleError(ExceptionType = typeof(System.Exception), View = "Error")]
[Filters.LogExceptionFilter]
public ActionResult GetUserInfor(int Id)
{
UserServer server = new UserServer();
UserInfor user = server.GetUserDetail(Id);
ViewBag.User = user;
return View();
}
重写过滤器接口
在“控制器中,可以重写过滤器接口的方法
public class HomeController : Controller
{
protected override void OnException(ExceptionContext filterContext)
{
//定义一个日志文件路径
string filepath = filterContext.HttpContext.Server.MapPath(@"~/Log/log.txt");
//写入日志信息
using (StreamWriter writer = System.IO.File.AppendText(filepath))
{
writer.WriteLine($"时间:{DateTime.Now}");
writer.WriteLine($"控制器:{filterContext.RouteData.Values["Controller"]}");
writer.WriteLine($"动作方法:{filterContext.RouteData.Values["Action"]}");
writer.WriteLine($"异常信息:{filterContext.Exception.Message}");
writer.WriteLine("----------------------------------------------------------------------------------------------");
}
}
重写Controller类所继承的过滤器方法之后则不需要单独给某个行为方法添加特性,默认是对整个控制器内的行为方法进行使用过滤器
//
// 摘要:
// 提供用于响应对 ASP.NET MVC 网站所进行的 HTTP 请求的方法。
public abstract class Controller : ControllerBase, IActionFilter, IAuthenticationFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter, IAsyncController, IController, IAsyncManagerContainer
Controller对象所继承的这些过滤器接口中的方法都可以重写
总结
- 过滤器的三种应用小结
- 应用到动作方法上:作用于这个动作方法
- 应用到控制器上:作用于这个控制中所有的动作方法
- 应用到整个程序中:作用于所有动作方法
- FilterConfig.cs文件
- 作用:注册全局过滤器
- 默认:已将错误处理作为全局过滤器
- 扩展:可以添加自己定义的过滤器作为全局过滤器
过滤器的执行顺序
- 类上的过滤器优先于方法上的过滤器
- 按Order属性从小到大执行
[Filters.ActionFilter(Order =1)]
[Filters.ExceptionFilter(Order =2)] - 控制器中重写的过滤器接口方法优先执行
- 异常过滤器执行顺序错误
错误过滤器如果要详细到错误的根本原因,这个错误顺序和之前学习try catch异常捕获顺序要一样,都是从小的错误到大的错误进行顺序
例如:针对数据库查询等做异常,首先先捕获SqlException异常,如果这个异常捕获不到在进行Exception
[HandleError(ExceptionType = typeof(SqlException), View = "Error")]
[HandleError(ExceptionType = typeof(System.Exception), View = "Error")]