一切为客户着想

一切的一切还得从和一位台湾客户的沟通说起:

客户提到将ViewState保存在服务器端以减少上行数据量,从而加快页面的回发速度。

但是在FineUI中,控件状态都保存在FState中,并且为了减少下行数据量,FState的数据不仅用来保存状态,而且用于JavaScript的数据源。

所以FState必须写入HTTP响应,才能被JavaScript使用。我在之前的一篇文章中曾详细阐述:http://www.cnblogs.com/sanshi/archive/2013/01/08/2850459.html

但这的确是个问题,FState虽然能够减少下行数据量,但是页面回发时上行数据量依然很大,特别是页面中有多个下拉列表和表格时,上行的数据量可达到500K或者更多,对网速受限的环境的确是个挑战。

FineUI(专业版)v3.5.0将提供一种简单的方法,将FState保存在服务器端,从而大幅减少页面回发时的上行数据量。

注:FState仍然需要返回到页面上(以便JavaScript使用,比如作为表格和下拉列表的数据源),只不过不需要回发到服务器而已。

减少 90% 的上行数据

作为对比,我们以下面的表格页面为例:http://fineui.com/demo_pro/iframe/grid_iframe.aspx

首先选中一项,然后点击工具栏上的[删除选中行]按钮,此时会触发按钮点击事件,我们分别看下v3.3.0和v3.5.0中上传数据量。

FineUI(专业版)v3.3.0:

FineUI(专业版)v3.5.0:

FineUI(专业版)v3.3.0上行数据量:32616bytes =  31.9K

FineUI(专业版)v3.5.0上行数据量:2137bytes =  2.1K

从上面数据来看,FineUI(专业版)v3.5.0上行数据量减少了 90% 左右。在一个包含多个表格和下拉列表的页面,这个效果会更加明显。

自定义编码实现

虽然FineUI(专业版)v3.5.0提供了将FState保存到服务器端的方法,但不是默认就支持的,需要自己写点代码。因为保存到服务器有多种方法,可以保存到服务器文件中,HttpRuntime.Cache,SqlServer或者NoSQL数据库(比如Memcached,Redis)。

官网示例的PageBase.cs中提供了两种保存方式:文件、HttpRuntime.Cache,你可以直接拷贝代码到自己的项目中去。

现在来看下保存到服务器缓存中(HttpRuntime.Cache)的方法:

1. 启用PageManager的EnableFStatePersistence,并定义代理函数LoadFStateFromPersistenceMedium和SaveFStateToPersistenceMedium。

protected override void OnInit(EventArgs e)
{
var pm = PageManager.Instance;
if (pm != null)
{
// FState保存到服务器缓存
pm.EnableFStatePersistence = true;
pm.LoadFStateFromPersistenceMedium = LoadFStateFromPersistenceMedium_Cache;
pm.SaveFStateToPersistenceMedium = SaveFStateToPersistenceMedium_Cache; }
}

页面级别的支持,方便我们控制哪些页面启用,哪些页面可以不启用。

2. 获取和保存FState的代理函数

private static readonly string FSTATE_CACHE_KEY = "__FSTATE_KEY";

private JObject LoadFStateFromPersistenceMedium_Cache()
{
string cacheKey = Page.Request.Form[FSTATE_CACHE_KEY]; var fstate = HttpRuntime.Cache[cacheKey] as JObject; if (fstate != null)
{
// 缓存使用过一次后,5s后过期(用不到了)
HttpRuntime.Cache.Insert(cacheKey, fstate, null,
DateTime.Now.AddSeconds(),
System.Web.Caching.Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.Default, null);
} return fstate;
} private void SaveFStateToPersistenceMedium_Cache(JObject fstate)
{
   // 1. 生成缓存Key = 用户会话ID+当前时间
string cacheKey = String.Format("{0}_{1}",
HttpContext.Current.Session.SessionID,
DateTime.Now.Ticks.ToString());

   // 2. 将页面的FState保存到缓存中,指定过期时间为当前用户会话过期时间(Session.Timeout)
// 指定时间后过期(Session.Timeout)
HttpRuntime.Cache.Insert(cacheKey, fstate, null,
DateTime.Now.AddMinutes(HttpContext.Current.Session.Timeout),
System.Web.Caching.Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.Default, null);

// 3. 将缓存Key保存到页面的一个隐藏字段中,通过PageContext.RegisterStartupScript来注册一段脚本
PageContext.RegisterStartupScript(String.Format("F.setHidden('{0}','{1}');", FSTATE_CACHE_KEY, cacheKey));
}

这里面的实现方式和在服务器端保存ViewState的方式类似。

官网示例中也有保存到服务器端文件的实现,可以参考:

private static readonly string FSTATE_FILE_KEY = "__FSTATE_KEY";
private static readonly string FSTATE_FILE_BASE_PATH = "~/App_Data/FState/"; private JObject LoadFStateFromPersistenceMedium()
{
string filePath = GetFStateFilePath();
string fileContent;
using (StreamReader sr = new StreamReader(filePath, System.Text.Encoding.UTF8))
{
fileContent = sr.ReadToEnd();
}
return JObject.Parse(fileContent);
} private void SaveFStateToPersistenceMedium(JObject fstate)
{
string filePath = GenerateFStateFilePath();
using (StreamWriter streamW = new StreamWriter(filePath, false, System.Text.Encoding.UTF8))
{
streamW.Write(fstate.ToString(Formatting.None));
}
} private string GenerateFStateFilePath()
{
DateTime now = DateTime.Now;
string folderName = now.ToString("yyyyMMddHH");
string fileName = String.Format("{0}_{1}",
HttpContext.Current.Session.SessionID,
now.Ticks.ToString());
//Page.Request.Url.AbsolutePath.Replace(".", "_").Replace("/", "_")); string folderPath = Page.Server.MapPath(Path.Combine(FSTATE_FILE_BASE_PATH, folderName));
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
} PageContext.RegisterStartupScript(String.Format("F.setHidden('{0}','{1}');", FSTATE_FILE_KEY, fileName)); return folderPath + "/" + fileName + ".config";
} private string GetFStateFilePath()
{
string fileName = Request.Form[FSTATE_FILE_KEY];
string[] fileNames = fileName.Split('_');
string folderName = new DateTime(Convert.ToInt64(fileNames[])).ToString("yyyyMMddHH"); return Page.Server.MapPath(Path.Combine(FSTATE_FILE_BASE_PATH, folderName)) + "/" + fileName + ".config";
}

当然你也可以方便的扩展到外部数据库(SqlServer,MySql)以及NoSQL数据库(Memcached,Redis)。

使用建议

虽然EnableFStatePersistence可以极大的减少上行数据量,但并不适合于所有的场合。因为每个用户访问的每个页面都可能会产生大量的FState,所以在服务端保存意味着对服务器资源的极大消耗(内存、文件或者数据库)!

有一个简单的使用原则:

仅在上行带宽有限(也即是服务器成本低于网络传输成本)时使用,否则适得其反。

在 stackoverflow 上有一个帖子,描述了将 ViewState 保存到服务器端可能存在的问题。

启用 FineUI 的 EnableFStatePersistence 适用于同样的原则(引文中的VS指的是ViewState):

  1. If the application recycles, the VS for all anyone using the application is lost.

  2. It increases the memory consumption of the application. This isn't an issue if there are only a few apps hosted on a server; but there are cases when there could be many websites hosted on one box.

  3. Scalability; the more active the application, the more VS needs to be stored. And you can't assume 1-1 (1 user - 1 VS). A user can have multiple tabs open, can go back, leave tabs inactive, etc... which leads to:

  4. How long do you store VS? Keeping the data encoded on the page ensures that it'll still be there if the user leaves the site open for a while.

  5. What happens if you're hosted on a web farm. We can't guarantee that the user will hit the same machine on each request.

官网示例:http://fineui.com/demo_pro/

FineUIPro v3.5.0发布了,减少 90% 的上行数据量,15行代码全搞定!的更多相关文章

  1. FineUIPro v3.6.0 发布了(3 年助力 200 家企业的信息化建设)!

    FineUI(专业版)自从 2014-07-30 发布第一个版本以来,3 年来已经持续更新了 25 个版本,我们的坚持有目共睹,同时也受到了 200 家企业的青睐和信任,感谢一路有你. FineUI( ...

  2. FineUIPro v5.1.0 发布了!

    FineUIPro v5.1.0 已发布,这已经是自 2014 年以来的第 31 个版本,4 年来精雕细琢,只为你来! 上个大版本新增了响应式布局,而这个版本主要是BUG修正,此外还增加了树控件的级联 ...

  3. FineUI(专业版)v3.2.0 发布(ASP.NET UI控件库)!

    +2016-08-20 v3.2.0 +表格增强. +表格列RenderField增加属性ClientHtmlEncode,用于在客户端进行HTML编码. -增加示例:单元格编辑->杂项-> ...

  4. AEAI DP V3.7.0 发布,开源综合应用开发平台

    1  升级说明 AEAI DP 3.7版本是AEAI DP一个里程碑版本,基于JDK1.7开发,在本版本中新增支持Rest服务开发机制(默认支持WebService服务开发机制),且支持WS服务.RS ...

  5. 一个共通的viewModel搞定所有的分页查询一览及数据导出(easyui + knockoutjs + mvc4.0)

    前言 大家看标题就明白了我想写什么了,在做企业信息化系统中可能大家写的最多的一种页面就是查询页面了.其实每个查询页面,除了条件不太一样,数据不太一样,其它的其实都差不多.所以我就想提取一些共通的东西出 ...

  6. FineUI v4.0.3 (beta) 和 FineUI v3.3.3 发布了!

    关于FineUI基于 ExtJS 的开源 ASP.NET 控件库 FineUI的使命创建 No JavaScript,No CSS,No UpdatePanel,No ViewState,No Web ...

  7. 开源敏捷测试管理& 开源BUG跟踪管理软件itest(爱测试) V3.3.0隆重发布

    v3.3.0 下载地址 :itest下载 码云源码地址 https://gitee.com/itestwork/itest 开源中国  itest项目地址   https://www.oschina. ...

  8. 痞子衡嵌入式:MCUBootUtility v3.0发布,开始支持LPC, Kinetis啦

    -- 痞子衡维护的NXP-MCUBootUtility工具距离上一个版本(v2.4.0)发布过去2个半月了,这一次痞子衡为大家带来了全新版本v3.0.0,从这个版本开始,NXP-MCUBootUtil ...

  9. 痞子衡嵌入式:MCUBootFlasher v3.0发布,为真实的产线操作场景而生

    -- 痞子衡维护的NXP-MCUBootFlasher工具(以前叫RT-Flash)距离上一个版本(v2.0.0)发布过去一年半以上了,这一次痞子衡为大家带来了全新版本v3.0.0,从这个版本开始,N ...

随机推荐

  1. vue 构建项目 文件引入

    1.vue引用依赖文件.  举例:axios 先安装 axios.如果直接安装 vue-axios 会报错 npm install axios npm install --save axios vue ...

  2. 洗礼灵魂,修炼python(70)--爬虫篇—补充知识:json模块

    在前面的某一篇中,说完了pickle,但我相信好多朋友都不懂到底有什么用,那么到了爬虫篇,它就大有用处了,而和pickle很相似的就是JSON模块 JSON 1.简介 1)JSON(JavaScrip ...

  3. SQL Server最大内存设为0后的处置办法

    故障说明: 远程调整实例内存时疏忽,将实例最大内存调整为了0,因此最大内存变成了128MB的最小值. 解决方式: 1.正常关闭SQL Server服务,如果是集群,需要先关停止集群角色防止故障转移,然 ...

  4. XSS 漏洞原理及防御方法

    XSS跨站脚本攻击:两种情况.一种通过外部输入然后直接在浏览器端触发,即反射型XSS:还有一种则是先把利用代码保存在数据库或文件中,当web程序读取利用代码并输出在页面上时触发漏洞,即存储型XSS.D ...

  5. Android Studio教程03-Activtiy生命周期的理解

    目录 1. Activity 1.1. 安卓中的Activity定义和特性: 1.2. 注册Activity 1. Intent filters:设置默认开启的activity 1.3. Activi ...

  6. Fluentd初探 简介与安装

    Fluentd是一个开源的数据收集器,专为处理数据流设计,有点像 syslogd ,但是使用JSON作为数据格式.它采用了插件式的架构,具有高可扩展性高可用性,同时还实现了高可靠的信息转发. 据分(Y ...

  7. 如何学习sss和前端数据处理

    1.学习scss,就看这篇:http://www.ruanyifeng.com/blog/2012/06/sass.html 就够了,因为sass的出现本来就是为了简化工作提高效率,也不算什么深奥精妙 ...

  8. I/O 机制的介绍(Linux 中直接 I/O 机制的介绍)

    IO连接的建立方式 1.缓存IO.流式IO: 2.映射IO.块式IO: 3.直接IO. IO的方式: 同步.异步.定时刷新: MMAP与内核空间 mmap使用共享用户空间与内核空间实现: 直接 I/O ...

  9. Springboot监控之一:SpringBoot四大神器之Actuator

    介绍 Spring Boot有四大神器,分别是auto-configuration.starters.cli.actuator,本文主要讲actuator.actuator是spring boot提供 ...

  10. UVA11584-Partitioning by Palindromes(动态规划基础)

    Problem UVA11584-Partitioning by Palindromes Accept: 1326  Submit: 7151Time Limit: 3000 mSec Problem ...