Viewstate优化终极解决方案.net 3.5/2.0
如果你有一个非常酷的页面,页面上很多东西自动地响应用户操作而展现丰富的变化,你的ViewState是很有可能达到200K的。
这里
是我将ViewState持久化保持在服务器端的代码,这样ViewState不占用网络带宽,因此其存取只是服务器的磁盘读取时间。并且它很小,可以说
是磁盘随便转一圈就能同时读取好多ViewState,因此可以说“不占时间”。为了再“不占磁盘时间”,我还使用了缓存。
一下这段代码可以放在页面中,或者页面的父类中:
- C# code
-
protected override object LoadPageStateFromPersistenceMedium() { var viewStateID = (string)((Pair)base.LoadPageStateFromPersistenceMedium()).Second; var stateStr = (string)Cache[viewStateID]; if (stateStr == null) { var fn = Path.Combine(this.Request.PhysicalApplicationPath, @"App_Data/ViewState/" + viewStateID); stateStr = File.ReadAllText(fn); } return new ObjectStateFormatter().Deserialize(stateStr); } protected override void SavePageStateToPersistenceMedium(object state) { var value = new ObjectStateFormatter().Serialize(state); var viewStateID = (DateTime.Now.Ticks + (long)this.GetHashCode()).ToString(); //产生离散的id号码 var fn = Path.Combine(this.Request.PhysicalApplicationPath, @"App_Data/ViewState/" + viewStateID); ThreadPool.QueueUserWorkItem(obj => File.WriteAllText(fn, value)); Cache.Insert(viewStateID, value); base.SavePageStateToPersistenceMedium(viewStateID); }
不使用Session,因为它会“丢失”。ViewState保存在磁盘上,即使服务器重新启动,也不会丢失页面状态。
下面这段可以放在Global.asax中,也可以根本不管:
- C# code
-
protected void Application_Start(object sender, EventArgs e) { var dir = new DirectoryInfo(this.Server.MapPath("~/App_Data/ViewState/")); if (!dir.Exists) dir.Create(); else { var nt = DateTime.Now.AddHours(-1); dir.GetFiles().ForEach(f => { if (f.CreationTime < nt) f.Delete(); }); } }
这可以确保绝对稳定可靠地工作。以后请放心使用ViewState,把交互式页面提高水平才是最重要的,不要纠缠在“ViewState太大”上。实际上,由于页面设计不够酷,交互变化看上去不够丰富,ViewState实在是太小太小了。
如果你使用了它有效提高了复杂交互页面的效率,可以说一下提高了多少?!如果你觉得没用,也可以说一下在什么情况下没用。
不用看懂。只有两个简单方法,贴到自己的页面中就行。对所有使用到ViewState的页面都需要。或者你可以放在父类中。
由于一直可以运行,其实那句应该写为:
var fn = this.Server.MapPath(@"~/App_Data/ViewState/" + viewStateID);
我都一直懒得改了
可能需要自己添加命名空间:
using System.IO;
using System.Threading;
ThreadPool.QueueUserWorkItem(obj => File.WriteAllText(fn, value));
这一句也不是很必要。写为:
File.WriteAllText(fn, value));
就可以了。当时也是为了玩玩,今天才又想起来还有这个没改。
其实我太细抠个别语句的“效率”,除非到了必要的时候。
楼主的代码我在asp.net2.0里测试了,修正的代码如下:
==================================================
- C# code
-
#region 解决ViewState过于庞大的问题 protected override object LoadPageStateFromPersistenceMedium() { string viewStateID = (string)((Pair)base.LoadPageStateFromPersistenceMedium()).Second; string stateStr = (string)Cache[viewStateID]; if (stateStr == null) { string fn = Path.Combine(this.Request.PhysicalApplicationPath, @"App_Data/ViewState/" + viewStateID); stateStr = File.ReadAllText(fn); } return new ObjectStateFormatter().Deserialize(stateStr); } protected override void SavePageStateToPersistenceMedium(object state) { string value = new ObjectStateFormatter().Serialize(state); string viewStateID = (DateTime.Now.Ticks + (long)this.GetHashCode()).ToString(); //产生离散的id号码 string fn = Path.Combine(this.Request.PhysicalApplicationPath, @"App_Data/ViewState/" + viewStateID); //ThreadPool.QueueUserWorkItem(File.WriteAllText(fn, value)); File.WriteAllText(fn, value); Cache.Insert(viewStateID, value); base.SavePageStateToPersistenceMedium(viewStateID); } #endregion
======================
- C# code
-
DirectoryInfo dir = new DirectoryInfo(this.Server.MapPath("~/App_Data/ViewState/")); if (!dir.Exists) dir.Create(); else { DateTime nt = DateTime.Now.AddHours(-1); foreach(FileInfo f in dir.GetFiles()) { if (f.CreationTime < nt) f.Delete(); } }
- 另外,不使用缓存,那么代码就简单一些了,代码变为:
protected override object LoadPageStateFromPersistenceMedium()
{
var viewStateID = (string)((Pair)base.LoadPageStateFromPersistenceMedium()).Second;
var fn = Path.Combine(this.Request.PhysicalApplicationPath, @"App_Data/ViewState/" + viewStateID);
var stateStr = File.ReadAllText(fn);
return new ObjectStateFormatter().Deserialize(stateStr);
}
protected override void SavePageStateToPersistenceMedium(object state)
{
var value = new ObjectStateFormatter().Serialize(state);
var viewStateID = (DateTime.Now.Ticks + (long)this.GetHashCode()).ToString(); //产生离散的id号码
var fn = Path.Combine(this.Request.PhysicalApplicationPath, @"App_Data/ViewState/" + viewStateID);
ThreadPool.QueueUserWorkItem(obj => File.WriteAllText(fn, value));
base.SavePageStateToPersistenceMedium(viewStateID);
}
我认为大家应该知道了缓存的作用,所以我并没有特意去说不过不用缓存,代码如何写。
即使不用缓存(那么我们也就暂时满足了对缓存忧心忡忡的人,虽然这是不必要的),我们使用服务器端磁盘读的时间来节省服务器通过http从浏览器端读ViewState时间,其结论跟我这个题目要说明的也是一样的。
这个我没有碰到过。如果是强制转换问题,似乎也应该是“object不能强制转换为string”,因为要转换的是Pair.Sencond,而不是Pair类型的对象。请插入一个断言测试一下是否
((Pair)base.LoadPageStateFromPersistenceMedium()).Second==null
看看这什么是否发生。
3.5。如果是低版本,请自己转换一下。“var”可以自己写成“string”之类的具体类型。另外我自己在静态类中有一个方法:
static public void ForEach<T>(this IEnumerable<T> array, Action<T> action)
{
foreach (T x in array)
{
action(x); ;
}
}
因为有太多地方需要 ForEach,我比较喜欢函数编程风格。也可以自己改成foreach(....)写法,就像上面已经有的回帖那样写。
上面看不懂一定要看下面
这段时间,发现viewstate所产生的一堆乱码,严重影响了我们网站的打开速度和搜索引擎的抓取.
| 例如: input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="dEV4cHJlc3Npb247UmVhZE9ubHk7PjtsPHB1Yl9uYW1lO3B1Yl9uYW1lO3B1Yl9uYW1 lO288Zj47Pj47Ozs7PjtAMDxw" /> |
我翻遍了所有的资料,及查遍了百度和Google。以求得到最佳解决方案。但都没有一个完整的解决方案。都写的比较零碎。但黄天不负有心人,最终还 是让我找到了几种方案,并加以修改,改进。在此我要感谢这几个方案的提供者。谢谢他们的分享,在解决完我自己的问题后,有感于前几位的分享,故我也不敢独 自分享,现在总结七种解决方案如下,以供大家分享,有不对的地方欢迎拍砖。现把ViewState的优化方法总结如下:
第一种解决方案(最快的一种,但是以牺牲asp.net方便性为代价的)

浙公网安备 33010602011771号