创建过期的ASP.NET会话值。

5

我想创建一个会话值,它在5分钟后过期。

如何做到这一点?我需要在读取时手动比较创建时间吗?

Session("sessionval") = myvariable
Session("sessioncreated") = now

你想让所有的会话变量在5分钟后过期,还是只有这一个变量,在其余时间较长或较短的情况下超时? - belgariontheking
我们只有锤子,所以你确定你的螺丝不是钉子吗?不过无论如何,让我们还是用锤子敲一下吧。 - AnthonyWJones
7个回答

6
如果您想在单个变量上执行此操作,我认为这是不可能的,但您可以使用web.config定义会话超时时间。
<system.web>  
    <sessionState timeout="5" />
<system.web>

这将影响所有的会话对象,而不仅仅是单个对象。

我建议为单个项目设置自定义过期日期的方法是创建一个 cookie,这样您可以真正地设置其到期值。

Response.Cookies.Add(New Web.HttpCookie("AdminID", admin.AdminID))
Response.Cookies("AdminID").Expires = Now.AddMinutes(5)

@Anthony:这就是为什么我在答案中特别指出,如果您要求如何在单个项目中完成它,我认为是不可能的。 - TheTXI
@TheTXI 这是一种选择,警告在盒子上。我个人不会选择这个选项(web.config),但它是完全有效的答案 +1 - cgreeno
BTHB:我个人也不会选择它,但考虑到对于OP想要做什么缺乏细节描述,这仍然是一个可能性,尽管很遥远。 - TheTXI
@TheTXI:您的额外建议现在存在一个缺陷,即将放置在客户端上的值的负担和包含它在所有请求中所需的带宽,无论是否需要,以及将其类型降低为字符串。更不用说客户端可能会阻止或更糟地伪造它们。 - AnthonyWJones
@Anthony,尽管上述明显的缺陷,Cookie 仍然被广泛使用。选择最适合他/她上下文的最佳解决方案取决于 OP。我必须承认,Cookie 解决方案甚至没有出现在我的脑海中。肯定是加一。 - Cerebrus

4

您不能为会话变量定义自定义超时时间。

也许您可以使用缓存来实现,使用一个依赖于会话的唯一键。

您可以为缓存项目设置超时时间。

Cache.Insert("key_dependent_to_session", value, Nothing, 
  DateTime.Now.AddMinutes(5), TimeSpan.Zero)

再进一步创造几个静态(在VB中被称为Shared)访问器方法,位于一个静态(Shared)类中。让这些方法发现当前会话ID并对键名进行一些后缀处理。 - AnthonyWJones

3

如果您想使用SessionState,可以创建自己的包装器,以便于缓存包装器而不是实际项。这里是一个快速简单的未经测试的包装器示例,它检查项目是否为空,或者是否已过期,如果是,则调用一个可以提供刷新项的Func。

Func获取上次设置的值,因此如果您可以确定该值仍然有效,则可以避免重新加载它。

public class TimeExpirationItem<T>
{
    private T _item=default(T);
    private TimeSpan _expirationDuration;
    private Func<T> _getItemFunc;
    private DateTime _expiresTime;
    public TimeExpirationItem(TimeSpan expirationDuration, Func<T, T> getItemFunc)
    {
        this._getItemFunc = getItemFunc;
        this._expirationDuration = expirationDuration;
    }
    public T Item
    {
        get
        {
            if (_item == null || ItemIsExpired())
            {
                _item = _getItemFunc(_item);
                _expiresTime = DateTime.Now.Add(_expirationDuration);
            }
            return _item;
        }
    }
    public bool ItemIsExpired()
    {
        return DateTime.Now > _expiresTime;
    }
}

再次提醒,此代码不带任何保证和测试,但是它是你可以做的事情的示例。

使用方法如下:

Session.Add("ObjectKey", new TimeExpirationItem<MyObject>(new TimeSpan(0, 0, 5), mo=>MyObjectRepository.GetItemByLogin(Request.User.Identity.Name));


2

抱歉挖掘一个旧问题,但我面临完全相同的问题,不得不为HttpSession对象创建一个扩展类。

这是我的博客文章

附:代码:

public static class SessionExtender
{
    public static void AddWithTimeout(this HttpSessionState session,
        string name,
        object value,
        TimeSpan expireAfter)
    {
        session[name] = value;
        session[name + "ExpDate"] = DateTime.Now.Add(expireAfter);
    }

    public static object GetWithTimeout(
        this HttpSessionState session,
        string name)
    {
        object value = session[name];
        if (value == null) return null;

        DateTime? expDate = session[name + "ExpDate"] as DateTime?;
        if (expDate == null) return null;

        if (expDate < DateTime.Now)
        {
            session.Remove(name);
            session.Remove(name + "ExpDate");
            return null;
        }

        return value;
    }
}

你的博客有一个更新版本,更易于使用。谢谢分享! - kodybrown

2

没错。会话状态没有过期的概念。

如果您的数据不是基于用户的,可以使用缓存代替。甚至可以使用缓存,但将用户名作为键的一部分,这样就可以获得类似于过期会话状态的效果。


即使它是特定于会话的,您仍可以将会话ID用作键的一部分。 - AnthonyWJones
@John:“会话状态没有过期概念。”鉴于sessionState对象的timeout属性,您如何解释这个声明? - Cerebrus
".Timeout是针对整个会话状态的,而不是每个项目的过期时间。" - John Saunders

1

我倾向于同意TheTXI的观点。

虽然单个Session项不能分配自定义超时时间,但需要注意的是,在InProc会话模式中,Sessionstate本身就被添加为ASP.NET缓存的一个项目。这使得它可以具有"超时"。

在您特定的情况下,Cache对象是最适合的解决方案。


保持一致。问题不在于整个会话状态的过期。 - AnthonyWJones
@Anthony:对于一个从未发布自己的答案的人来说,你对于原作者想要什么非常慷慨地进行了贬低和假设。 - TheTXI

-1

1) 将此内容放入 web.config 文件中

<configuration>
   <system.web>
     <sessionState mode="InProc" timeout="5">
     </sessionState>
   </system.web> 
</configuration>

2) 将System.Web.SessionState.HttpSessionState.Timeout设置为5分钟。


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