ASP.NET MVC中Filter过滤器的使用

04-27 1986阅读 0评论

MVC Filter是典型的AOP(面向切面编程)应用,在ASP.NET MVC中的4个过滤器类型,如下:

ASP.NET MVC中Filter过滤器的使用

但是默认实现它们的过滤器只有三种,分别是ActionFilter(方法),Authorize(授权),HandleError(错误处理)。

  • 特性(Attribute)是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。
  • 特性(Attribute)用于添加元数据,如编译器指令和注释、描述、方法、类等其他信息。.Net 框架提供了两种类型的特性:预定义特性和自定义特性

    Filter的默认实现方式就是带有Attribute后缀的,有了Attribute,我们就可以将我们的Filter像标签一样的贴在方法或者控制器的上方

    Web Api:   System.Web.Http.Filters.ActionFilterAttribute 继承该类

    • OnActionExecuting  执行前
    • OnActionExecuted   执行后
    • OnResultExecuting  返回前
    • OnResultExecuted   返回后

      Mvc:   System.Web.Mvc.ActionFilterAttribute  继承该类

      • OnActionExecuting  执行前  
      • OnActionExecutingAsync  执行前(异步)
      • OnActionExecuted   执行后 
      •  OnActionExecutedAsync   执行后(异步)

        1、Action过滤器在ASP.NET MVC中创建MvcApp项目,创建文件夹Filter,然后新建类MyActionFilterAttribute(为了遵循默认的约定,名称以Attribute结尾),继承自ActionFilterAttribute类。ActionFilterAttribute类有如下4个方法。

        using System;
         
        namespace System.Web.Mvc
        {
            [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
            public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter
            {
         
                protected ActionFilterAttribute();
         
                public virtual void OnActionExecuted(ActionExecutedContext filterContext);
         
                public virtual void OnActionExecuting(ActionExecutingContext filterContext);
         
                public virtual void OnResultExecuted(ResultExecutedContext filterContext);
         
                public virtual void OnResultExecuting(ResultExecutingContext filterContext);
            }
        }

        实现MyActionFilterAttribute类:

        using System;
        using System.Web.Mvc;
         
        namespace MvcApp.Filter
        {
            public class MyActionFilterAttribute : ActionFilterAttribute
            {
                public override void OnActionExecuting(ActionExecutingContext filterContext)
                {
                    //1、获取请求的类名和方法名
                    string strController = filterContext.RouteData.Values["controller"].ToString();
                    string strAction = filterContext.RouteData.Values["action"].ToString();
         
                    //2、用另一种方式获取请求的类名和方法名
                    string strController2 = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
                    string strAction2 = filterContext.ActionDescriptor.ActionName;
         
                    filterContext.HttpContext.Response.Write("控制器:" + strController + "
        "); filterContext.HttpContext.Response.Write("控制器:" + strController2 + "
        "); filterContext.HttpContext.Response.Write("Action:" + strAction + "
        "); filterContext.HttpContext.Response.Write("Action:" + strAction2 + "
        "); filterContext.HttpContext.Response.Write("Action执行前:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "
        "); base.OnActionExecuting(filterContext); } public override void OnActionExecuted(ActionExecutedContext filterContext) { filterContext.HttpContext.Response.Write("Action执行后:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "
        "); base.OnActionExecuted(filterContext); } } }

        对于过滤器,我们可以把它们加在3个地方,一个是控制器上面(控制器下面的所有Action),一个是Action上面(指定标识的Action),另一个就是全局位置(所有控制器中的Action)。这里只演示在Action上面和Home控制器中:

        [MyActionFilter]
        public ActionResult Index()
        {
            return View();
        }

        2、Result过滤器

        新建MyResultFilterAttribute类,继承ActionFilterAttribute:

        using System;
        using System.Web.Mvc;
         
        namespace MvcApp.Filter
        {
            public class MyResultFilterAttribute : ActionFilterAttribute
            {
                /// 
                /// 加载“视图”前执行
                /// 
                /// 
                public override void OnResultExecuting(ResultExecutingContext filterContext)
                {
                    filterContext.HttpContext.Response.Write("加载视图前执行 OnResultExecuting" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "
        "); base.OnResultExecuting(filterContext); } /// /// 加载“视图”后执行 /// /// public override void OnResultExecuted(ResultExecutedContext filterContext) { filterContext.HttpContext.Response.Write("加载视图后执行 OnResultExecuted" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "
        "); base.OnResultExecuted(filterContext); } } }

        这里把MyResultFilter过滤器加在控制器上面,相当于给Home控制器中的所有的Action方法添加了MyResultFilter过滤器。

        using MvcApp.Filter;
        using System.Web.Mvc;
         
        namespace MvcApp.Controllers
        {
            [MyResultFilter]
            public class HomeController : Controller
            {
                [MyActionFilter]
                public ActionResult Index()
                {
                    return View();
                }
         
            }
        }

        3、AuthorizeAttribute过滤器

        创建MyAuthorizeAttribute类,继承AuthorizeAttribute类:

        using System.Web.Mvc;
         
        namespace MvcApp.Filter
        {
            /// 
            /// 授权过滤器
            /// 
            public class MyAuthorizeAttribute : AuthorizeAttribute
            {
                public override void OnAuthorization(AuthorizationContext filterContext)
                {
                    filterContext.HttpContext.Response.Write("OnAuthorization
        "); //注释掉父类方法,因为父类里的OnAuthorization方法会调用ASP.NET的授权验证机制 //base.OnAuthorization(filterContext); } } }

        在控制器Home中的Index上添加MyAuthorize过滤器:

        [MyAuthorize]
        [MyActionFilter]
        public ActionResult Index()
        {
            return View();
        }

        通常Authorize过滤器也是在全局过滤器上面的,主要用来做登录验证或者权限验证,在App_Start目录下的FilterConfig类的RegisterGlobalFilters方法中添加:

        public class FilterConfig
        {
            public static void RegisterGlobalFilters(GlobalFilterCollection filters)
            {
                //filters.Add(new HandleErrorAttribute());
         
                //添加全局授权过滤器
                filters.Add(new MyAuthorizeAttribute());
            }
        }

        在全局中注册过滤器,则所有控制器的所有行为(Action)都会执行这个过滤器。

        运行结果,如下图:

        ASP.NET MVC中Filter过滤器的使用

        4、Exception过滤器

        创建MyHandleErrorAttribute类,继承HandleErrorAttribute类:

        using System;
        using System.Web.Mvc;
         
        namespace MvcApp.Filter
        {
            /// 
            /// 异常处理过滤器
            /// 
            public class MyHandleErrorAttribute : HandleErrorAttribute
            {
                public override void OnException(ExceptionContext filterContext)
                { 
                    //1、获取异常对象
                    Exception ex = filterContext.Exception;
                    
                    //2、记录异常日志
         
                    //3、重定向友好页面
                    filterContext.Result = new RedirectResult("~/error.html");
         
                    //4、标记异常已经处理完毕
                    filterContext.ExceptionHandled = true;
         
                    base.OnException(filterContext);
                }
            }
        }

        在Action上面添加MyHandleError过滤器:

        [MyHandleError]
        public ActionResult GetErr()
        {
            int a = 0;
            int b = 1 / a;
            return View();
        }

        创建异常错误友好提示页面error.html。

            自定义错误页面
        

        运行会自动跳转到error.html页面。

        如果页面没有跳转,就需要去Web.config配置文件中的节点下面添加如下配置节点,开启自定义错误:

         
        

        通常这样的异常处理是放在全局过滤器上面的,只要任意Action方法报错就会执行MyHandleError过滤器中的代码。

        修改App_Start目录下面的FilterConfig类:

        public class FilterConfig
        {
            public static void RegisterGlobalFilters(GlobalFilterCollection filters)
            {
                //filters.Add(new HandleErrorAttribute());
         
                //添加全局授权过滤器
                filters.Add(new MyAuthorizeAttribute());
         
                //添加全局异常处理过滤器
                filters.Add(new MyHandleErrorAttribute());
            }
        }

        Global.asax下的代码:

        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Web;
        using System.Web.Mvc;
        using System.Web.Optimization;
        using System.Web.Routing;
         
        namespace MvcApp
        {
            public class MvcApplication : System.Web.HttpApplication
            {
                protected void Application_Start()
                {
                    AreaRegistration.RegisterAllAreas();
                    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
                    RouteConfig.RegisterRoutes(RouteTable.Routes);
                    BundleConfig.RegisterBundles(BundleTable.Bundles);
                }
            }
        }

免责声明
本网站所收集的部分公开资料来源于AI生成和互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,1986人围观)

还没有评论,来说两句吧...

目录[+]