王朝网络
分享
 
 
 

用MasterPage 代替 PageBase

王朝other·作者佚名  2008-06-01
宽屏版  字体: |||超大  

目的:

实现用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地址栏中带有参数,如下:

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

本人之前没有写技术文章的经验,所以以上的文字难免晦涩,而且自身技术水平也有限,可能有些观点不太成熟,欢迎各位朋友指正。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有