| 導購 | 订阅 | 在线投稿
分享
 
 
 

用MasterPage 代替 PageBase

來源:互聯網網民  2008-06-01 01:19:26  評論

目的:

實現用MasterPage中的.cs文件 代替項目中的PageBase。

動機:

寫這篇文章的動機,來自于一次項目重構。在.Net Framwork 2.0的B/S架構項目中同時采用PageBase和MasterPage技術,發現每次訪問頁面,頁面同時訪問PageBase和MasterPage,不僅造成性能降低,甚至有可能給日後的項目功能擴充和調整帶來邏輯錯誤隱患。

技術環節:

PageBase:.Net Framework 1.1 中經常使用的一種封裝多個頁面相同功能的技術。PageBase.cs類繼承自System.Web.UI.Page類,項目中的Web頁面繼承自PageBase.cs類,通過重寫基類中的頁面初始化方法,實現調用PageBase中的業務功能,例如:url參數驗證,保存訪問量等功能(具體實現方式參見微軟官方例子duwamishi)。

MasterPage:.Net Framework 2.0 中新特性,物理上包括兩個文件,分別是:.Master文件(html標記),.cs文件(C#代碼)。.Master文件實現顯示層繪制,.cs文件實現具體功能。繼承自MasterPage的Web頁面可以繼承MasterPage中的顯示層內容。繪制通用的頁頭頁腳,定制統一的布局,MasterPage是不錯的選擇。

模擬需求:

用MasterPage技術,代替PageBase,實現地址欄參數驗證。

簡單的做個解釋吧,數據庫中Login表信息如下圖:

用MasterPage 代替 PageBase

登錄系統之後,url地址欄中帶有參數,如下:

http://localhost:3730/MasterPageBaseDemo/TestPage.aspx?id=1001

此時用戶手動修改url地址欄中參數爲:

http://localhost:3730/MasterPageBaseDemo/TestPage.aspx?id=1002

被視爲非法操作,系統將自動跳轉回登錄頁面。

第一次代碼叠代:

1.參照傳統PageBase方法:

傳統的Page做法爲:

public class PageBase : System.Web.UI.Page

{

public PageBase()

{

}

/**//// <summary>

/// 入口方法

/// </summary>

PRotected void Initialize()

{

// 插入通用業務邏輯

}

}

Web頁面:

public partial class TestPage : PageBase

{

// 傳統的調用PageBase的方法

/**///// <summary>

/// 重寫基類OnPreInit() 方法,調用通用驗證方法

/// </summary>

/// <param name="e"></param>

protected override void OnInit(eventargs e)

{

base.Initialize();

}

}

參照其做法,將PageBase中的代碼移入MasterPage中:

MasterPage.cs:

public partial class MyMasterPage : System.Web.UI.MasterPage

{

protected void Page_Load(object sender, EventArgs e)

{

if (!IsPostBack)

{

// 調用驗證方法

Initialize();

}

}

}

將Web頁面中的代碼修改爲:

public partial class TestPage : System.Web.UI.Page

{

// 仿照PageBase方法,調用Master中的方法

/**//// <summary>

/// 重寫基類OnPreInit() 方法,調用通用驗證方法

/// </summary>

/// <param name="e"></param>

protected override void OnInit(eventargs e)

{

// 獲得母板頁引用

MyMasterPage myMasterPage = (MyMasterPage)this.Master;

// 調用母板頁中通用驗證方法

if (!IsPostBack)

{

myMasterPage.Initialize();

}

}

}將MasterPage中的Initialize()方法替換爲實例中的,測試代碼:

步驟1:用 用戶名zhangsan登錄系統,登錄成功,

頁面顯示 歡迎 zhangsan 登錄。

url地址顯示:

http://localhost:3730/MasterPageBaseDemo/TestPage.aspx?id=1001

步驟2:手動修改url地址欄:如下:

http://localhost:3730/MasterPageBaseDemo/TestPage.aspx?id=1002

頁面不會顯示 歡迎lisi登錄,而是跳轉回登錄頁面。

反思:雖然功能實現,但是存在不理想的環節:

1. Master中的被子類調用方法必須是public方法;

2. 雖然不用修改Web頁的繼承,但是依然要機械的複制粘貼重寫基類的OnInit()方法。

爲了消除這些懷味道,于是開始:

第二次代碼叠代:

修改MasterPage.cs中的代碼:

public partial class MyMasterPage : System.Web.UI.MasterPage

{

protected void Page_Load(object sender, EventArgs e)

{

if (!IsPostBack)

{

// 調用驗證方法

CheckLogin();

}

}

/**//// <summary>

/// 驗證訪問是否合法

/// </summary>

private void CheckLogin()

{

// 如果 url中的編號 或 cookie中的編號

if (string.IsNullOrEmpty(Request.QueryString["id"])

|| string.IsNullOrEmpty(CookieUtil.ReadCookieByKey("id")))

{

Response.Redirect("Login.aspx");

}// 如果url中的編號 和 cookie中的編號 不匹配,返回登錄頁

else if (int.Parse(Request.QueryString["id"]) != int.Parse(CookieUtil.ReadCookieByKey("id")))

{

Response.Redirect("Login.aspx");

}

}

}重構之後,Web頁可以不進行任何修改,MasterPage在自身的Page_Load()方法中自動調用驗證方法,而且將驗證方法設置爲private,僅供MasterPage自身調用,提高安全性。至此,代碼似乎比較理想了,測試:

步驟一:用 用戶名 zhangsan登錄系統,

依然顯示用戶登錄頁面。

測試失敗。

用斷點跟蹤代碼,發現問題出現在MasterPage.cs中的CheckLogin()方法中的代碼片段:

if (string.IsNullOrEmpty(Request.QueryString["id"])

|| string.IsNullOrEmpty(CookieUtil.ReadCookieByKey("id")))

{

Response.Redirect("Login.aspx");

}

由于登錄頁繼承自MasterPage,所以頁面加載時自動調用MasterPage.cs中的驗證方法,而自身的參數又不滿足string.IsNullOrEmpty()方法,于是又跳回到登錄頁面,登錄頁面在再次在加載時調用基類中的驗證方法,于是形成死循環。

在PageBase技術中,Web頁面可以有選擇的繼承自PageBase,而MasterPage技術中,爲了獲得一致的顯示層效果,Web頁面對繼承MasterPage的選擇性是非常底的,而且我們也不應該采用新建相同顯示,不帶有驗證代碼的MasterPage,來給不需要繼承基類功能的Web頁面來繼承,這種方式顯然不合理。爲了解決這個問題,于是開始了

第三次叠代:

引入配置文件:

<?xml version="1.0" encoding="utf-8" ?>

<pages>

<testpage>

<page title="TestPage" url="TestPage.aspx" needvalidate="true"/>

<page title="Login" url="Login.aspx" needvalidate="false"/>

</testpage>

<adminpages>

<page title="Page1" url="~/Admin/Page1.aspx" needvalidate="false"/>

<page title="Page2" url="~/Admin/Page2.aspx" needvalidate="false"/>

</adminpages>

</pages>

從中可以看到,將需要驗證的頁面加以標識(needvalidate="true")。

創建Xml數據訪問類:

public class XmlDAL

{

private static string filePath = string.Empty;

static XmlDAL()

{

// 初始化配置文件路徑

filePath = HttpContext.Current.Request.MapPath("~/App_Data/xml/" + "Pages.xml");

}

/**//// <summary>

/// 獲得需要驗證的頁面列表

/// </summary>

/// <returns>需要驗證的頁面列表</returns>

public static IList<string> GetValidatePages()

{

IList<string> pages = new List<string>();

// 如果指定配置文件存在

if (System.IO.File.Exists(filePath))

{

try

{

XmlDocument xmlDoc = new XmlDocument();

xmlDoc.Load(filePath);

// 獲取配置文件根節點

XmlNode root = xmlDoc.DocumentElement;

string xpath = "/pages/testpage/page[@needvalidate='true']";

XmlNodeList nodeList = root.SelectNodes(xpath);

// 便利節點集合

foreach (XmlNode node in nodeList)

{

pages.Add(node.Attributes["title"].Value);

}

}

catch (Exception ex)

{

throw new Exception(ex.Message);

}

}

return pages;

}

}

重構MasterPage.cs中的代碼,加入IsValidateNeeded(string url)方法,用于檢測當前頁面是否需要驗證,修改驗證方法:

public partial class MyMasterPage : System.Web.UI.MasterPage

{

protected void Page_Load(object sender, EventArgs e)

{

if (!IsPostBack)

{

// 調用驗證方法

CheckLogin();

}

}

/**//// <summary>

/// 驗證訪問是否合法

/// </summary>

private void CheckLogin()

{

// 判斷當前訪問頁面是否需要進行驗證

if (IsValidateNeeded(Request.RawUrl))

{

// 如果 url中的編號 或 cookie中的編號

if (string.IsNullOrEmpty(Request.QueryString["id"])

|| string.IsNullOrEmpty(CookieUtil.ReadCookieByKey("id")))

{

Response.Redirect("Login.aspx");

}// 如果url中的編號 和 cookie中的編號 不匹配,返回登錄頁

else if (int.Parse(Request.QueryString["id"]) != int.Parse(CookieUtil.ReadCookieByKey("id")))

{

Response.Redirect("Login.aspx");

}

}

}

/**//// <summary>

/// 驗證當前頁是否需要驗證

/// </summary>

/// <param name="currentPage">當前頁面名稱</param>

/// <returns>是否需要驗證狀態</returns>

private bool IsValidateNeeded(string url)

{

bool isNeeded = false;

// GetValidatePages() 方法返回需要驗證頁面列表

IList<string> pages = XmlDAL.GetValidatePages();

IEnumerator<string> ie = pages.GetEnumerator();

while (ie.MoveNext())

{

// 如果當前頁面需要進行驗證

if (url.Contains(ie.Current))

// 返回需要驗證狀態

return isNeeded = true;

}

return isNeeded;

}

}

進行測試:

步驟1:用 用戶名zhangsan登錄系統,登錄成功,

頁面顯示 歡迎 zhangsan 登錄。

url地址顯示:

http://localhost:3730/MasterPageBaseDemo/TestPage.aspx?id=1001

步驟2:手動修改url地址欄:如下:

http://localhost:3730/MasterPageBaseDemo/TestPage.aspx?id=1002

頁面不會顯示 歡迎lisi登錄,而是跳轉回登錄頁面。

至此我的代碼叠代結束了。

代碼下載:

http://www.cnblogs.com/Files/ayuan/MasterPageBaseDemo.rar

本人之前沒有寫技術文章的經驗,所以以上的文字難免晦澀,而且自身技術水平也有限,可能有些觀點不太成熟,歡迎各位朋友指正。

 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
目的: 實現用MasterPage中的.cs文件 代替項目中的PageBase。 動機: 寫這篇文章的動機,來自于一次項目重構。在.Net Framwork 2.0的B/S架構項目中同時采用PageBase和MasterPage技術,發現每次訪問頁面,頁面同時訪問PageBase和MasterPage,不僅造成性能降低,甚至有可能給日後的項目功能擴充和調整帶來邏輯錯誤隱患。 技術環節: PageBase:.Net Framework 1.1 中經常使用的一種封裝多個頁面相同功能的技術。PageBase.cs類繼承自System.Web.UI.Page類,項目中的Web頁面繼承自PageBase.cs類,通過重寫基類中的頁面初始化方法,實現調用PageBase中的業務功能,例如:url參數驗證,保存訪問量等功能(具體實現方式參見微軟官方例子duwamishi)。 MasterPage:.Net Framework 2.0 中新特性,物理上包括兩個文件,分別是:.Master文件(html標記),.cs文件(C#代碼)。.Master文件實現顯示層繪制,.cs文件實現具體功能。繼承自MasterPage的Web頁面可以繼承MasterPage中的顯示層內容。繪制通用的頁頭頁腳,定制統一的布局,MasterPage是不錯的選擇。 模擬需求: 用MasterPage技術,代替PageBase,實現地址欄參數驗證。 簡單的做個解釋吧,數據庫中Login表信息如下圖: [url=/bbs/detail_1783457.html][img]http://image.wangchao.net.cn/it/1323610743438.jpg[/img][/url] 登錄系統之後,url地址欄中帶有參數,如下: http://localhost:3730/MasterPageBaseDemo/TestPage.aspx?id=1001 此時用戶手動修改url地址欄中參數爲: http://localhost:3730/MasterPageBaseDemo/TestPage.aspx?id=1002 被視爲非法操作,系統將自動跳轉回登錄頁面。 第一次代碼叠代: 1.參照傳統PageBase方法: 傳統的Page做法爲: public class PageBase : System.Web.UI.Page { public PageBase() { } /**//// <summary> /// 入口方法 /// </summary> PRotected void Initialize() { // 插入通用業務邏輯 } } Web頁面: public partial class TestPage : PageBase { // 傳統的調用PageBase的方法 /**///// <summary> /// 重寫基類OnPreInit() 方法,調用通用驗證方法 /// </summary> /// <param name="e"></param> protected override void OnInit(eventargs e) { base.Initialize(); } } 參照其做法,將PageBase中的代碼移入MasterPage中: MasterPage.cs: public partial class MyMasterPage : System.Web.UI.MasterPage { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // 調用驗證方法 Initialize(); } } } 將Web頁面中的代碼修改爲: public partial class TestPage : System.Web.UI.Page { // 仿照PageBase方法,調用Master中的方法 /**//// <summary> /// 重寫基類OnPreInit() 方法,調用通用驗證方法 /// </summary> /// <param name="e"></param> protected override void OnInit(eventargs e) { // 獲得母板頁引用 MyMasterPage myMasterPage = (MyMasterPage)this.Master; // 調用母板頁中通用驗證方法 if (!IsPostBack) { myMasterPage.Initialize(); } } }將MasterPage中的Initialize()方法替換爲實例中的,測試代碼: 步驟1:用 用戶名zhangsan登錄系統,登錄成功, 頁面顯示 歡迎 zhangsan 登錄。 url地址顯示: http://localhost:3730/MasterPageBaseDemo/TestPage.aspx?id=1001 步驟2:手動修改url地址欄:如下: http://localhost:3730/MasterPageBaseDemo/TestPage.aspx?id=1002 頁面不會顯示 歡迎lisi登錄,而是跳轉回登錄頁面。 反思:雖然功能實現,但是存在不理想的環節: 1. Master中的被子類調用方法必須是public方法; 2. 雖然不用修改Web頁的繼承,但是依然要機械的複制粘貼重寫基類的OnInit()方法。 爲了消除這些懷味道,于是開始: 第二次代碼叠代: 修改MasterPage.cs中的代碼: public partial class MyMasterPage : System.Web.UI.MasterPage { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // 調用驗證方法 CheckLogin(); } } /**//// <summary> /// 驗證訪問是否合法 /// </summary> private void CheckLogin() { // 如果 url中的編號 或 cookie中的編號 if (string.IsNullOrEmpty(Request.QueryString["id"]) || string.IsNullOrEmpty(CookieUtil.ReadCookieByKey("id"))) { Response.Redirect("Login.aspx"); }// 如果url中的編號 和 cookie中的編號 不匹配,返回登錄頁 else if (int.Parse(Request.QueryString["id"]) != int.Parse(CookieUtil.ReadCookieByKey("id"))) { Response.Redirect("Login.aspx"); } } }重構之後,Web頁可以不進行任何修改,MasterPage在自身的Page_Load()方法中自動調用驗證方法,而且將驗證方法設置爲private,僅供MasterPage自身調用,提高安全性。至此,代碼似乎比較理想了,測試: 步驟一:用 用戶名 zhangsan登錄系統, 依然顯示用戶登錄頁面。 測試失敗。 用斷點跟蹤代碼,發現問題出現在MasterPage.cs中的CheckLogin()方法中的代碼片段: if (string.IsNullOrEmpty(Request.QueryString["id"]) || string.IsNullOrEmpty(CookieUtil.ReadCookieByKey("id"))) { Response.Redirect("Login.aspx"); } 由于登錄頁繼承自MasterPage,所以頁面加載時自動調用MasterPage.cs中的驗證方法,而自身的參數又不滿足string.IsNullOrEmpty()方法,于是又跳回到登錄頁面,登錄頁面在再次在加載時調用基類中的驗證方法,于是形成死循環。 在PageBase技術中,Web頁面可以有選擇的繼承自PageBase,而MasterPage技術中,爲了獲得一致的顯示層效果,Web頁面對繼承MasterPage的選擇性是非常底的,而且我們也不應該采用新建相同顯示,不帶有驗證代碼的MasterPage,來給不需要繼承基類功能的Web頁面來繼承,這種方式顯然不合理。爲了解決這個問題,于是開始了 第三次叠代: 引入配置文件: <?xml version="1.0" encoding="utf-8" ?> <pages> <testpage> <page title="TestPage" url="TestPage.aspx" needvalidate="true"/> <page title="Login" url="Login.aspx" needvalidate="false"/> </testpage> <adminpages> <page title="Page1" url="~/Admin/Page1.aspx" needvalidate="false"/> <page title="Page2" url="~/Admin/Page2.aspx" needvalidate="false"/> </adminpages> </pages> 從中可以看到,將需要驗證的頁面加以標識(needvalidate="true")。 創建Xml數據訪問類: public class XmlDAL { private static string filePath = string.Empty; static XmlDAL() { // 初始化配置文件路徑 filePath = HttpContext.Current.Request.MapPath("~/App_Data/xml/" + "Pages.xml"); } /**//// <summary> /// 獲得需要驗證的頁面列表 /// </summary> /// <returns>需要驗證的頁面列表</returns> public static IList<string> GetValidatePages() { IList<string> pages = new List<string>(); // 如果指定配置文件存在 if (System.IO.File.Exists(filePath)) { try { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(filePath); // 獲取配置文件根節點 XmlNode root = xmlDoc.DocumentElement; string xpath = "/pages/testpage/page[@needvalidate='true']"; XmlNodeList nodeList = root.SelectNodes(xpath); // 便利節點集合 foreach (XmlNode node in nodeList) { pages.Add(node.Attributes["title"].Value); } } catch (Exception ex) { throw new Exception(ex.Message); } } return pages; } } 重構MasterPage.cs中的代碼,加入IsValidateNeeded(string url)方法,用于檢測當前頁面是否需要驗證,修改驗證方法: public partial class MyMasterPage : System.Web.UI.MasterPage { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // 調用驗證方法 CheckLogin(); } } /**//// <summary> /// 驗證訪問是否合法 /// </summary> private void CheckLogin() { // 判斷當前訪問頁面是否需要進行驗證 if (IsValidateNeeded(Request.RawUrl)) { // 如果 url中的編號 或 cookie中的編號 if (string.IsNullOrEmpty(Request.QueryString["id"]) || string.IsNullOrEmpty(CookieUtil.ReadCookieByKey("id"))) { Response.Redirect("Login.aspx"); }// 如果url中的編號 和 cookie中的編號 不匹配,返回登錄頁 else if (int.Parse(Request.QueryString["id"]) != int.Parse(CookieUtil.ReadCookieByKey("id"))) { Response.Redirect("Login.aspx"); } } } /**//// <summary> /// 驗證當前頁是否需要驗證 /// </summary> /// <param name="currentPage">當前頁面名稱</param> /// <returns>是否需要驗證狀態</returns> private bool IsValidateNeeded(string url) { bool isNeeded = false; // GetValidatePages() 方法返回需要驗證頁面列表 IList<string> pages = XmlDAL.GetValidatePages(); IEnumerator<string> ie = pages.GetEnumerator(); while (ie.MoveNext()) { // 如果當前頁面需要進行驗證 if (url.Contains(ie.Current)) // 返回需要驗證狀態 return isNeeded = true; } return isNeeded; } } 進行測試: 步驟1:用 用戶名zhangsan登錄系統,登錄成功, 頁面顯示 歡迎 zhangsan 登錄。 url地址顯示: http://localhost:3730/MasterPageBaseDemo/TestPage.aspx?id=1001 步驟2:手動修改url地址欄:如下: http://localhost:3730/MasterPageBaseDemo/TestPage.aspx?id=1002 頁面不會顯示 歡迎lisi登錄,而是跳轉回登錄頁面。 至此我的代碼叠代結束了。 代碼下載: http://www.cnblogs.com/Files/ayuan/MasterPageBaseDemo.rar 本人之前沒有寫技術文章的經驗,所以以上的文字難免晦澀,而且自身技術水平也有限,可能有些觀點不太成熟,歡迎各位朋友指正。
󰈣󰈤
王朝萬家燈火計劃
期待原創作者加盟
 
 
 
>>返回首頁<<
 
 
 
 
 
 熱帖排行
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有