ASP.NET MVC过滤器的使用

过滤器的简介

为什么要用过滤器

例如在生活中,乘坐火车、地铁、飞机等一般情况下要将行李进行安检,安检的主要作用:1.规范人们的出行行为。2.保证公共秩序的安全

  1. 调用动作方法之前,或方法调用之后执行的一些业务逻辑,比如“检查当前请求是否授权?方法执行后出现错误如何处理?”,本质就是对动作方法的执行过程进行干预,和Java中Struts里面拦截器有类似作用
  2. 提供了一种向控制器行为方法中添加“前行为(Pre-action)和后行为(Post-action)”的方法

过滤器的理解

  1. 在ASP.NET MVC中继承自拔FilterAttribute的类统称为过滤器
  2. 其实Authorize、HandleError、OutputCahce这些类都直接或者间接继承自FilterAttribute类

过滤器的分类

  1. Authorize(授权):该过滤器用来限制进入控制器的行为
  2. HandleError(处理错误):该过滤器用来限定一个行为,这个行为用来处理某个行为方法中跑出来的异常
  3. OutputCahce(缓存):该过滤器用来为行为方法提供输出缓存
  4. 自定义过滤器:开发者自己根据需要创建的过滤器,例如:日志、权限等

过滤器接口

接口类型 方法 说明
IActionFilter void OnActionExecuted void OnActionExecuting 在执行动作方法后调用 在执行动作方法前调用
IResultFilter void OnResultExecuted void OnResultExecuting 在操作结果执行之后调用 在操作结果执行之前调用
IExceptionFilter void OnException 在发生异常的时候调用
IAuthorizationFilter void OnAuthorization 在需要授权的时候调用

这些接口在自定义过滤器的时候并非全部继承根据实际需求选择

自定义日志过滤器

条件
自定义过滤器的条件

  1. 实现任意一个或多个过滤器接口
  2. 继承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对象所继承的这些过滤器接口中的方法都可以重写

总结

  1. 过滤器的三种应用小结
    1. 应用到动作方法上:作用于这个动作方法
    2. 应用到控制器上:作用于这个控制中所有的动作方法
    3. 应用到整个程序中:作用于所有动作方法
  2. FilterConfig.cs文件
    1. 作用:注册全局过滤器
    2. 默认:已将错误处理作为全局过滤器
    3. 扩展:可以添加自己定义的过滤器作为全局过滤器

过滤器的执行顺序

  1. 类上的过滤器优先于方法上的过滤器
  2. 按Order属性从小到大执行
    [Filters.ActionFilter(Order =1)]
    [Filters.ExceptionFilter(Order =2)]
  3. 控制器中重写的过滤器接口方法优先执行
  4. 异常过滤器执行顺序错误
    错误过滤器如果要详细到错误的根本原因,这个错误顺序和之前学习try catch异常捕获顺序要一样,都是从小的错误到大的错误进行顺序
    例如:针对数据库查询等做异常,首先先捕获SqlException异常,如果这个异常捕获不到在进行Exception
        [HandleError(ExceptionType = typeof(SqlException), View = "Error")]
        [HandleError(ExceptionType = typeof(System.Exception), View = "Error")]

猜你喜欢

转载自blog.csdn.net/dust__/article/details/106205772