在asp.net裏面通常的生命週期都比較短,若是想要比較長久的保存數據的話,通常有選擇幾種方式可供選擇,即cookies、ViewState、Session、Cache、application等。他們各有優缺點,也各有其本身的使用範圍。算法
我如今遇到了兩個問題,第一個是如何在這幾種方式裏面快速、方便的切換,第二個是如何實現一個既能夠區分用戶,又能夠區分頁面,又節省服務器的資源,又比較安全的保存數據的方式。安全
ViewState比較符合第二個問題的要求,可是他不太安全,表面上看他存放在客戶端的是亂碼,實際上是能夠解密的,解密以後就是明文了,你存放的是什麼就一目瞭然。若是是使用ViewState保存通常的數據倒也是沒有什麼問題,可是我想保存的是表名、字段名、SQL語句這樣的很敏感的數據,這樣的數據放在ViewState裏面,估計會被人罵死,呵呵。服務器
之前的QuickPager分頁控件確實是這麼處理的,如今越想越不安全,本身用用也就湊合了,若是推廣的話,那就害人了。因此我不得不想辦法來解決這個很嚴重的問題。因而我想寫一個獨立的可以保存數據的類。這個類可使用各類方式來存放數據,若是要加密數據的話,也能夠本身設置密鑰,這樣不知道密鑰的話,就不能解密了(除非暴力破解),固然您也能夠選擇不加密(保存在Session、Cache就不用加密了),也能夠選擇不保存。cookie
在實現這個函數的時候,遇到了兩大難題,一個是如何操做隱藏域,另外一個是如何「自動」保存和「自動」加載。ViewState但是不用單獨調用SaveViewState()來保存數據的。asp.net
在Class裏面操做cookie、Session等仍是比較容易的(System.Web.HttpContext.Current.Response.Cookies[ClientID]),但是如何控制隱藏域呢?想了很久也沒有想到好的方法,只好用笨方法了——傳遞一個Page實例(System.Web.UI.Page)進來,而後使用Page.ClientScript.RegisterHiddenField(ClientID, myData) 來搞定。ide
至於自動保存,也是採用了一個笨笨的方法,既然已經把Page傳遞進來了,那麼就給他加一個事件吧,_page.PreRender += new EventHandler(MyPage_PreRender);在執行Render以前保存數據。我想用相似的思路來搞定自動加載數據的(_page.PreLoad += new EventHandler(MyPage_PreLoad);),可是遇到了一個小問題。咱們通常都是習慣在Page_Load函數裏面給屬性賦值,可是我要加的事件倒是在Page_Load以前執行,也就是說若是在Page_Load裏面賦值的話,即便把事件加上了,那麼也早已經失去了執行的機會。固然能夠在OnInit裏面給屬性賦值,只是這麼作不太符合習慣。函數
Ps:這個難題解決以後,QuickPager分頁控件就能夠一份爲二了,變成QuickPager_UI、QuickPager_SQL兩個部分,再加上個人數據訪問函數庫和現實數據的控件,就是一套完整的分頁解決方案了。this

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

}

}