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   回复我要密码  以后共同探讨问题

时间: 2024-10-10 09:41:47

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

通过定制特性灵活判断C# mvc中的action是否需要登录验证

在实现通过定制特性灵活判断mvc中的action是否需要登录验证之前,先简单讲两个知识点: 1.每个action执行前都会先执行OnActionExecuting方法: 2.FCL提供了多种方式来检测特性的存在,比如IsDefined.GetCustomAttributes方法等,IsDefined方法仅仅是判断目标有没有应用指定特性,而GetCustomAttributes方法会构造指定特性的新实例. 一.下面先利用OnActionExecuting和IsDefined这两个方法实现判断act

关于Eclipse中Jsp页面打不开并且显示Failed to create the part&#39;s controls的解决办法

问题描述:同事从svn上导入的一个项目,jdk都设置好了以后,java.xml.html等文件都能打开,唯独jsp文件打不开,并且显示Failed to create the part's controls,但有小部分jsp是可以打开的. 解决过程:我在网上搜索了Failed to create the part's controls这个关键语句,网上解决办法1:关闭Eclipse再打开:办法2:切换工作空间式重启:办法3:jdk版本的问题.前两种办法都试过了,最后一种是不存在的情况,但都没有解

MVC下用户登录状态校验的问题以及解决方案--------------Action全局过滤器的使用

前言当我们访问某个网站的时候需要检测用户是否已经登录(通过Session是否为null),我们知道在WebForm中可以定义一个BasePage类让他继承System.Web.UI.Page,重写它的OnInit()方法,在OnInit()中判断Session中是否有用户登录的信息 1 /// <summary> 2 /// 公共基类里面干一些公共的事情 3 /// </summary> 4 public class BasePage : System.Web.UI.Page 5

Java中使用Jsoup抓取网页URL时出现中文汉字乱码的问题及解决办法

public static String readHtml(String myurl) { StringBuffer sb = new StringBuffer(""); URL url; try { url = new URL(myurl); BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream(), "gbk")); String s = "";

Android中 在显示ImageView时图片上面和下面都出现一段空白区间的解决办法

开始的时候是在ScrollView中显示ImageView的时候出现这样的问题,以为是要对ScrollView进行设置的,后来发现单独显示一个ImageView的时候也会出现这样的问题,由此才知道是应该对ImageView进行设置啦- 解决办法如下喽- 1.在XML文件中设置: android:adjustViewBounds="true" 2.在Java代码中进行设置: mImageView.setAdjustViewBounds(true);

在WIn32程序中使用MFC的CInternetSession运行异常,主要是因为获取目前应用程序名出错的解决办法

转载:http://group.gimoo.net/review/22564 头文件#include <afxinet.h"> 在非MFC工程中使用CInternetSession抛异常的原因,调试跟踪到说AfxGetAppName为空 解决办法:创建CInternetSession 有参对象 CInternetSession InternetSession(_T("myagent"));

ASP.NET MVC 使用jquery.form.js 异步上传 在IE下返回值被变为下载的解决办法

错误记录: <script type="text/javascript"> $(function () { $(document).off("ajaxSend"); //异步上传 $("#Submit").click(function () { if ($("#selectFileButton").val() == "") { return false; } $("#fileForm&

mvc中的action验证登录(ActionFilterAttribute)

方法一 :  1.创建一个全局action过滤器  (在appstart  的filterconfig中注册   filters.Add(new LoginAttribute());)  2.不需要登录的contoller或者action  则在该类或者action上添加该过滤器特性 (isNeed=false) 方法二: 1.创建一个filter 不在全局注册 2. 创建 一个baseControler ,然后再basecontroller上边添加该filter特性 3.需要登录的则继承该ba

(五)ASP.NET MVC 中关于 Action 的参数

在ASP.NET MVC 的 Controller 类下有多个 Method,如果这些 Method 都是 public 修饰的和返回值类型是 ActionResult 类型的,这些方法就时 Action.通过 "Controller 名字/方法名" 访问的时候就会执行对应的方法. Action 有三种类型的参数:普通参数,Model 类, FormCollection. 普通参数:构架会自动把用户请求的值根据参数名字映射到对应的值. Model 类:这种类叫 ViewModel Fo