ASP.NET - 在不序列化的情况下保存在视图状态中
ASP.NET - Saving in Viewstate Without serializing
我试图在 Viewstate 中存储一个复杂的对象,以避免每次在页面加载时调用它。我知道它需要序列化才能保存并从 Viewstate 中检索,这意味着我的 class 应该标记为 [Serializable]
这是一个相当复杂的实体,基本上我希望避免将每个 class 标记为可序列化,因为它可能会影响我用于映射的其他依赖项。
Class Article
{
Albums albumList { get; set; }
Authors authorList { get; set; }
...
}
是否有可能在不序列化的情况下保存和检索视图状态对象?
您可以改用 ASP.NET Session
对象(这避免了序列化路径,因为 Session
中的所有内容都存储为 Object
),如下所示:
var theArticle = new Article();
Session["MyArticle"] = theArticle;
Session
中的所有内容都存储为对象,因此当您检索 Article
对象时,您需要将其转换为 Article
,如下所示:
var myArticleFromSession = Session["MyArticle"] as Article;
注意:建议在尝试访问该值之前检查 Session
键是否确实存在,如下所示:
if(Session["MyArticle"] != null)
{
// The key MyArticle exists, so it is safe to attempt to get the object value
var myArticleFromSession = Session["MyArticle"] as Article;
// Since we used as to attempt the cast,
// then myArticleFromSession will be null if the cast failed
// so check for null before using myArticleFromSession
if(myArticleFromSession != null)
{
// Use myArticleFromSession here
}
}
如果可能,应避免序列化,因为它相对较慢(扩展性不好)。
如果您希望在回发之间或跨页面缓存特定对象,请使用 ASP.NET Session
对象进行特定于会话的缓存,Application
对象用于站点范围缓存,或将 System.Web.Caching.Cache
用于您自己的自定义缓存行为。您还可以缓存 ASP.NET 个页面或部分页面的输出。更多信息在这里:ASP.NET Caching
但是如果您希望缓存整个页面的视图状态,可以选择服务器端视图状态持久化。在这种情况下,您需要创建一个新的 BasePage
。例如,当浏览器限制非常大的视图状态的大小时,这非常有用。您可以在此处获得有关此方法的更多信息:Server Side Viewstate
在我看来,从您的用例来看,"to avoid calling it everytime on page load" 急需缓存。我想如果你想让它过期,可以设置一些依赖关系,它 might work better than session(我们不知道所有的细节)。
现在,您可能可以使用 json.net,它可以帮助您在不更改对象的情况下序列化您的信息。只是不要滥用视图状态,如果让它增长,它会很快变得令人讨厌。使用会话或缓存(如果它满足您的需要)是可以在长期 运行 中更好地扩展的东西。
如果这是显示内容,还请查看 Output cache,因为也许您可以在用户控件或其他内容中分隔重复的内容。
综上所述,我想添加一个你实际使用 JSON.net 询问的小例子(从他们那里偷来的例子):
//Doesnt need to be marked as serializable
Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Sizes = new string[] { "Small" };
//Use this string to save into view state
string json = JsonConvert.SerializeObject(product);
ViewState["something"]=json;
之后,从 ViewState[something] 取回字符串并反序列化。
string json = (string)ViewState["something"];
Product m = JsonConvert.DeserializeObject<Product>(json);
警告,未经编译而编写的代码。
另一种可能的解决方案是您可以将所有非必需属性映射为 [NonSerialized]
,以便只使用一次必需属性。我遇到了类似的问题并选择了这个选项。
所以假设在上面的例子中你想要专辑而不是艺术家那么你的class将变成如下
[Serializable]
Class Article
{
Albums albumList { get; set; }
[NonSerialized]
Authors authorList { get; set; }
...
}
我试图在 Viewstate 中存储一个复杂的对象,以避免每次在页面加载时调用它。我知道它需要序列化才能保存并从 Viewstate 中检索,这意味着我的 class 应该标记为 [Serializable]
这是一个相当复杂的实体,基本上我希望避免将每个 class 标记为可序列化,因为它可能会影响我用于映射的其他依赖项。
Class Article
{
Albums albumList { get; set; }
Authors authorList { get; set; }
...
}
是否有可能在不序列化的情况下保存和检索视图状态对象?
您可以改用 ASP.NET Session
对象(这避免了序列化路径,因为 Session
中的所有内容都存储为 Object
),如下所示:
var theArticle = new Article();
Session["MyArticle"] = theArticle;
Session
中的所有内容都存储为对象,因此当您检索 Article
对象时,您需要将其转换为 Article
,如下所示:
var myArticleFromSession = Session["MyArticle"] as Article;
注意:建议在尝试访问该值之前检查 Session
键是否确实存在,如下所示:
if(Session["MyArticle"] != null)
{
// The key MyArticle exists, so it is safe to attempt to get the object value
var myArticleFromSession = Session["MyArticle"] as Article;
// Since we used as to attempt the cast,
// then myArticleFromSession will be null if the cast failed
// so check for null before using myArticleFromSession
if(myArticleFromSession != null)
{
// Use myArticleFromSession here
}
}
如果可能,应避免序列化,因为它相对较慢(扩展性不好)。
如果您希望在回发之间或跨页面缓存特定对象,请使用 ASP.NET Session
对象进行特定于会话的缓存,Application
对象用于站点范围缓存,或将 System.Web.Caching.Cache
用于您自己的自定义缓存行为。您还可以缓存 ASP.NET 个页面或部分页面的输出。更多信息在这里:ASP.NET Caching
但是如果您希望缓存整个页面的视图状态,可以选择服务器端视图状态持久化。在这种情况下,您需要创建一个新的 BasePage
。例如,当浏览器限制非常大的视图状态的大小时,这非常有用。您可以在此处获得有关此方法的更多信息:Server Side Viewstate
在我看来,从您的用例来看,"to avoid calling it everytime on page load" 急需缓存。我想如果你想让它过期,可以设置一些依赖关系,它 might work better than session(我们不知道所有的细节)。
现在,您可能可以使用 json.net,它可以帮助您在不更改对象的情况下序列化您的信息。只是不要滥用视图状态,如果让它增长,它会很快变得令人讨厌。使用会话或缓存(如果它满足您的需要)是可以在长期 运行 中更好地扩展的东西。
如果这是显示内容,还请查看 Output cache,因为也许您可以在用户控件或其他内容中分隔重复的内容。
综上所述,我想添加一个你实际使用 JSON.net 询问的小例子(从他们那里偷来的例子):
//Doesnt need to be marked as serializable
Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Sizes = new string[] { "Small" };
//Use this string to save into view state
string json = JsonConvert.SerializeObject(product);
ViewState["something"]=json;
之后,从 ViewState[something] 取回字符串并反序列化。
string json = (string)ViewState["something"];
Product m = JsonConvert.DeserializeObject<Product>(json);
警告,未经编译而编写的代码。
另一种可能的解决方案是您可以将所有非必需属性映射为 [NonSerialized]
,以便只使用一次必需属性。我遇到了类似的问题并选择了这个选项。
所以假设在上面的例子中你想要专辑而不是艺术家那么你的class将变成如下
[Serializable]
Class Article
{
Albums albumList { get; set; }
[NonSerialized]
Authors authorList { get; set; }
...
}