Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >一个保存数据的方法(可以切换存放的位置,可以设置密钥)

一个保存数据的方法(可以切换存放的位置,可以设置密钥)

作者头像
用户1174620
发布于 2018-02-26 03:32:12
发布于 2018-02-26 03:32:12
1.1K00
代码可运行
举报
运行总次数:0
代码可运行

      在asp.net里面一般的生命周期都比较短,如果想要比较长久的保存数据的话,一般有选择几种方式可供选择,即cookies、ViewState、Session、Cache、application等。他们各有优缺点,也各有其自己的使用范围。

      我现在遇到了两个问题,第一个是如何在这几种方式里面快速、方便的切换,第二个是如何实现一个既可以区分用户,又可以区分页面,又节省服务器的资源,又比较安全的保存数据的方式。

      ViewState比较符合第二个问题的要求,但是他不太安全,表面上看他存放在客户端的是乱码,其实是可以解密的,解密之后就是明文了,你存放的是什么就一目了然。如果是使用ViewState保存一般的数据倒也是没有什么问题,但是我想保存的是表名、字段名、SQL语句这样的很敏感的数据,这样的数据放在ViewState里面,估计会被人骂死,呵呵。

      以前的QuickPager分页控件确实是这么处理的,现在越想越不安全,自己用用也就凑合了,如果推广的话,那就害人了。所以我不得不想办法来解决这个很严重的问题。于是我想写一个独立的能够保存数据的类。这个类可以使用各种方式来存放数据,如果要加密数据的话,也可以自己设置密钥,这样不知道密钥的话,就不能解密了(除非暴力破解),当然您也可以选择不加密(保存在Session、Cache就不用加密了),也可以选择不保存。

      这样这个类就很灵活了,使用范围也可以广泛一点。

      在实现这个函数的时候,遇到了两大难题,一个是如何操作隐藏域,另一个是如何“自动”保存和“自动”加载。ViewState可是不用单独调用SaveViewState()来保存数据的。

      在Class里面操作cookie、Session等还是比较容易的(System.Web.HttpContext.Current.Response.Cookies[ClientID]),可是如何控制隐藏域呢?想了好久也没有想到好的方法,只好用笨方法了——传递一个Page实例(System.Web.UI.Page)进来,然后使用Page.ClientScript.RegisterHiddenField(ClientID, myData) 来搞定。

      至于自动保存,也是采用了一个笨笨的方法,既然已经把Page传递进来了,那么就给他加一个事件吧,_page.PreRender += new EventHandler(MyPage_PreRender);在执行Render之前保存数据。我想用类似的思路来搞定自动加载数据的(_page.PreLoad += new EventHandler(MyPage_PreLoad);),但是遇到了一个小问题。我们一般都是习惯在Page_Load函数里面给属性赋值,但是我要加的事件却是在Page_Load之前执行,也就是说如果在Page_Load里面赋值的话,即使把事件加上了,那么也早已经失去了执行的机会。当然可以在OnInit里面给属性赋值,只是这么做不太符合习惯。

      我也研究了一下IStateManager 这个接口,也试了一下,可惜没有成功,也许是我功力不够的原因吧。

      Ps:这个难题解决之后,QuickPager分页控件就可以一份为二了,变成QuickPager_UI、QuickPager_SQL两个部分,再加上我的数据访问函数库和现实数据的控件,就是一套完整的分页解决方案了。

      QuickPager_SQL就是专门处理分页算法(也就是分页用的SQL语句)的,这些部分都可以独立使用,也可以替换成其他的控件、类库。

      下面是源码,源文件等整理之后和分页控件一起发送。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
namespace JYK.Common
{
    枚举enum SaveViewStateLocation#region 枚举enum SaveViewStateLocation
    /**//// <summary>
    /// 保存数据的位置
    /// </summary>
    public enum SaveViewStateLocation
    {
        /**//// <summary>
        /// 不保存
        /// </summary>
        NoSave = 1,
        /**//// <summary>
        /// 放在Cookie里面保存
        /// </summary>
        Cookie = 2,
        /**//// <summary>
        /// 放在隐藏域里面保存
        /// </summary>
        Hidden = 3,
        /**//// <summary>
        /// 放在Session里面保存
        /// </summary>
        Session = 4,
        /**//// <summary>
        /// 放在Cache里面保存
        /// </summary>
        Cache = 5,
        /**//// <summary>
        /// 放在Application里面保存
        /// </summary>
        Application = 6
    }
    #endregion
    public class MyViewState        //: IStateManager
    {
        成员#region 成员
        /**//// <summary>
        /// 保存数据的字典
        /// </summary>
        private Dictionary<string, string> vs = new Dictionary<string, string>();
        /**//// <summary>
        /// 用于给表单里面添加隐藏域和加事件
        /// </summary>
        private System.Web.UI.Page _page;
        /**//// <summary>
        /// 密钥
        /// </summary>
        private string _key = "";
        #endregion
        public MyViewState()
        {
            //默认设置为不保存
            SaveLocation = SaveViewStateLocation.NoSave;
        }
      
        属性#region 属性
        /**//// <summary>
        /// 存放数据的位置
        /// </summary>
        public SaveViewStateLocation SaveLocation;
        /**//// <summary>
        /// 密钥,不同的密钥会生成不同的密文。空字符串表示不需要加密
        /// </summary>
        public string Key
        {
            set
            {
                _key = value;
            }
            get
            {
                return _key;
            }
        }
        /**//// <summary>
        /// 保存数据的标识
        /// </summary>
        public string ClientID = "myVS";
       
        /**//// <summary>
        /// 传递Page实例,以实现自动保存数据,和添加隐藏域的功能
        /// </summary>
        public Page Page
        {
            set
            {
                _page = value;
                _page.PreLoad += new EventHandler(MyPage_PreLoad);          //本来想在Page_Load之前加载内容,但是出现了一点问题
                _page.PreRender += new EventHandler(MyPage_PreRender);      //自动保存内容
            }
            get { return _page; }
        }
        索引器,类似于ViewState的使用方式#region 索引器,类似于ViewState的使用方式
        /**//// <summary>
        /// 索引器,类似于ViewState的使用方式
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string this[string key]
        {
            set 
            {
                if (vs.ContainsKey(key))
                {
                    vs[key] = value; 
                }
                else 
                {
                    vs.Add(key, value);
                }
            }
            get 
            {
                if (vs.ContainsKey(key))
                {
                    return vs[key];
                }
                else
                {
                    return null;
                }
            }
        }
        #endregion
        #endregion
        用于自动加载和保存数据的事件#region 用于自动加载和保存数据的事件
        void MyPage_PreRender(object sender, EventArgs e)
        {
            SaveViewState();
            //throw new NotImplementedException();
        }
        void MyPage_PreLoad(object sender, EventArgs e)
        {
            LoadViewState();
            //throw new NotImplementedException();
        }
        #endregion

        函数#region 函数
        /**//// <summary>
        /// 把数据保存到指定的位置里面
        /// </summary>
        public void SaveViewState()
        {
            //拼接字符串
            System.Text.StringBuilder str = new StringBuilder(1000);
            foreach (KeyValuePair<string,string> entry in vs)
            {
                str.Append(entry.Key);
                str.Append("`");
                str.Append(entry.Value);
                str.Append("`");
            }
            if (str.Length == 0)        //没有赋值
                return ;
            str.Remove(str.Length - 1, 1);
            string myData =  str.ToString();
            if (Key.Length > 0)
            {
                //加密
                myData = Encryptor.Encrypt(myData, Key);
            }
            str.Length = 0;
            保存#region 保存
            switch (SaveLocation)
            {
                case SaveViewStateLocation.Cookie :
                    System.Web.HttpContext.Current.Response.Cookies[ClientID].Value = myData;
                    break;
                case SaveViewStateLocation.Hidden:
                    #region
                    if (Page != null)
                    {
                        Page.ClientScript.RegisterHiddenField(ClientID, myData);
                    }
                    #endregion
                    break;
                case SaveViewStateLocation.Session :
                    System.Web.HttpContext.Current.Session[ClientID] = myData;
                    break;
                case SaveViewStateLocation.Cache :
                    System.Web.HttpContext.Current.Cache[ClientID] = myData;
                    break;
                
                case SaveViewStateLocation.Application :
                    System.Web.HttpContext.Current.Application[ClientID] = myData;
                    break;
            }
            #endregion
          
        }
        
        public void LoadViewState()
        {
            //加载
            string str = "";
            string[] arr = null;
            switch (SaveLocation)
            {
                case SaveViewStateLocation.Cookie:
                    if (System.Web.HttpContext.Current.Request.Cookies[ClientID] == null)
                        return;
                    str = System.Web.HttpContext.Current.Request.Cookies[ClientID].Value;
                    break;
                case SaveViewStateLocation.Hidden :
                    if (Page == null) return;
                    if (System.Web.HttpContext.Current.Request[ClientID] == null) return;
                    str = System.Web.HttpContext.Current.Request[ClientID];
                    break;
                case SaveViewStateLocation.Session:
                    str = System.Web.HttpContext.Current.Session[ClientID].ToString();
                    break;
                case SaveViewStateLocation.Cache:
                    str = System.Web.HttpContext.Current.Cache[ClientID].ToString();
                    break;
                case SaveViewStateLocation.Application:
                    str = System.Web.HttpContext.Current.Application[ClientID].ToString();
                    break;
            }
            if (str.Length == 0)        //没有取到值
                return;
            if (Key.Length > 0)
            {
                //加密
                str = Encryptor.Decrypt(str, Key);
            }
            //拆分
            arr = str.Split('`');
                  
            //赋值
            for (int i = 0; i < arr.Length; i += 2)
            {
                vs.Add(arr[i], arr[i + 1]);
            }
        }
        #endregion
      
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2009-04-24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
CodeSmith系列(二)——使用CodeSmith生成ASP.NET后台代码
因为表单的后台代码都差不多,所以采用了CodeSmith生成。由于表单的控制是基于XML的,所以可以根据XML自定义生成。由于没时间,就不多写了,具体模板代码见最后。 在这里,先选择变量。如下: X
雪雁-心莱科技
2018/12/27
3.1K0
【开源】QuickPager ASP.NET2.0分页控件V2.0.0.1——分页控件的源码(一) 主体
namespace JYK.Controls {     /**//// <summary>     /// 分页控件     /// PageGetData.cs 负责提取数据     /// PageSQL.cs 负责生成SQl语句     /// PageUI.cs 负责分页控件的页面内容     /// </summary>     [DefaultProperty("Text")]     [ToolboxData("<{0}:JYKPage runat=server></{0}:JYKPage>
用户1174620
2018/02/26
9400
分页解决方案 —— GridView + QuickPager + QuickPager_SQL + DataAccessLibrary + 数据库
    这里要说的不仅仅是一个分页控件,而是一套解决方案,包括如何显示数据、显示分页导航,如何得到分页用的sql语句(等效于存储过程),如何提取数据,如何绑定控件,如何响应事件,添加、修改、删除数据后如何更新,如何查询数据等等。一整套完整的解决方案。 这个方案要有几个特点:       1、支持多种数据库,可以提供多个分页算法以便于支持多种数据库。       2、可以在不同的要求下选用最优的分页算法。比如如果只需要按照主键排序,那么选择Max分页算法无疑是最快的一种分页算法。       3、按需所取。
用户1174620
2018/02/08
8990
分页解决方案 —— GridView + QuickPager + QuickPager_SQL + DataAccessLibrary + 数据库
jQuery EasyUI+ashx实现数据库的CIUD操作
对上一个小项目做一个回顾总结,涉及到了jQuery EasyUI+ashx实现数据库的CIUD操作,和大家分享一下。基本思路是用easyui做前端,ashx做后端,中间使用json格式交换数据,其中json主要使用Newtonsoft.Json来序列化和反序列化,为简单起见,后端没有分层,数据都是靠拼接sql,使用一个简单封装的DBHelper来时间数据库的操作。
全栈程序员站长
2022/11/15
1.1K0
jQuery EasyUI+ashx实现数据库的CIUD操作
【开源】QuickPager ASP.NET2.0分页控件V2.0.0.1——分页控件的源码 (二)
namespace JYK.Controls.PageManage {     /**//// <summary>     /// 生成分页控件需要的SQL语句     /// </summary>     public class PageSQL     {         /**//// <summary>         /// 分页控件的实例         /// </summary>         public JYKPage myPage = null;               生成分页
用户1174620
2018/02/26
1.3K0
一个页面搞定几乎所有的列表需求的实现思路和一点代码。
     其实如果要单独实现一个能够显示数据的表格,那么是很简单的,写一个for循环,把DataTable里面数据循环出来就OK了。相信大家都会做吧,如果是从asp走过来的应该更不陌生吧。      上一篇说了,我们要根据表里面的记录来确定显示哪些列,哪一列在前,哪一列在后。那么怎么做呢?我们先定义一个类来存放这些信息。  public class GridColumnsInfo     {         public int ColumnID = 0;       public string Co
用户1174620
2018/02/26
1.2K0
其实添加数据也可以这样简单——表单的第一步抽象(针对数据访问层)《怪怪设计论: 抽象无处不在 》有感
更正: 不好意思,昨天晚上思路有点混乱。有几个前提忘记说明了,现在补充一下。 1、缩小范围。按照由简到难的思路,这里先讨论最简单的添加数据的情况。就是单表的添加和修改;这里讨论的是webform的情况。 2、第一步抽象是针对数据访问层的抽象。 如果我没有理解错的话,现在大多数人的做法是:有一个表(或者几个有关联的表)在数据层里就要有一个“函数”与之对应, 如果采用的是SQL语句的方式的话,那么函数的内筒就是组合SQL语句的代码, 如果采用的是存储过程的方式的话,那么函数的内筒就是给存储过程的参数赋
用户1174620
2018/02/07
6890
【自然框架】QuickPager分页控件,新增一种分页方式——伪URL分页(Postback版)
适用场景   先说一下伪URL分页的适用场景。在网站的网页里实现查询功能,如果查询条件比较少的话,还比较好办,把查询条件放到URL里面传递即可。但是如果查询条件过多,就会照成URL的长度过长。既不好看,编写起来也很麻烦。如果查询条件是汉字的话,还有一个编码的问题。 Postback分页   再看看现有的几种分页方式。Postback分页方式可以利用ViewState来很方便的保存查询条件,但是由于采用表单提交的方式实现,搜索引擎不能识别。这个对于网站来说,是一个很难接受的。 URL分页   这个是通
用户1174620
2018/02/26
9240
【自然框架】 页面里的父类—— 改进和想法、解释
1、 从Control到GridView继承了多少层? (这个图可不是现做的,这是以前为了写QuickPager分页控件而弄的。http://www.cnblogs.com/jyk/archive/
用户1174620
2018/02/26
1.2K0
【自然框架】 页面里的父类—— 改进和想法、解释
FineUI开源版之TreeGrid(修改)
上篇文章中做了简单实现,但是还是有bug的,还需要在外面写事件的处理,今天又进行修改了。
冰封一夏
2019/09/11
9230
我的数据访问类(第二版)—— for .net2.0 (一)
asp.net2.0已经出来好久了,由于许多的原因一直没有使用,一个月前才开始使用VS2005写东西。 这一个月里又重新学习了一下基础知识,比如多态、接口了什么的。 既然已经到了2.0了嘛,那么以前的数据访问的方式要不要变一下呢?简单看了一下,感觉还是我的那种方式好,至少时我已经用习惯了。那么用.net2.0的方法重写一遍吧。 看了一下Framework 2.0的代码,发现一个问题。虽然表面上ADO.NET的使用没有什么变化(加了一些功能,原来由的功能没有变),但是内部实现有比较大的变化,原来的接口的“工作
用户1174620
2018/02/07
7770
其实添加数据也可以这样简单——表单的第三步抽象(针对UI及后置代码)
终于赶出来了,现写了一遍代码。 感谢大家的支持,感谢大家提出自己的看法。衷心的感谢,真的。 应该是先写第二步的,但是想一想还是先写第三步吧。 一般大项目里面都会有很多的基础信息的表,比如学历、职称等等,最近做了一个项目,居然有四十多个。如果一个一个地写是不是太麻烦了呢? 下面就要介绍一种方法 —— 基本一个页面搞定。 还是先说一下前提吧 VS2003 、 SQL2000 、 webform ,办公系统里的基础信息表的维护。 1、SQL2000里的几个系统表 写过代码生成器的Tx对这几个表都很
用户1174620
2018/02/07
1K0
其实添加数据也可以这样简单——表单的第三步抽象(针对UI及后置代码)
使用接口来统一控件的取值、赋值和初始化
      这里说的控件主要指的是文本框、下拉列表框这一类的控件,用户使用这些控件输入数据,然后我们需要提取这些数据进行处理。但是不同的控件有不同的取值方式,比如文本框要用Text,下拉列表框是SelectedValue (当然还有其他的方法),CheckBoxList也是SelectedValue,但是这个只能获取第一个选项,如果是选择了多个选项,他只能返回第一个被选中的选项。可能您觉得这个没什么的呀,很正常呀。       是呀,只不过我比较懒,尤其在写表单控件的时候,如何取值就是一个大问题了。以前用很
用户1174620
2018/02/08
8300
使用接口来统一控件的取值、赋值和初始化
我的数据访问函数库的源代码(一)—— 共用部分
/* 2008 4 25 更新 */ 我的数据访问函数库的源码。整个类有1400多行,原先就是分开来写的,现在更新后还是分开来发一下吧。 第一部分:内部成员,初始化设置等。 using System; using System.Data; using System.Data.SqlClient; using HBS.DataStruct; using HBS.Form; //using System.Security.Principal; namespace HBS {     
用户1174620
2018/02/07
8210
分页解决方案 之 分页算法——Pager_SQL的详细使用方法和注意事项
      上一次有点匆忙,如何使用介绍的不是太清楚,而且这两天有改掉了几个bug,所以这次呢详细说一下,然后更新一下代码和demo。       源代码和demo的下载:http://www.cnblogs.com/jyk/archive/2008/07/29/1255891.html JYK.Controls.Pager.QuickPagerSQL PagerSQL = new QuickPagerSQL();             //设置保存属性的位置。可以不保存,也可以保存在隐藏域、Cook
用户1174620
2018/02/26
8720
GridView导出Excel的超好样例「建议收藏」
事实上网上有非常多关于Excel的样例,可是不是非常好,他们的代码没有非常全,读的起来还非常晦涩。经过这几天的摸索,最终能够完毕我想要导出报表Excel的效果了。以下是我的效果图。
全栈程序员站长
2022/09/07
1K0
GridView导出Excel的超好样例「建议收藏」
分页解决方案 之 QuickPager的使用方法(PostBack分页、自动获取数据)
      适用范围:网站后台管理、OA、CRM、CMS等,从关系型数据库里提取数据,愿意使用Pager_SQL、DataAccessLibrary的情况。       最佳数据库:MS SQL。       优点:只需要设置几个属性即可,不用编写“分页事件”的处理代码。可以很方便的实现查询功能,以及保存查询条件。       Demo下载:http://www.cnblogs.com/jyk/archive/2008/07/29/1255891.html       使用方法: using JYK.Da
用户1174620
2018/02/26
5700
我自己写的一个分页控件(源码和演示代码)PostBack分页版 for vs2003、SQL Server
温馨提示: asp.net分页控件已经升级了,基于.net2.0 ,支持多种数据库。 正式命名为:QuickPager Asp.net 2.0 分页控件。 网站:www.natureFW.com 下载:http://www.naturefw.com/down/List1.aspx 在线演示:http://demo.naturefw.com 上一篇随笔: 我的分页控件(未完,待续)——控件件介绍及思路 一、分页控件的工作层次     如果按照三层的划分方式来说,应该算作工作在 UI层 和 逻辑层
用户1174620
2018/02/08
1.1K0
一种小型后台管理系统通用开发框架中的Cache缓存设计
本篇博客记录一下我在实习的公司的后台管理系统开发框架中学习到的一种关于网站的缓存(Cache)的实现方法,我会在弄懂的基础上,将该方法在.net core上进行实现。因为公司开发都是基于.net framework的,但是在.net 这一块,.net framework正在逐渐被.net core所取代,而目前公司的前辈们由于开发任务较重,并没有着手使用.net core的打算,所以,我自己打算为公司搭建一个基于.net core的后台开发框架,这对自己是一个挑战,但收获还是很大的,在这个过程中,我学到了很多。下面我记录一下我们公司关于网站设计中Cache的一种设计与实现方法(先说在.net mvc下的实现方法,后续会写另一篇.net core的实现方法):
CherishTheYouth
2019/07/30
5140
一种小型后台管理系统通用开发框架中的Cache缓存设计
Gridview行上下移动自己做的一个小例子(第一种方法)
今天没有什么事做,就写了一个GridView行上下移动的小例子。 方法有好多种,我先写第一种。 没有什么技术含量 思路: 把要上移或下移的id 与它的临近行的id进行互换 效果: 前台页面: 1 <
lpxxn
2018/01/31
9060
Gridview行上下移动自己做的一个小例子(第一种方法)
推荐阅读
CodeSmith系列(二)——使用CodeSmith生成ASP.NET后台代码
3.1K0
【开源】QuickPager ASP.NET2.0分页控件V2.0.0.1——分页控件的源码(一) 主体
9400
分页解决方案 —— GridView + QuickPager + QuickPager_SQL + DataAccessLibrary + 数据库
8990
jQuery EasyUI+ashx实现数据库的CIUD操作
1.1K0
【开源】QuickPager ASP.NET2.0分页控件V2.0.0.1——分页控件的源码 (二)
1.3K0
一个页面搞定几乎所有的列表需求的实现思路和一点代码。
1.2K0
其实添加数据也可以这样简单——表单的第一步抽象(针对数据访问层)《怪怪设计论: 抽象无处不在 》有感
6890
【自然框架】QuickPager分页控件,新增一种分页方式——伪URL分页(Postback版)
9240
【自然框架】 页面里的父类—— 改进和想法、解释
1.2K0
FineUI开源版之TreeGrid(修改)
9230
我的数据访问类(第二版)—— for .net2.0 (一)
7770
其实添加数据也可以这样简单——表单的第三步抽象(针对UI及后置代码)
1K0
使用接口来统一控件的取值、赋值和初始化
8300
我的数据访问函数库的源代码(一)—— 共用部分
8210
分页解决方案 之 分页算法——Pager_SQL的详细使用方法和注意事项
8720
GridView导出Excel的超好样例「建议收藏」
1K0
分页解决方案 之 QuickPager的使用方法(PostBack分页、自动获取数据)
5700
我自己写的一个分页控件(源码和演示代码)PostBack分页版 for vs2003、SQL Server
1.1K0
一种小型后台管理系统通用开发框架中的Cache缓存设计
5140
Gridview行上下移动自己做的一个小例子(第一种方法)
9060
相关推荐
CodeSmith系列(二)——使用CodeSmith生成ASP.NET后台代码
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验