ASP.NET MVC - 使用Session的替代方案

3
我有一个ASP.NET MVC视图,使用jquery.Uploadify将文件上传到我的控制器之一,以供我的应用程序使用。我注意到Uploadify的一个副作用是,当Flash文件上传到我的控制器时,它会从ASP.NET获取自己的SessionID。当然,如果我的Upload控制器不使用Session来存储当前用户上传的文件列表,以供我的应用程序将来操作,那就没问题了...因此,在使用视图上传文件后,当前用户的会话不包含刚刚上传的任何文件。
有没有建议如何在不依赖Sessions(最好也不依赖数据库)的情况下实现我的目标?
4个回答

2

由于Uploadify纯粹是一个前端脚本,我不明白为什么它会从ASP.NET获取会话。我也不完全理解你的具体问题。

如果您的问题是上传文件后,用户无法在屏幕上看到它们,那么我建议找出一种独立于Uploadify的方法来显示文件列表。如果可以的话,请让它发送一个带有文件的ID令牌,然后从数据库中获取显示列表所需的数据。


1
基本上这就是问题所在,对吧。我考虑过将上传内容缓存到数据库中,但那似乎就像用卡车来敲钉子一样不切实际... - Nathan Taylor

0
这是我想出的解决方案。虽然我没有进行太多测试,但在当前情况下,它似乎是Session的一个可接受的替代方案。我将使用Global.asax的Session_End/Session_Start来确保根据需要创建和删除行。
public class UserTable : Dictionary<string, Dictionary<string, object>>
{
    public new object this[string key]
    {
        get
        {
            object value = null;
            if (HttpContext.Current != null)
            {
                var sessionId = HttpContext.Current.Session.SessionID;
                if (ContainsKey(sessionId) && base[sessionId].ContainsKey(key))
                    value = base[sessionId][key];
            }
            else
                throw new Exception("No HttpContext present.");
            return value;
        }
        set
        {
            if (HttpContext.Current != null)
            {
                var sessionId = HttpContext.Current.Session.SessionID;
                if (!ContainsKey(sessionId))
                    Add(sessionId, new Dictionary<string, object>());
                if (!base[sessionId].ContainsKey(key))
                    base[sessionId].Add(key, value);
                else
                    base[sessionId][key] = value;
            }
            else
                throw new Exception("No HttpContext present.");
        }
    }

    public object this[string sessionId, string key]
    {
        get
        {
            object value = null;
            if (ContainsKey(sessionId) && base[sessionId].ContainsKey(key))
                value = base[sessionId][key];
            return value;
        }
        set
        {
            if (!ContainsKey(sessionId))
                Add(sessionId, new Dictionary<string, object>());
            if (!base[sessionId].ContainsKey(key))
                base[sessionId].Add(key, value);
            else
                base[sessionId][key] = value;
        }
    }

    public void Add(string sessionId)
    {
        Add(sessionId, new Dictionary<string, object>());
    }

    public void Add()
    {
        if (HttpContext.Current != null)
            Add(HttpContext.Current.Session.SessionID);
        else
            throw new Exception("No HttpContext present.");
    }

    public new void Remove(string sessionId)
    {
        base.Remove(sessionId);
    }

    public void Remove()
    {
        if (HttpContext.Current != null)
            Remove(HttpContext.Current.Session.SessionID);
        else
            throw new Exception("No HttpContext present.");
    }
}

0
也许可以使用静态哈希表,其键为客户端的用户:IP? 值可以是您想要跨不同会话存储的任何对象。

其实这还不错。非常感谢您。 - Nathan Taylor
当然,在咖啡店这样的场景中,这种方法可能不太适用。但是,如果我在上传操作中传递会话ID,并使用会话ID的HashMap,我可以显式地使用提供的会话ID。是否可以为给定的会话ID获取会话对象? - Nathan Taylor
不同的会话ID表示已经建立了一个新的会话,旧的会话不再可用(除非您保存了之前的会话)。会话是一个对象,您可以将其存储在哈希表中,但我认为这种解决方法会引起更多问题。但是你提到的咖啡店的情况是什么?用户改变了IP地址吗? - Freddy
在咖啡店的情景中,可能会有多个使用相同IP地址的用户,这样我的UserTable就会连接多个用户。如果我使用Session ID,我可以保证值是唯一的。我已经将我的"UserTable"实现添加到上面的帖子中。它似乎做到了我想要的,尽管我还没有进行严格的测试。显然,我并不打算用UserTable替换Session,因为我只在这种情况下真正需要UserTable。尽管如此,我仍然将UserTable存储在BaseController中,以供所有人访问。 - Nathan Taylor
好的,明白了。这就是为什么我建议使用“user:ip”作为哈希表的键。我认为在99.99%的情况下,这种组合应该是唯一的。 - Freddy
顺便提一下,用户指的是连接到您会话的用户,因此您的密钥将是类似于“freddy:207.95.30.3”的字符串。 - Freddy

0

有一件事要交叉检查——在上传之前,您是否通过添加一些数据使会话“活跃”?ASP.NET会在会话中添加数据之前重新生成会话。


是的,会话确实在进行中。问题涉及到SWFUpload,不仅仅是我。 :) - Nathan Taylor
明白了。我会使用一个HTTP调试器(比如Fiddler2)来查看网络上发生了什么。这里有些地方似乎不太对劲。至少根据我的直觉是这样的。 - Wyatt Barnett

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