zoukankan      html  css  js  c++  java
  • ASP.NET MVC 过滤器

    APS.NET MVC中(以下简称“MVC”)的每一个请求,都会分配给相应的控制器和对应的行为方法去处理,而在这些处理的前前后后如果想再加一些额外的逻辑处理。这时候就用到了过滤器。

    MVC的过滤器类型

    过滤器类型

    接口

    描述

    Authorization

    IAuthorizationFilter

    此类型(或过滤器)用于限制进入控制器或控制器的某个行为方法

    Exception

    IExceptionFilter

    用于指定一个行为,这个被指定的行为处理某个行为方法或某个控制器里面抛出的异常

    Action

    IActionFilter

    用于进入行为之前或之后的处理

    Result

    IResultFilter

    用于返回结果的之前或之后的处理

    过滤器类型

    接口

    默认实现

    描述

    Authorization

    IAuthorizationFilter

    AuthorizationAttribute

    最先运行

    Action

    IActionFilter

    ActionFilterAttribute

    在动作方法前后运行

    Result

    IResultFilter

    ActionResultAttribute

    在动作结果被执行前后

    Exception

    IExceptionFilter

    HandlerErrorAttribute

    仅在过滤器、动作发生异常时

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

    过滤器

    类名

    实现接口

    描述

    ActionFilter

    AuthorizeAttribute

    IAuthorizationFilter

    此类型(或过滤器)用于限制进入控制器或控制器的某个行为方法

    HandleError

    HandleErrorAttribute

    IExceptionFilter

    用于指定一个行为,这个被指定的行为处理某个行为方法或某个控制器里面抛出的异常

    自定义

    ActionFilterAttribute

    IActionFilter和IResultFilter

    用于进入行为之前或之后的处理或返回结果的之前或之后的处理

    一:Authorize(授权过滤器)

    (1)默认Authorize使用

       [Authorize]
            public ActionResult ChangePassword()
            {
                return View();
            }

    如果要通过验证,通过调用FormsAuthentication.SetAuthCookie方法来获得授权,登陆的页面如下

    @model FilterTest.Models.LogInModel
    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <title>Login</title>
    </head>
    <body>
        <div>
        @using( Html.BeginForm()){
           <div>
            ID:@Html.TextBoxFor(m=>m.UserName)
            <br />
            Password:@Html.PasswordFor(m => m.Password)
            <br />
            <input type="submit" value="login" />
           </div>
        }
        </div>
    </body>
    </html>

    后台方法

    [HttpPost]//这里用了谓词过滤器,只处理POST的请求
            public ActionResult Login(LogInModel login)
            {
                if (login.UserName == "admin" && login.Password == "123456")
                {
                    FormsAuthentication.SetAuthCookie(login.UserName, false);
                    return Redirect("/Customer/ChangePassword");
                }
    
                return View();
            }

    当然有登录也要有注销,因为注销是在登陆之后发生的,没登陆成功也就没有注销,所以注销的行为方法也要加上Authorize过滤器,注销调用的是FormsAuthentication.SignOut方法,代码如下

    [Authorize]
            public ActionResult LogOut()
            {
                FormsAuthentication.SignOut();
                return Redirect("/Customer/Login");
            }

    (2)自定义授权

    我们不一定要用MVC默认的Authorize授权验证规则,规则可以自己来定,自定义授权过滤器可以继承AuthorizeAttribute这个类,这个类里面有两个方法是要重写的

    •          bool AuthorizeCore(HttpContextBase httpContext):这里主要是授权验证的逻辑处理,返回true的则是通过授权,返回了false则不是。
    •          void HandleUnauthorizedRequest(AuthorizationContext filterContext):这个方法是处理授权失败的事情。
    • public class MyAuthorizeAttribute:AuthorizeAttribute
          {
              
              protected override bool AuthorizeCore(HttpContextBase httpContext)
              {
                  //return base.AuthorizeCore(httpContext);
                  return DateTime.Now.Minute % 2 == 0
              }
      
              
              protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
              {
                  filterContext.HttpContext.Response.Redirect("/Customer/Login");
                  
                  //base.HandleUnauthorizedRequest(filterContext);
              }
          }

      然后用到行为方法上

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

      每当偶数分钟的时候就可以访问这个ShowDetail的视图了,否则就会调到了登陆页面了

    二:处理错误过滤器HandleError

    (1) 默认HandleError使用

             HandleErroe的属性如下

    属性名称

    类型

    描述

    ExceptionType

    Type

    要处理的异常的类型,相当于Try/Catch语句块里Catch捕捉的类型,如果这里不填的话则表明处理所有异常

    View

    String

    指定需要展示异常信息的视图,只需要视图名称就可以了,这个视图文件要放在Views/Shared文件夹里面

    Master

    String

    指定要使用的母版视图的名称

    Order

    Int

    指定过滤器被应用的顺序,默认是-1,而且优先级最高的是-1

               这个Order属性其实不只这个HandleError过滤器有,其优先级规则和其它过滤器的都是一样的。

      [HandleError(ExceptionType = typeof(Exception))]
            public ActionResult ThrowErrorLogin()
            {
                throw new Exception("this is ThrowErrorLogin Action Throw");
            }

    光是这样还不够,还要到web.config文件中的<system.web>一节中添加以下代码

    <customErrors mode="On" />
    四:自定义过滤器
    万一前面介绍的过滤器也满足不了需求,要在行为方法执行返回的前前后后定义自己的处理逻辑的话,这个自定义过滤器就应该能派上用场了。若要自定义一个过滤器,则要继承ActionFilterAttribute类,这个类是一个抽象类,实现了IActionFilter和IResultFilter接口,主要通过重写四个虚方法来达到在行为方法执行和返回的前后注入逻辑

    方法

    参数

    描述

    OnActionExecuting

    ActionExecutingContext

    在行为方法执行前执行

    OnActionExecuted

    ActionExecutedContext

    在行为方法执行后执行

    OnResultExecuting

    ResultExecutingContext

    在行为方法返回前执行

    OnResultExecuted

    ResultExecutedContext

    在行为方法返回后执行

    四个方法执行顺序是OnActionExecuting——>OnActionExecuted——>OnResultExecuting——>OnResultExecuted。上面四个方法的参数都是继承基ContollorContext类。例如下面定义了一个自定义的过滤器

    public class MyCustomerFilterAttribute : ActionFilterAttribute
        {
            public string Message { get; set; }
    
            public override void OnActionExecuted(ActionExecutedContext filterContext)
            {
                base.OnActionExecuted(filterContext);
                filterContext.HttpContext.Response.Write(string.Format( "<br/> {0} Action finish Execute.....",Message));
            }
    
            public override void OnActionExecuting(ActionExecutingContext filterContext)
            {
                CheckMessage(filterContext);
                filterContext.HttpContext.Response.Write(string.Format("<br/> {0} Action start Execute.....", Message));
                base.OnActionExecuting(filterContext);
            }
    
            public override void OnResultExecuted(ResultExecutedContext filterContext)
            {
                filterContext.HttpContext.Response.Write(string.Format("<br/> {0} Action finish Result.....", Message));
                base.OnResultExecuted(filterContext);
            }
    
            public override void OnResultExecuting(ResultExecutingContext filterContext)
            {
                filterContext.HttpContext.Response.Write(string.Format("<br/> {0} Action start Execute.....", Message));
                base.OnResultExecuting(filterContext);
            }
    
            private void CheckMessage(ActionExecutingContext filterContext)
            { 
                if(string.IsNullOrEmpty( Message)||string.IsNullOrWhiteSpace(Message))
                    Message = filterContext.Controller.GetType().Name + "'s " + filterContext.ActionDescriptor.ActionName;
            }
        }

    (1)使用它的行为方法定义

    [MyCustomerFilter]
            public ActionResult CustomerFilterTest()
            {
                Response.Write("<br/>Invking CustomerFilterTest Action");
                return View();
            }

    执行结果如下

              验证了执行顺序

    (2) 当控制器也使用上这个过滤器时,而行为方法不使用时,结果

    这个也验证了结果顺序
    (3)如果控制器和行为方法都使用了过滤器,理论上是显示上面两个结果的结合,但是实际上不是,因为在定义过滤器的时候还少了
    一个特性:[AttributeUsage(AttributeTargets.All, AllowMultiple = true)],把这个加上
       [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]//多次调用
        public class MyCustomerFilterAttribute : ActionFilterAttribute
        {
            ……
        }
    结果执行顺序

    可以看出,同一个过滤器分别用在了控制器和行为方法中,执行同一个方法都会有先后顺序,如果按默认值,一般顺序都是由最外层到最里层,就是"全局"--控制器--行为方法,而错误处理的过滤器,由于异常是由里往外抛,行为方法---控制器---全局。

    全局的过滤器在Global.asax文件里面的RegisterGlobalFilters(GlobalFilterCollection filters)中设置的

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
            {
                filters.Add(new HandleErrorAttribute());
                filters.Add(new MyFilters.MyCustomerFilterAttribute() { Message="Global"});//全局过滤器
            }

    转自 :http://www.cnblogs.com/HopeGi/p/3342083.html#commentform

    
    
     


    111111
  • 相关阅读:
    Binary Tree Zigzag Level Order Traversal
    Add Binary
    Subsets II
    Subsets
    Minimum Depth of Binary Tree
    node Cannot enqueue Quit after invoking quit.
    微擎快速修改数量实例(异步)
    destoon 分页
    ajax里面使用this方法
    微擎系统 微信支付 get_brand_wcpay_request:fail
  • 原文地址:https://www.cnblogs.com/whl4835349/p/9523348.html
Copyright © 2011-2022 走看看