用MasterPage 代替 PageBase

四季青tanmu

四季青tanmu

2016-02-19 20:57

想不想get新技能酷炫一下,今天图老师小编就跟大家分享个简单的用MasterPage 代替 PageBase教程,一起来看看吧!超容易上手~

  目的:
          实现用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
  被视为非法操作,系统将自动跳转回登录页面。

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/webkaifa/)

  
  第一次代码迭代:

  
  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 IListstring GetValidatePages()
      {
          IListstring pages = new Liststring();
          // 如果指定配置文件存在
          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() 方法返回需要验证页面列表
          IListstring pages = XmlDAL.GetValidatePages();
          IEnumeratorstring 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
  本人之前没有写技术文章的经验,所以以上的文字难免晦涩,而且自身技术水平也有限,可能有些观点不太成熟,欢迎各位朋友指正。

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/webkaifa/)
展开更多 50%)
分享

猜你喜欢

用MasterPage 代替 PageBase

Web开发
用MasterPage 代替 PageBase

用湿纸巾代替洗手好吗

电脑网络
用湿纸巾代替洗手好吗

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

怕上火 用牛胶代替阿胶

饮食禁忌 健康饮食
怕上火 用牛胶代替阿胶

木薯粉可以用什么代替

电脑网络
木薯粉可以用什么代替

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

化妆棉可以用什么代替

化妆棉 化妆工具 化妆技巧
化妆棉可以用什么代替

用session代替apache服务器验证

PHP
用session代替apache服务器验证

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

如何使用MAC自带预览软件给图片添加注释

如何使用MAC自带预览软件给图片添加注释

输入法不能切换 解决输入法不能切换方法

输入法不能切换 解决输入法不能切换方法
下拉加载更多内容 ↓