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

 

      在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语句)的,这些部分都可以独立使用,也可以替换成其他的控件、类库。

 

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

 

 

 

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

      
    }
}

 

时间: 2024-09-20 05:37:51

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

java使用hashMap缓存保存数据的方法_java

本文实例讲述了java使用hashMap缓存保存数据的方法.分享给大家供大家参考,具体如下: private static final HashMap<Long, XXX> sCache = new HashMap<Long, XXX>(); private static int sId = -1; public static void initAlbumArtCache() { try { //... if (id != sId) { clearCache(); sId = id

Android 实现永久保存数据的方法详解_Android

背景:在Android中按照数据保存的方式,可以分为如下几种Content Provider (用的SQLite实现),SQLite,SharedPreferences(用的XML实现),文件,网络等方式. 今天在项目中,需要做一个永久保存的数据,保存到本地.于是测试了这几种保存方式.其中:SharedPreferences.SQLite.Content Provider 会在[设置]--[应用管理]--点击[清除数据]的时候,会删除文件.所以不安全.文件系统:如果SD卡坏了,或者拔掉的时候也会

Android 实现永久保存数据的方法详解

背景: 在Android中按照数据保存的方式,可以分为如下几种 Content Provider (用的SQLite实现),SQLite,SharedPreferences(用的XML实现),文件,网络等方式. 今天在项目中,需要做一个永久保存的数据,保存到本地. 于是测试了这几种保存方式. 其中:SharedPreferences.SQLite.Content Provider 会在[设置]--[应用管理]--点击[清除数据]的时候,会删除文件.所以不安全. 文件系统:如果SD卡坏了,或者拔掉

Flash MX本地保存数据的二种方法

数据 谈到计算机操作,往往就不了数据操作,最基本的数据操作就是读取和保存数据.Flash程序很多时候也会用到数据操作,比如说载入外部文件就是读取数据.然而Flash保存数据的能力是很有限的.Flash 5时我们还可以用fscommond来本地保存外部文本文件,到了FlashMX时代,出于对安全因素的考虑,Micromedia取消了这个功能. 那是不是我们就无法用Flash MX保存数据了呢?回答是否定的,这里我就系统给大家介绍用Flash MX本地保存外部数据的三种方法. 方法一:使用MMsav

javascript实现Table间隔色以及选择高亮(和动态切换数据)的方法_javascript技巧

本文实例讲述了javascript实现Table间隔色以及选择高亮(和动态切换数据)的方法.分享给大家供大家参考.具体实现方法如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1

教大家一个让数据不再重复的方法

    不知道你是不是还是为数据重复烦恼呢?近天在这里教大家一个让数据不再重复的方法 自定义Excel公式!     大家在使用Excel2007编辑工作表格时经常要输入大量数据,有时要求输入的这些数据是不允许重复的,例如常见的身份证号码等,一旦错误输入查找起来那可是相当麻烦的一件事.对于这个问题,其实我们可以自定义公式,让Excel对重复数据能够自动弹出警告信息,以便及时提醒操作人员. Step1:运行Excel 2007程序并新建一个工作表格,然后按下"Ctrl+A "组合键全选该

asp 保存数据与批量删除数据方法

文章来提供一篇asp教程 保存数据与批量删除数据方法哦,在asp中保存数据到数据库教程也有很多种方法,我们只说了二种,同时删除数据也有很多方法,单条删除,批量删除,会用到for ,in来 实现. 注意:不同的字段名用英文逗号隔开,且不支持星号 表名处输入要查询的表名:如:table1 前台表单页面: 主要是注意input字段的name属性. asp下常用的添加数据代码是: 通过adodb.recordset 优点是:数据库入库比较简单,不用考虑单引号问题.不容易出现错误. 代码如下: usern

win8系统下保存历史文件数据的方法

  小编就来教大家win8电脑中如何使用文件历史数据进行保存文件. win8系统下保存历史文件数据的方法教程 1.打开电脑之后,咱们直接按下快捷键win+i,这样就会弹出一个设置界面,咱们直接选择设置中的控制面板功能. 2.在控制面板的界面中,咱们找到并选中系统和安全下的"通过文件历史记录保存你的文件备份副本"选项. 3.接下来需要咱们选择一个盘或者是移动设备来存储这些东西,这里需要说明的是,由于文件可能很大,所以小编建议大家选择8G及以上的存储盘来保存文件.选择好之后,点击页面中的启

python爬取网站数据保存使用的方法_python

编码问题因为涉及到中文,所以必然地涉及到了编码的问题,这一次借这个机会算是彻底搞清楚了.问题要从文字的编码讲起.原本的英文编码只有0~255,刚好是8位1个字节.为了表示各种不同的语言,自然要进行扩充.中文的话有GB系列.可能还听说过Unicode和UTF-8,那么,它们之间是什么关系呢?Unicode是一种编码方案,又称万国码,可见其包含之广.但是具体存储到计算机上,并不用这种编码,可以说它起着一个中间人的作用.你可以再把Unicode编码(encode)为UTF-8,或者GB,再存储到计算机