목적:
MasterPage의 .cs 파일을 사용하여 프로젝트의 PageBase를 대체하십시오.
동기 부여:
이 글을 쓰게 된 동기는 프로젝트 재구성에서 비롯되었습니다. .Net Framwork 2.0의 B/S 아키텍처 프로젝트에서는 PageBase와 MasterPage 기술을 모두 사용했는데, 해당 페이지에 접속할 때마다 해당 페이지가 PageBase와 MasterPage에 동시에 접속하게 되어 성능 저하가 발생할 뿐만 아니라, 그러나 향후 프로젝트 기능 확장 및 조정 시 숨겨진 논리 오류가 발생할 수도 있습니다.
기술적인 측면:
PageBase: 여러 페이지의 동일한 기능을 캡슐화하기 위해 .Net Framework 1.1에서 자주 사용되는 기술입니다. PageBase.cs 클래스는 System.Web.UI.Page 클래스에서 상속됩니다. 프로젝트의 웹 페이지는 기본 클래스에서 페이지 초기화 메서드를 재정의하여 PageBase의 비즈니스 함수를 호출합니다. 예: URL 매개변수 확인, 방문 저장 및 기타 기능(구체적인 구현 방법은 Microsoft의 공식 예제 duwamishi를 참조하세요).
MasterPage: .Net Framework 2.0의 새로운 기능입니다. 물리적으로 .Master 파일(html 마크업)과 .cs 파일(C# 코드)이라는 두 개의 파일이 포함되어 있습니다. .Master 파일은 디스플레이 레이어 그리기를 구현하고, .cs 파일은 특정 기능을 구현합니다. MasterPage에서 상속되는 웹 페이지는 MasterPage의 표시 레이어 콘텐츠를 상속할 수 있습니다. 공통 머리글과 바닥글을 그리고 통합 레이아웃을 사용자 지정하려면 MasterPage가 좋은 선택입니다.
시뮬레이션 요구 사항:
MasterPage 기술을 사용하여 PageBase를 대체하여 주소 표시줄 매개변수 확인을 구현합니다.
데이터베이스의 로그인 테이블 정보를 간단히 설명하면 다음과 같습니다.
시스템에 로그인하면 URL 주소 표시줄에 다음과 같은 매개변수가 있습니다.
http://localhost:3730/MasterPageBaseDemo/TestPage.aspx?id=1001
이때 사용자는 URL 주소 표시줄의 매개변수를 다음과 같이 수동으로 수정합니다.
http://localhost:3730/MasterPageBaseDemo/TestPage.aspx?id=1002
이는 불법적인 작업으로 간주되며 시스템은 자동으로 로그인 페이지로 돌아갑니다.
첫 번째 코드 반복:
1. 전통적인 PageBase 방법을 참조하십시오:
전통적인 페이지 접근 방식은 다음과 같습니다.
공개 클래스 PageBase : System.Web.UI.Page
{
공개페이지베이스()
{
}
/**//// <요약>
/// 입력 방법
/// </summary>
보호된 무효 초기화()
{
//공통 비즈니스 로직 삽입
}
}
웹페이지:
공개 부분 클래스 TestPage : PageBase
{
//PageBase를 호출하는 전통적인 방법
/**///// <요약>
/// 기본 클래스 OnPreInit() 메서드를 재정의하고 일반 확인 메서드를 호출합니다.
/// </summary>
/// <param name="e"></param>
보호된 재정의 void OnInit(evenargs e)
{
베이스.초기화();
}
}
이 접근 방식을 따르고 PageBase의 코드를 MasterPage로 이동합니다.
MasterPage.cs:
공개 부분 클래스 MyMasterPage : System.Web.UI.MasterPage
{
protected void Page_Load(개체 전송자, EventArgs e)
{
if (!IsPostBack)
{
//호출 확인 방법
초기화();
}
}
}
웹페이지의 코드를 다음과 같이 수정하세요.
공개 부분 클래스 TestPage : System.Web.UI.Page
{
// PageBase 메소드를 모방하고 Master에서 메소드를 호출합니다.
/**//// <요약>
/// 기본 클래스 OnPreInit() 메서드를 재정의하고 일반 확인 메서드를 호출합니다.
/// </summary>
/// <param name="e"></param>
보호된 재정의 void OnInit(evenargs e)
{
// 마스터 페이지 참조를 가져옵니다.
MyMasterPage myMasterPage = (MyMasterPage)this.Master;
//마스터 페이지에서 일반 확인 방법을 호출합니다.
if (!IsPostBack)
{
myMasterPage.Initialize();
}
}
}MasterPage의 초기화() 메서드를 인스턴스 테스트 코드의 메서드로 바꿉니다.
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의 하위 클래스가 호출하는 메서드는 공개 메서드여야 합니다.
2. 웹 페이지의 상속을 수정할 필요는 없지만 기본 클래스의 OnInit() 메서드를 기계적으로 복사하여 붙여넣고 재정의해야 합니다.
이러한 미련을 없애기 위해 나는 다음과 같이 시작했습니다.
두 번째 코드 반복:
MasterPage.cs에서 코드를 수정합니다.
공개 부분 클래스 MyMasterPage : System.Web.UI.MasterPage
{
protected void Page_Load(개체 전송자, EventArgs e)
{
if (!IsPostBack)
{
//호출 확인 방법
로그인 확인();
}
}
/**//// <요약>
/// 접근이 적법한지 확인
/// </summary>
개인 무효 CheckLogin()
{
// URL의 숫자 또는 쿠키의 숫자인 경우
if (string.IsNullOrEmpty(Request.QueryString["id"]))
|| string.IsNullOrEmpty(CookieUtil.ReadCookieByKey("id")))
{
Response.Redirect("Login.aspx");
}//URL의 숫자가 쿠키의 숫자와 일치하지 않으면 로그인 페이지로 돌아갑니다.
else if (int.Parse(Request.QueryString["id"]) != int.Parse(CookieUtil.ReadCookieByKey("id")))
{
Response.Redirect("Login.aspx");
}
}
}재구성 후에는 웹 페이지를 어떤 식으로든 수정할 수 없습니다. MasterPage는 자체 Page_Load() 메서드에서 자동으로 확인 메서드를 호출하고 보안 강화를 위해 MasterPage 자체에서만 호출할 수 있는 확인 메서드를 비공개로 설정합니다. 이 시점에서 코드는 이상적인 것 같습니다.
1단계: 사용자 이름 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 기술에서는 웹 페이지가 PageBase를 선택적으로 상속할 수 있지만 MasterPage 기술에서는 일관된 디스플레이 레이어 효과를 얻기 위해 MasterPage를 상속하는 웹 페이지의 선택성이 매우 낮으며, 동일한 디스플레이를 생성하여 동일한 디스플레이를 생성해서는 안 됩니다. 새로운 것, 인증 코드가 없는 MasterPage는 기본 클래스 기능을 상속할 필요가 없는 웹 페이지를 상속하는 데 사용됩니다. 이 문제를 해결하기 위해 세 번째 반복이 시작되었습니다.
구성 파일을 가져옵니다.
<?xml version="1.0" 인코딩="utf-8" ?>
<페이지>
<테스트페이지>
<페이지 제목="TestPage" url="TestPage.aspx" needvalidate="true"/>
<page title="로그인" url="Login.aspx" needvalidate="false"/>
</testpage>
<관리 페이지>
<페이지 제목="페이지1" url="~/Admin/Page1.aspx" needvalidate="false"/>
<페이지 제목="페이지2" url="~/Admin/Page2.aspx" needvalidate="false"/>
</adminpages>
</페이지>
보시다시피 확인이 필요한 페이지가 식별됩니다(needvalidate="true").
Xml 데이터 액세스 클래스를 만듭니다.
공개 클래스 XmlDAL
{
개인 정적 문자열 filePath = string.Empty;
정적 XmlDAL()
{
//구성 파일 경로 초기화
filePath = HttpContext.Current.Request.MapPath("~/App_Data/xml/" + "Pages.xml");
}
/**//// <요약>
/// 확인이 필요한 페이지 목록을 가져옵니다.
/// </summary>
/// <returns>확인이 필요한 페이지 목록</returns>
공개 정적 IList<문자열> GetValidatePages()
{
IList<string> 페이지 = new List<string>();
//지정된 구성 파일이 존재하는 경우
if (System.IO.File.Exists(파일 경로))
{
노력하다
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(filePath);
// 구성 파일의 루트 노드를 가져옵니다.
XmlNode 루트 = xmlDoc.DocumentElement;
string xpath = "/pages/testpage/page[@needvalidate='true']";
XmlNodeList nodeList = root.SelectNodes(xpath);
// 편의 노드 수집
foreach(nodeList의 XmlNode 노드)
{
페이지.추가(노드.속성["제목"].값);
}
}
잡기 (예외예외)
{
새로운 예외 발생(ex.Message);
}
}
반환 페이지;
}
}
MasterPage.cs에서 코드를 리팩터링하고 IsValidateNeeded(string url) 메서드를 추가하여 현재 페이지에 확인이 필요한지 확인합니다.
공개 부분 클래스 MyMasterPage : System.Web.UI.MasterPage
{
protected void Page_Load(개체 전송자, EventArgs e)
{
if (!IsPostBack)
{
//호출 확인 방법
로그인 확인();
}
}
/**//// <요약>
/// 접근이 적법한지 확인
/// </summary>
개인 무효 CheckLogin()
{
// 현재 액세스한 페이지에 확인이 필요한지 여부를 결정합니다.
if(IsValidateNeeded(Request.RawUrl))
{
// URL의 숫자 또는 쿠키의 숫자인 경우
if (string.IsNullOrEmpty(Request.QueryString["id"]))
|| string.IsNullOrEmpty(CookieUtil.ReadCookieByKey("id")))
{
Response.Redirect("Login.aspx");
}//URL의 숫자가 쿠키의 숫자와 일치하지 않으면 로그인 페이지로 돌아갑니다.
else if (int.Parse(Request.QueryString["id"]) != int.Parse(CookieUtil.ReadCookieByKey("id")))
{
Response.Redirect("Login.aspx");
}
}
}
/**//// <요약>
/// 현재 페이지에 인증이 필요한지 확인합니다.
/// </summary>
/// <param name="currentPage">현재 페이지 이름</param>
/// <returns>상태 확인이 필요한지 여부</returns>
개인 부울 IsValidateNeeded(문자열 URL)
{
bool isNeeded = false;
// GetValidatePages() 메서드는 확인이 필요한 페이지 목록을 반환합니다.
IList<string> 페이지 = XmlDAL.GetValidatePages();
IEnumerator<string> 즉 = 페이지.GetEnumerator();
동안(즉.MoveNext())
{
// 현재 페이지에서 확인이 필요한 경우
if (url.Contains(ie.Current))
//확인이 필요한 상태로 복귀
isNeeded = true를 반환합니다.
}
반환이 필요합니다.
}
}
테스트하려면:
1단계: 사용자 이름 zhangsan으로 시스템에 로그인하면 로그인이 성공합니다.
페이지에는 zhangsan의 로그인을 환영한다고 표시됩니다.
URL 주소는 다음과 같습니다.
http://localhost:3730/MasterPageBaseDemo/TestPage.aspx?id=1001
2단계: URL 주소 표시줄을 다음과 같이 수동으로 수정합니다.
http://localhost:3730/MasterPageBaseDemo/TestPage.aspx?id=1002
페이지에 환영 lisi 로그인이 표시되지 않지만 로그인 페이지로 다시 이동합니다.
이것으로 내 코드 반복이 끝났습니다.
코드 다운로드: