ASP.NET MVC中如何检测会话过期

26
我建立了一个购物车,使用Session State在用户浏览商店时保留购物车数据。
如果我在购物车的第1步长时间不关闭浏览器窗口,然后点击“转到第2步”,我的操作会抛出错误,因为第2步操作假定会话没有过期且ShopCart对象处于正确状态。
我希望这种情况对我的用户更友好,但我认为我需要某种方式检测会话是否过期,以便在下一次请求时将它们引导到Step1。
我找到了下面的代码,它声称可以解决这个问题,但对我不起作用。
IsNewSession条件为true,但条件可能是:
if ((null != sessionCookie) && (sessionCookie.IndexOf("ASP.NET_SessionId") >= 0)) {
   // handle expired session
}

这个函数始终返回 false,而且它从不处理无效的会话。我很困惑。

在 ASP.NET(和 MVC)中是否可能实现这种情况?

3个回答

18

方法1

将以下代码放置在第二页的Init / Load事件中...

        if (Context.Session != null)
        {
            if (Context.Session.IsNewSession)
            {
                string sCookieHeader = Request.Headers["Cookie"];
                if ((null != sCookieHeader) && (sCookieHeader.IndexOf("ASP.NET_SessionId") >= 0))
                {

                    if (Request.IsAuthenticated)
                    {
                        FormsAuthentication.SignOut();
                    }
                    Response.Redirect("Error Page");
                }
            }
        }

方法二

另一种方法是在进入第二个页面之前检查Session对象是否存在,例如:

if (Session["Key"] != null)
{
   Object O1 = (Object) Session["Key"]; 
}
else
{
    Response.Redirect("ErrorPage.aspx");
}

1
如果用户在登录状态下关闭浏览器(会话仍然存在)...那么在会话过期后再返回会发生什么? - Paul Zahra

15

国王的回答对我没有用。我已经在OnActionExcuting()中添加了FormsAuthentication.SignOut()。但是Response.Redirect不起作用!

if (Request.IsAuthenticated)
{
    FormsAuthentication.SignOut();
}

这是我的完整方法

public class SessionExpireFilterAttribute : ActionFilterAttribute
    {

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            HttpContext ctx = HttpContext.Current;

            // check if session is supported
            if (ctx.Session != null)
            {

                // check if a new session id was generated
                if (ctx.Session.IsNewSession)
                {

                    // If it says it is a new session, but an existing cookie exists, then it must
                    // have timed out
                    string sessionCookie = ctx.Request.Headers["Cookie"];
                    if ((null != sessionCookie) && (sessionCookie.IndexOf("ASP.NET_SessionId") >= 0))
                    {
                        string redirectOnSuccess = filterContext.HttpContext.Request.Url.PathAndQuery;
                        string redirectUrl = string.Format("?ReturnUrl={0}", redirectOnSuccess);
                        string loginUrl = FormsAuthentication.LoginUrl + redirectUrl;
                        if (ctx.Request.IsAuthenticated)
                        {
                            FormsAuthentication.SignOut();
                        }
                        RedirectResult rr = new RedirectResult(loginUrl);
                        filterContext.Result = rr;
                        //ctx.Response.Redirect("~/Home/Logon");

                    }
                }
            }

            base.OnActionExecuting(filterContext);
        }
    }

2
嗨Tom,不要在意我的知識,我應該在哪裡聲明這個類(控制器???),我怎麼使用這些屬性??? - Sanjay Zalke
2
Sanjay,您可以在任何地方声明它。该类正在创建一个属性。您可以通过应用 [SessionExpireFilterAttribute] 将该属性与您的控制器类或操作方法相关联。 - 1c1cle

0

您需要在项目的 Global.asax.cs 文件中创建 Session_OnEnd 方法。

这是我的代码,我能够检测ASP.NET MVC上的会话过期

protected void Session_OnEnd(object sender, EventArgs e)
{
    int userid = 0;
    userid = Convert.ToInt32(Session["UserID"]);
    if (userid != 0)
    {
        var userActivity = DependencyResolver.Current.GetService<IUserRepo>();
        var responce = userActivity.LogOutUsers(userid);
        if (responce == true)
        {
            Session.Clear();
            Session.Abandon();
        }
    }
}

更多


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接