统一管理 Session、Cookie、Query String 和 Cache 变量






4.06/5 (8投票s)
一个包装器,可以以统一、灵活且类型安全的方式处理 Session、Cookie、Query String 或 Cache,同时完全支持 JSON 序列化。
引言
Session、Cookie、Query String 还是 Cache?作为一名 Web 开发人员,我经常问自己这个问题,多年来,随着我的 Web 项目变得越来越复杂,我发现自己做出了错误的决定。我发现 .NET 3.5 中提供的数据持久化对象相当笨拙且难以维护,因为它们不包括强类型和泛型。此外,每种存储类型都有自己的语法、限制和怪癖,这给它们的互操作性带来了很大的负担。由于我在网上找不到任何可以帮助我从总体上解决这些问题的方案,所以我开始了这个项目,并决定在这里分享。
基本上,它为您提供了一个简单而统一的模型,一个强类型且支持复杂数据类型(通过 JSON 序列化)的泛型包装器,以及一种在复杂场景下更易于维护的方法。简单地说,我可能会说,它对于本地存储模型来说,就像 Entity Framework 对于纯 SQL 一样,只是没有那些花哨的界面。
现在可以像处理 Session 对象一样处理 Cookie 和 Query String,而数据大小是唯一的显著限制。可以一次处理多种存储类型,并且为了增加安全性,可以使用基于 machineKey 的加密使 Query String 和 Cookie 防篡改。为了解决数据大小问题,支持压缩功能。请注意,为了优化和与外部对象(如 ASP.NET 数据源)兼容,原始类型不会被序列化。
现在可以以断开连接的方式处理变量,从而在需要进行多次操作时消除了任何不必要的开销。引入了一种新的基于文本的存储系统,以应对传统 Cookie 模型相关的限制和安全问题。它的工作方式与传统 Cookie 非常相似,只是它存储在服务器上,因此客户端无法访问。它也没有大小限制,因此您需要负责任地使用它。
另一个很酷的功能是 UIPersistence
类。只需一行代码,您就可以通过将其存储在您选择的存储类型中来持久化控件内的任何属性值。其用法示例在演示中的示例 3 中进行了说明。请参考该示例以获取更多信息。
Using the Code
首先,让我们创建一个对象来将整数存储在 Session 中,键为“counter
”
var count = new Local.Integer("counter");
这是上述示例的泛型版本
var count = new Local.Var<int>("counter");
要操作整数,我们像下面这样使用 Value
属性
count.Value = count.Value + 10;
要指定源类型,我们使用下面给出的 Sources 枚举
public enum Sources
{
None = 0,
Session = 1,
Cookie = 2,
Query = 4,
Cache = 8,
SharedCache = 16,
ServerCookie = 32
}
SharedCache
使用 ASP.NET 中提供的默认 Cache 对象,并且在所有用户之间共享。然而,Cache
将始终包含用户的唯一 Session ID 作为其键,从而使其对每个用户都唯一。因此,要创建一个操作 Cookie 中整数的对象,我们可以使用下面的声明
var count = new Local.Integer("counter", Sources.Cookie);
由于其泛型性质,并且对于基于文本的存储类型在底层使用 Json 序列化,我们可以使用下面的示例来访问存储在 Query String 中的任何对象类型,例如 Person
var person1 = new Local.Var<person>("person_1", Sources.QueryString);
现在还有另一种访问变量键的方法,特别是那些具有共同前缀的变量。方法如下
var persons = new Local.Var<person>("person", Sources.QueryString);
var person1 = persons[1];
var person2 = persons[2];
这将自动将对 person1
和 person2
的请求映射到键 {""person_1"
和 "person_2"
"}。请注意,“_
”是用于分隔父键和子键的默认分隔符。它也是与 Cookie 一起使用的默认键分隔符,因为它们本身支持父/子键。此外,您可以顺序指定多种源类型,这样如果前一种类型返回 null 值,则会使用接下来的源。
var person1 = new Local.Var<person>("person_1", Sources.QueryString, Sources.Cookie);
Person person = person1.Value;
person1.Value = new Person();
在上面的示例中,只有在尝试从 Query String 检索 person1
失败后,它才会从 Cookie 中检索其值。最后一行代码中分配的新值将被保存到所有指定的源中。但是,如果我们不想写入 Query String,因为这会导致页面刷新,而是想写入 Cache 呢?方法如下
var person2 = new Local.Var<person>("person_1", Targets.Cookie + Targets.Cache,
Sources.QueryString, Sources.Cookie);
上面的示例使用 Targets 结构来指定目标类型。后者与 Sources 枚举
类似,只是其元素声明为字节。在检索值时,Person2
的行为将与 person1
完全相同。但是,分配的任何值都将被保存到 Cookie 和 Cache 中。
请注意,您可以对任何具有泛型类型的对象调用 ToString()
函数来获取其 Json 表示。更多用法示例可以在演示代码中找到。
Cookie 在超过 4Kb 的大小限制时会自动清除,而 Query String 的最大大小为 2048Kb。请注意,当 Query String 超过其大小限制时会抛出错误,但对于 Cookie 无法实现这一点,因为我还没有找到确定其大小的方法。因此,我能做的最好的事情来避免大小限制问题就是实现压缩功能。
如果该项目获得社区足够多的关注,我们将随着时间的推移添加更好的文档,与此同时,您的建议、问题和批评也最受欢迎。
未来计划
- 添加使用 Web 服务作为持久化机制的功能
- 增强当前的服务器 Cookie 实现
- 使用 MemCache 和/或 Velocity 支持 Web Farm(仅限 .NET 4.0)
历史
- 2009 年 11 月 3 日:首次发布
- 2009 年 12 月 1 日:文章已更新