• MVC中使用Action全局过滤器出现:网页无法正常运作 将您重定向的次数过多。解决办法


    前言当我们访问某个网站的时候需要检测用户是否已经登录(通过Session是否为null),我们知道在WebForm中可以定义一个BasePage类让他继承System.Web.UI.Page,重写它的OnInit()方法,在OnInit()中判断Session中是否有用户登录的信息。

    /// <summary>
        /// 公共基类里面干一些公共的事情
       /// </summary>
        public class BasePage : System.Web.UI.Page
        {
            //页面生命周期Init事件对应的OnInit()方法
            //这个方法会先于PageLoad方法执行
            //override 表示重写 OnInit方法 OnInit 方法,在所有控件都已初始化且已应用所有外观设置后引发。使用该事件来读取或初始化控件属性       
            protected override void OnInit(EventArgs e)
            {
                base.OnInit(e);
                if (Session["UserInfo"] == null)  //检查用户是否登录
                {
                       //跳转到登录页面
                }
            }
        }

     在mvc下该怎样校验呢?

    我们知道,MVC下可以自定义特性类为控制器或控制器中的Action打上[特性],这里只需要ActionFilter过滤器(Action方法执行前后执行),MVC提供了IActionFilter接口。(为了方便我们可以用微软提供好的ActionFilterAttribute类,他是筛选器特性的基类,也是一个抽象类,其实这个抽象类实现了IActionFilter和IResultFilter)

    IActionFilter接口的定义:

       //在执行操作方法后调用。  
           void OnActionExecuted(ActionExecutedContext filterContext);
           
              // 在执行操作方法之前调用。       
           void OnActionExecuting(ActionExecutingContext filterContext); 

    新建一个特性类LoginCheckFilterAttribute,让他继承ActionFilterAttribute,并重写其中的OnActionExecuting方法,在其中完成校验

    public class LoginCheckFilterAttribute : ActionFilterAttribute
        {
            //表示是否检查登录
            public bool IsCheck { get; set; }
    
            //Action方法执行之前执行此方法
            public override void OnActionExecuting(ActionExecutingContext filterContext)
            {
                base.OnActionExecuting(filterContext);
    
                if (IsCheck)
                {
                    //校验用户是否已经登录
                    if (filterContext.HttpContext.Session["loginUser"] == null)
                    {
                        //跳转到登陆页
                        filterContext.HttpContext.Response.Redirect("/UserLogin/Index");
                    }
                }
            }
        }

    怎么让这个过滤器起作用呢?

    步骤:1、在Global.asax文件中为MVC程序注册全局过滤器, 调用FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters)。FilterConfig类在App_Start文件夹中(创建新的MVC项目会自动生成),在FilterConfig的静态方法中public static void RegisterGlobalFilters(GlobalFilterCollection filters)注册全局过滤器

    public class FilterConfig
        {
            //这个方法是用于注册全局过滤器(在Global中被调用)
            public static void RegisterGlobalFilters(GlobalFilterCollection filters)
            {
                //filters.Add(new HandleErrorAttribute());
                filters.Add(new LoginCheckFilterAttribute() { IsCheck = true });
            }
        }

    注意要为特性类实例的IsCheck属性赋值true否则Session校验不起作用。

    这样子,LoginCheckFilterAttribute这个特性就会对整个MVC程序中的控制器和Action起作用了,就是说在执行Action方法之前会先调用特性类中的重写OnActionExecuting方法,这样用户在访问网站的时候会首先检测用户是否已经登录,如果没有登录会跳转到登录页面。

    但是!但是!问题来了,因为我们注册的是全局的过滤器,这个过滤特性会对所有的控制器下的Action起作用,当访问网站的时候会(比如我们注册默认路由为/Home/Index)会首先跳转到/Home/Index,这时不会执行Index方法,会先执行OnActionExecuting()中的校验,发现Session为null,Response.Redirect("/UserLogin/Index")跳转到了登录页面;这时我们在浏览器中依然看不到登录页面,为什么呢?还记得我们注册的全局的过滤器,作用对象包括所有控制器下的Action当然也包括/UserLogin/Index,代码走到了这里会再次执行OnActionExecuting()方法,发现Session["UserInfo"==]null,又跳到了登录页面,我们连登录页面都见不着肯定不能输入用户名密码Session也就不会有登录信息,浏览器会返回 ”此网页包含重定向循环“ 的错误页面,也就是说会一直循环不停的重定向到登录页面,类似死循环,浏览器当然罢工了。。

    该怎样解决这个bug的?

    解决方法:为UserLoginController控制器打上特性 

    [LoginCheckFilterAttribute(IsCheck = false)]  //打上用户登录校验特性(IsCheck设为false不让它对此控制器起作用,而对其他控制器和Action起作用,防止重定向循环)
        public class UserLoginController : Controller
        {
    
        ...
    
         }

    我们在定义这个特性类的时候 有个bool属性 IsCheck,它表示是否校验,这里设为false表示不校验。顺便说一下LoginCheckFilterAttribute可以省略Attrbute后缀。

    一定要在控制器上打这个特性,不要只针对下边的某个Action,因为这里边有生成验证码的Action和处理登录请求的Action,它们都不需要进行session校验(没意义),在控制器上打上特性会对它下边的所有Action起作用,不用为每个Action打特性了,节省代码量。我们注册了全局过滤器,又单独为UserLoginController控制器打上过滤特性,这里有一个优先级的问题Action>Controller>全局,UserLoginController不会受全局过滤器的影响。到这里测试一下,输入网站地址,成功进入登录页面。问题解决。

    本文主要参考了:http://www.cnblogs.com/Look_Sun/p/4425083.html这篇文章。我遇到这个问题的时候,看了这篇文章和我开发时候遇到的问题基本一样。但是那哥们写的全局过滤器好像有问题,只需要判断Session["userinfo"]==null的时候就可以,他把Session["userinfo"]!=null的时候也做了判断,并做了跳转到。所有当点击登陆的时候,重定向到了/Home/Index,但是到了Home又会是个死循环。

    MVC中过滤器中非常好的一个视屏:http://pan.baidu.com/s/1i5zwhjZ   回复我要密码  以后共同探讨问题

  • 相关阅读:
    Reactive Extensions (Rx) 入门(5) —— Rx的事件编程
    Reactive Extensions (Rx) 入门(4) —— Rx的事件编程
    Reactive Extensions (Rx) 入门(3) —— Rx的事件编程
    Reactive Extensions (Rx) 入门(2) —— 安装 Reactive Extensions
    Reactive Extensions (Rx) 入门(1) —— Reactive Extensions 概要
    Xamarin NuGet 缓存包导致 already added : Landroid/support/annotation/AnimRes 问题解决方案
    Android 系统Action大全
    Xamarin Forms 实现发送通知点击跳转
    如何理解灰度发布
    推荐一款分布式微服务框架 Surging
  • 原文地址:https://www.cnblogs.com/huangshuqiang/p/5372348.html
Copyright © 2020-2023  润新知