1. ความรู้เบื้องต้นเกี่ยวกับสคริปต์เซิร์ฟเวอร์
ขั้นแรก เรามาทบทวนวิธีการดำเนินการพื้นฐานของเว็บเซิร์ฟเวอร์เพจกัน:
1. ไคลเอนต์ส่งคำขอไปยังเซิร์ฟเวอร์โดยการพิมพ์ที่อยู่ในแถบที่อยู่ของเบราว์เซอร์
2. หลังจากที่เซิร์ฟเวอร์ได้รับคำขอแล้ว มันส่งไปยังเพจฝั่งเซิร์ฟเวอร์ที่เกี่ยวข้อง (นั่นคือสคริปต์) จะถูกดำเนินการ สคริปต์สร้างการตอบกลับจากไคลเอนต์และส่งกลับไปยังไคลเอนต์
3. เบราว์เซอร์ไคลเอนต์ได้รับการตอบสนองจากเซิร์ฟเวอร์ และแยกวิเคราะห์ Html และนำเสนอเว็บเพจแบบกราฟิกแก่ผู้ใช้ สำหรับ
การโต้ตอบระหว่างเซิร์ฟเวอร์และไคลเอนต์ มักจะใช้วิธีหลักต่อไปนี้:
1. แบบฟอร์ม: นี่เป็นวิธีที่สำคัญที่สุดในการรับอินพุตจากผู้ใช้ การส่งข้อมูลไปยังเซิร์ฟเวอร์เพื่อการประมวลผล
2.QueryString
: โดยการเพิ่มพารามิเตอร์หลัง Url พารามิเตอร์จะถูกส่งไปยังเซิร์ฟเวอร์จริงๆ
วิธีพิเศษที่มักใช้เพื่อยืนยันตัวตนของผู้ใช้
2. บทนำ ASP.Net
ภาษาสคริปต์เซิร์ฟเวอร์แบบดั้งเดิม เช่น ASP, JSP ฯลฯ เขียนสคริปต์เซิร์ฟเวอร์ในลักษณะเดียวกันมาก ทั้งหมดฝังโค้ดที่แปลหรือคอมไพล์และดำเนินการ ใน Html และแพลตฟอร์มเซิร์ฟเวอร์รันโค้ดเหล่านี้เพื่อสร้าง Html สำหรับเพจที่คล้ายกัน วงจรชีวิตของ Servlet นั้นง่ายมาก นั่นคือโค้ดทั้งหมดจะถูกดำเนินการตั้งแต่ต้นจนจบ แน่นอนว่า Servlet เขียนไว้ Java สามารถเขียนโค้ดที่ซับซ้อนมากขึ้นได้ แต่จากมุมมองเชิงโครงสร้างแล้ว ก็ไม่ต่างจาก JSP
การเกิดขึ้นของ ASP.Net ทำลายประเพณีนี้ ASP.Net นำเทคโนโลยี CodeBehind และการควบคุมฝั่งเซิร์ฟเวอร์มาใช้ เพิ่มแนวคิดของเหตุการณ์ฝั่งเซิร์ฟเวอร์ เปลี่ยนรูปแบบการเขียนภาษาสคริปต์ และเข้าใกล้การเขียนโปรแกรม Window มากขึ้น ทำให้การเขียนโปรแกรมเว็บง่ายขึ้น ใช้งานง่าย แต่เราต้องเห็นว่า ASP.Net ไม่ได้เปลี่ยนรูปแบบพื้นฐานของการเขียนโปรแกรมเว็บ เพียงสรุปรายละเอียดบางส่วนและมีฟังก์ชันที่ใช้งานง่าย ทำให้เขียนและบำรุงรักษาโค้ดได้ง่ายขึ้น ขอบเขต ทำให้วิธีดำเนินการฝั่งเซิร์ฟเวอร์ซับซ้อนขึ้น นี่คือหัวข้อหลักที่เราจะพูดถึงในวันนี้: วงจรชีวิตของเว็บเพจ ASP.Net
3. โหมดการประมวลผลคำขอ ASP.Net
เราบอกว่าหน้าเว็บของ ASP.Net ไม่ได้แยกออกจากโหมดการเขียนโปรแกรมเว็บ ดังนั้นจึงยังคงทำงานในโหมดคำขอ -> รับคำขอ -> ประมวลผลคำขอ -> ส่งการตอบกลับแต่ละครั้ง กับไคลเอนต์จะทริกเกอร์คำขอใหม่ ดังนั้นวงจรชีวิตของเว็บเพจจะขึ้นอยู่กับคำขอเดียว
เมื่อ IIS ได้รับการร้องขอจากไคลเอนต์ มันจะส่งคำขอไปยังกระบวนการ aspnet_wp เพื่อการประมวลผล HttpRuntime ) เพื่อจัดการคำขอ รันไทม์นี้ "จัดเตรียมชุดบริการรันไทม์ ASP.NET สำหรับแอปพลิเคชันปัจจุบัน" (จาก MSDN)
เมื่อ HttpRuntime ประมวลผลคำขอ มันจะรักษาชุดของอินสแตนซ์ของแอปพลิเคชัน นั่นคือ อินสแตนซ์ของคลาส Global ของแอปพลิเคชัน (global.asax) อินสแตนซ์เหล่านี้จะถูกจัดเก็บไว้ในกลุ่มแอปพลิเคชันเมื่อไม่มีการร้องขอ (จริงๆ แล้ว กลุ่มแอปพลิเคชันได้รับการดูแล) โดยคลาสอื่น HttpRuntime เป็นเพียงการเรียกธรรมดา) ทุกครั้งที่ได้รับคำขอ HttpRuntime จะได้รับอินสแตนซ์ที่ไม่ได้ใช้งานเพื่อดำเนินการตามคำขอ กลับไปที่พูล "อินสแตนซ์ถูกใช้เพื่อจัดการคำขอหลายรายการในช่วงอายุการใช้งาน แต่สามารถจัดการได้ครั้งละหนึ่งคำขอเท่านั้น" (ตัดตอนมาจาก MSDN)
เมื่ออินสแตนซ์ของแอปพลิเคชันจัดการคำขอ มันจะสร้างอินสแตนซ์ของ คลาสเพจคำขอและดำเนินการวิธี ProcessRequest เพื่อประมวลผลคำขอ วิธีนี้เป็นจุดเริ่มต้นของวงจรชีวิตของเว็บเพจ
4. หน้า Aspx และ CodeBehind
ก่อนที่เราจะเจาะลึกวงจรชีวิตของหน้า เรามาพูดถึงความสัมพันธ์บางอย่างระหว่าง Aspx และ CodeBehind ก่อน
<%@ Page language="c#" Codebehind="WebForm.aspx.cs" Inherits="MyNamespace.WebForm" %>
ฉันเชื่อว่าเพื่อนๆ ที่เคยใช้เทคโนโลยี CodeBehind น่าจะคุ้นเคยกับประโยคที่อยู่ด้านบนสุดของ ASPX เป็นอย่างดี วิเคราะห์ทีละรายการ:
Page language="c#" Needless to say,
Codebehind="WebForm.aspx.cs" ประโยคนี้ระบุถึงไฟล์โค้ดที่ถูกผูกไว้
Inherits="MyNamespace.WebForm" ประโยคนี้มีความสำคัญมาก ซึ่งแสดงถึงชื่อคลาส สืบทอดมาจากเพจซึ่งเป็นคลาสในโค้ดไฟล์ของ CodeBehind คลาสนี้จะต้องได้รับมาจาก System.Web.WebControls.Page
จากข้างต้น เราสามารถวิเคราะห์ได้ว่า ที่จริงแล้ว คลาสใน CodeBehind เป็นพื้นฐานของเพจ (ASPX) คลาส ณ จุดนี้เพื่อนบางคนอาจต้องการถาม ?
จริงๆ แล้วปัญหานี้ไม่ซับซ้อน เพื่อนที่ใช้โปรแกรม ASP.Net สามารถไปที่ดิสก์ระบบของคุณได้: WINDOWSMicrosoft.NETFramework<version number>Temporary ASP.NET Files และวางไว้ด้านล่างไฟล์ชั่วคราวทั้งหมดของ ASP แอปพลิเคชัน .Net ที่มีอยู่ในเครื่องนี้ ชื่อของไดเรกทอรีย่อยคือชื่อของแอปพลิเคชัน จากนั้นลงไปสองระดับ (เพื่อให้แน่ใจว่าไม่ซ้ำกัน ASP.Net จะสร้างไดเรกทอรีย่อยสองระดับโดยอัตโนมัติ และไดเรกทอรีย่อยชื่อคือ สุ่ม) จากนั้นเราจะพบว่ามีไลบรารีลิงก์จำนวนมากที่คล้ายกับ: "yfy1gjhc.dll", "xeunj5u3.dll" และแหล่งที่มาเช่นไฟล์ "komee-bp.0.cs" และ "9falckav.0.cs" อันที่จริงนี่คือผลลัพธ์ของการคอมไพล์ ASPX แบบไดนามิกโดย ASP.Net เมื่อเราเปิดไฟล์ต้นฉบับเหล่านี้ เราจะพบ:
คลาสสาธารณะ WebForm_aspx: MyNamespace.WebForm, System.Web.SessionState.IRquiresSessionState
นี่เป็นการยืนยันคำสั่งก่อนหน้าของเรา , ASPX เป็นคลาสย่อยของคลาสการผูกโค้ด ชื่อของมันคือชื่อไฟล์ ASPX บวกกับส่วนต่อท้าย "_aspx" จากการศึกษาโค้ดเหล่านี้ เราจะพบว่าในความเป็นจริงแล้ว การควบคุมเซิร์ฟเวอร์ทั้งหมดที่กำหนดใน aspx นั้นถูกสร้างขึ้นในโค้ดเหล่านี้ และ เมื่อโค้ดเหล่านี้ถูกสร้างขึ้นแบบไดนามิก โค้ดที่เดิมฝังอยู่ใน ASPX จะถูกเขียนในตำแหน่งที่เกี่ยวข้อง
เมื่อมีการเยี่ยมชมเพจเป็นครั้งแรก รันไทม์ HTTP จะใช้ตัวสร้างโค้ดเพื่อแยกวิเคราะห์ไฟล์ ASPX และสร้างซอร์สโค้ดและคอมไพล์ จากนั้นการเยี่ยมชมครั้งต่อไปจะเรียก dll ที่คอมไพล์แล้วโดยตรง นี่คือเหตุผลว่าทำไม ASPX จึงเข้าถึงได้ มันช้ามาก
หลังจากอธิบายปัญหานี้แล้ว มาดูปัญหาอื่นกัน เมื่อเราใช้การผูกโค้ด ให้ลากตัวควบคุมบนเพจการออกแบบ จากนั้นสลับไปที่มุมมองโค้ด คุณสามารถใช้ตัวควบคุมได้โดยตรงใน Page_Load เนื่องจากตัวควบคุมถูกสร้างขึ้นในคลาสย่อย เหตุใดจึงสามารถใช้ในคลาสพาเรนต์ได้ แล้วใช้มันโดยตรงล่ะ?
ในความเป็นจริง เราจะพบว่าเมื่อใดก็ตามที่เราใช้ VS.Net เพื่อลากตัวควบคุมไปยังเพจ คำสั่งที่คล้ายกันนี้จะถูกเพิ่มลงในไฟล์การผูกโค้ดเสมอ:
protected System.Web.WebControls.Button Button1
เราพบว่าสิ่งนี้ ฟิลด์คือ Declare it as protected และชื่อสอดคล้องกับ ID ของตัวควบคุมใน ASPX หากคุณคิดอย่างรอบคอบ ปัญหานี้จะได้รับการแก้ไข เราได้กล่าวไว้ก่อนหน้านี้ว่าซอร์สโค้ดของ ASPX นั้นถูกสร้างขึ้นและคอมไพล์โดยตัวสร้างแบบไดนามิก มันจะเพิ่มโค้ดที่คล้ายกับดังต่อไปนี้:
this.DataGrid1 = __ctrl;
__ctrl นี้เป็นตัวแปรที่สร้างการควบคุม ในเวลานี้ มันจะกำหนดการอ้างอิงของการควบคุมให้กับตัวแปรที่สอดคล้องกันในคลาสหลัก ซึ่งเป็นสาเหตุว่าทำไม คลาสพาเรนต์ การประกาศจะต้องได้รับการปกป้อง (จริงๆ แล้วมันสามารถเป็นแบบสาธารณะได้) เพราะมันจำเป็นเพื่อให้แน่ใจว่าคลาสย่อยสามารถเรียกมันได้
จากนั้นเมื่อดำเนินการ Page_Load เนื่องจากการประกาศของคลาสพาเรนต์ได้รับการกำหนดโดยรหัสการเริ่มต้นในคลาสย่อย เราจึงสามารถใช้ฟิลด์นี้เพื่อเข้าถึงการควบคุมที่เกี่ยวข้อง เมื่อรู้สิ่งนี้แล้ว เราจะไม่ผูกมัดโค้ดโดยใช้การควบคุม ในตัวสร้างในไฟล์ที่ระบุทำให้เกิดข้อผิดพลาดข้อยกเว้นการอ้างอิงที่เป็นโมฆะ เนื่องจากตัวสร้างถูกดำเนินการก่อน การเริ่มต้นของคลาสย่อยจึงยังไม่เริ่มต้น ดังนั้นฟิลด์ในคลาสพาเรนต์จึงมีค่าเป็นโมฆะ เราจะหารือในภายหลัง เมื่อคลาสถูกเตรียมใช้งาน
5. วงจรชีวิตของเพจ
กลับมาที่เนื้อหาที่กล่าวถึงในหัวข้อที่สาม เราได้พูดถึงอินสแตนซ์ของ HttpApplication ที่ได้รับคำขอและการสร้างอินสแตนซ์ของคลาสเพจ ที่จริงแล้ว อินสแตนซ์นี้เป็นอินสแตนซ์ของคลาส ASPX ที่คอมไพล์แบบไดนามิก ในหัวข้อที่แล้ว เราได้เรียนรู้ว่าจริงๆ แล้ว ASPX เป็นคลาสย่อยของคลาสในการผูกโค้ด ดังนั้นจึงสืบทอดวิธีการที่ได้รับการป้องกันทั้งหมด
ตอนนี้เรามาดูโค้ดของคลาส CodeBehind ที่สร้างขึ้นโดยอัตโนมัติโดย VS.Net เพื่อเริ่มการอภิปรายเกี่ยวกับวงจรชีวิตของเพจ:
#region Web Form Designer ที่สร้างโค้ด
แทนที่การป้องกัน void OnInit(EventArgs e)
-
-
// CODEGEN: การเรียกนี้จำเป็นโดยผู้ออกแบบ ASP.NET Web Forms
-
เตรียมใช้งานส่วนประกอบ();
ฐาน OnInit(e);
}
/// <สรุป>
/// Designer รองรับวิธีการที่จำเป็น - อย่าใช้โปรแกรมแก้ไขโค้ดเพื่อแก้ไข
/// เนื้อหาของวิธีนี้
/// </summary>
โมฆะส่วนตัว InitializeComponent()
-
this.DataGrid1.ItemDataBound += ใหม่ System.Web.UI.WebControls.DataGridItemEventHandler(this.DataGrid1_ItemDataBound);
this.Load += ใหม่ System.EventHandler(this.Page_Load);
}
#endregion
นี่คือโค้ดสำหรับเพจที่สร้างโดยใช้ VS.Net มีสองวิธีในนั้น วิธีแรกคือ OnInit และอีกวิธีหนึ่งคือ InitializeComponent วิธีหลังถูกเรียกโดยวิธีแรก จุดเริ่มต้นของการเริ่มต้นเพจ ใน InitializeComponent เราเห็นการประกาศเหตุการณ์ของการควบคุมและการประกาศโหลดของเพจ
ต่อไปนี้เป็นคำอธิบายที่คัดลอกมาจาก MSDN และตารางลำดับของวิธีวงจรชีวิตของเพจและเหตุการณ์ที่ทริกเกอร์:
"แต่ละครั้งที่มีการร้องขอเพจ ASP.NET เซิร์ฟเวอร์จะโหลดเพจ ASP.NET และยกเลิกการโหลดเพจเมื่อคำขอเสร็จสมบูรณ์ เพจและตัวควบคุมเซิร์ฟเวอร์มีหน้าที่รับผิดชอบในการดำเนินการตามคำขอและแสดงผล HTML ไปยังไคลเอนต์ แม้ว่าการสื่อสารระหว่างไคลเอนต์และเซิร์ฟเวอร์นั้นไม่มีสถานะและไม่ต่อเนื่อง แต่ไคลเอนต์จะต้องรับรู้ว่าเป็นกระบวนการที่ต่อเนื่อง "
"ภาพลวงตาของความต่อเนื่องนี้ถูกนำไปใช้โดยเฟรมเวิร์กเพจ ASP.NET เพจ และส่วนควบคุมของมัน หลังจาก postback ลักษณะการทำงานของตัวควบคุมจะต้องเริ่มต้นจากตำแหน่งที่คำขอเว็บสุดท้ายสิ้นสุดลง กรอบงานสามารถทำให้การจัดการสถานะการดำเนินการค่อนข้างดี ง่าย แต่เพื่อให้บรรลุผลต่อเนื่อง นักพัฒนาการควบคุมจะต้องทราบลำดับการดำเนินการของการควบคุม นักพัฒนาการควบคุมจำเป็นต้องเข้าใจว่าข้อมูลใดที่สามารถนำมาใช้และข้อมูลใดที่สามารถเก็บรักษาไว้โดยการควบคุมในแต่ละขั้นตอนของวงจรชีวิตการควบคุม สถานะที่มีการแสดงผลตัวควบคุม ตัวอย่างเช่น ตัวควบคุมไม่สามารถเรียกพาเรนต์ได้จนกว่าแผนผังการควบคุมบนเพจจะถูกเติม" ตารางต่อไปนี้แสดงภาพรวมระดับสูงของขั้นตอนต่างๆ ในวงจรการใช้งานการควบคุม คลิกในตาราง ลิงค์"
ขั้นตอน | จำเป็นต้องดำเนินการ | เพื่อแทนที่วิธีการหรือเหตุการณ์การเริ่มต้น |
เริ่มต้น | การตั้งค่าที่จำเป็นภายในวงจรชีวิตของคำขอเว็บที่เข้ามา ดูการจัดการเหตุการณ์ที่สืบทอดมา | เหตุการณ์เริ่มต้น (วิธี OnInit) |
จะโหลดสถานะมุมมอง | เมื่อสิ้นสุดระยะนี้ คุณสมบัติ ViewState ของตัวควบคุมจะถูกเติมโดยอัตโนมัติ สำหรับรายละเอียด โปรดดูคำแนะนำในการบำรุงรักษาสถานะในการควบคุม ตัวควบคุมสามารถแทนที่การใช้งานเริ่มต้นของเมธอด LoadViewState เพื่อคืนค่าเป็นสถานะแบบกำหนดเอง | เมธอด LoadViewState |
จัดการข้อมูล postback | ประมวลผลข้อมูลแบบฟอร์มขาเข้า และอัปเดตคุณสมบัติตามนั้น ดูการจัดการข้อมูล Postback หมายเหตุ เฉพาะตัวควบคุมที่จัดการข้อมูล postback เท่านั้นที่เข้าร่วมในระยะนี้ | วิธีการ LoadPostData (ถ้ามีการใช้ IPostBackDataHandler) |
จะโหลดและ | ดำเนินการทั่วไปกับคำขอทั้งหมด เช่น การตั้งค่าแบบสอบถามฐานข้อมูล ณ จุดนี้ ตัวควบคุมเซิร์ฟเวอร์ในแผนผังได้ถูกสร้างขึ้นและเตรียมใช้งาน สถานะได้รับการคืนค่า และตัวควบคุมแบบฟอร์มสะท้อนถึงข้อมูลของไคลเอ็นต์ ดูการจัดการเหตุการณ์ที่สืบทอดมา | โหลดเหตุการณ์ (วิธี OnLoad) |
ส่งการแจ้งเตือนการเปลี่ยนแปลง postback | เพิ่มเหตุการณ์การเปลี่ยนแปลงเพื่อตอบสนองต่อการเปลี่ยนแปลงสถานะระหว่าง postback ปัจจุบันและก่อนหน้า ดูการจัดการข้อมูล Postback หมายเหตุ เฉพาะตัวควบคุมที่ทำให้เกิดเหตุการณ์การเปลี่ยนแปลง postback เท่านั้นที่เข้าร่วมในระยะนี้ | วิธีการ RaisePostDataChangedEvent (ถ้ามีการใช้งาน IPostBackDataHandler) |
จะจัดการเหตุการณ์ postback | โดยจะจัดการเหตุการณ์ของไคลเอ็นต์ที่ทำให้เกิดการ postbacks และเพิ่มเหตุการณ์ที่เหมาะสมบนเซิร์ฟเวอร์ ดูการจับภาพเหตุการณ์ Postback หมายเหตุ เฉพาะตัวควบคุมที่จัดการเหตุการณ์ postback เท่านั้นที่เข้าร่วมในระยะนี้ | เมธอด RaisePostBackEvent (ถ้ามีการใช้งาน IPostBackEventHandler) |
พรีเรนเดอร์ | จะดำเนินการอัพเดตใดๆ ก่อนที่จะเรนเดอร์เอาท์พุต การเปลี่ยนแปลงสถานะของตัวควบคุมในระหว่างขั้นตอนการเรนเดอร์ล่วงหน้าสามารถบันทึกได้ ในขณะที่การเปลี่ยนแปลงที่ทำระหว่างเฟสการเรนเดอร์จะสูญหายไป ดูการจัดการเหตุการณ์ที่สืบทอดมา | เหตุการณ์ PreRender (วิธี OnPreRender) |
จะบันทึกสถานะ | หลังจากระยะนี้ โดยคงคุณสมบัติ ViewState ของตัวควบคุมไว้ในวัตถุสตริงโดยอัตโนมัติ วัตถุสตริงนี้ถูกส่งไปยังไคลเอนต์และกลับมาเป็นตัวแปรที่ซ่อนอยู่ เพื่อปรับปรุงประสิทธิภาพ การควบคุมสามารถแทนที่เมธอด SaveViewState เพื่อแก้ไขคุณสมบัติ ViewState ดูการรักษาสถานะในการควบคุม | เมธอด SaveViewState |
แสดง | ผลผลลัพธ์ที่นำเสนอต่อไคลเอนต์ ดูการเรนเดอร์การควบคุมเซิร์ฟเวอร์ ASP.NET | วิธีการเรนเดอร์ |
จัดการ | การดำเนินการล้างข้อมูลขั้นสุดท้ายทั้งหมดก่อนที่จะทำลายตัวควบคุม การอ้างอิงถึงทรัพยากรที่มีราคาแพง เช่น ลิงก์ฐานข้อมูล จะต้องเผยแพร่ในขั้นตอนนี้ ดูวิธีการในการควบคุมเซิร์ฟเวอร์ ASP.NET | วิธีการกำจัด |
จะถ่าย | การดำเนินการล้างข้อมูลขั้นสุดท้ายทั้งหมดก่อนที่จะทำลายตัวควบคุม ผู้เขียนควบคุมมักจะดำเนินการล้างข้อมูลในการกำจัดโดยไม่ต้องจัดการเหตุการณ์นี้ | เหตุการณ์ UnLoad (บนวิธี UnLoad) |
จากตารางนี้ เราจะเห็นวิธีการเรียกและเวลาทริกเกอร์ของเพจตั้งแต่การโหลดจนถึงการยกเลิกการโหลดได้อย่างชัดเจน ต่อไปเราจะวิเคราะห์เชิงลึก
หลังจากดูตารางด้านบนแล้ว เพื่อนที่ใส่ใจอาจถาม เนื่องจาก OnInit เป็นจุดเริ่มต้นของวงจรชีวิตของหน้า และเราพูดถึงการควบคุมที่ถูกสร้างขึ้นในคลาสย่อยในการบรรยายครั้งก่อน ในที่นี้เราใช้วิธี InitializeComponent Fields ที่ประกาศในคลาสพาเรนต์ สามารถใช้งานได้แล้ว หมายความว่าคลาสย่อยถูกเตรียมใช้งานก่อนหน้านี้ใช่หรือไม่
ในหัวข้อที่สาม เราได้กล่าวถึงว่า ProcessRequest ของคลาสเพจเป็นจุดเริ่มต้นของรอบการประกาศเพจตามความหมายที่แท้จริง วิธีการนี้ถูกเรียกโดย HttpApplication (วิธีการเรียกนั้นซับซ้อนกว่า และฉันจะมีโอกาสเขียน a แยกบทความมาอธิบาย) การประมวลผลคำขอเริ่มต้นจากวิธีนี้ โดยการแยกไลบรารีคลาส .Net เพื่อดูซอร์สโค้ด เราพบคลาสพื้นฐานของ System.Web.WebControls.Page: System.Web WebControls.TemplateControl (เป็นเพจและการควบคุมผู้ใช้ A วิธีการเสมือน "FrameworkInitialize" ถูกกำหนดไว้ในคลาสพื้นฐาน) จากนั้นเมธอดนี้จะถูกเรียกครั้งแรกใน ProcessRequest ของเพจ เราพบร่องรอยของเมธอดนี้ในซอร์สโค้ด ASPX สร้างโดยตัวสร้าง การควบคุมทั้งหมดอยู่ในนั้นเริ่มต้นได้ในวิธีนี้และโครงสร้างการควบคุมของเพจจะถูกสร้างขึ้นในเวลานี้
สิ่งต่อไปคือเรื่องง่ายๆ เรามาค่อยๆ วิเคราะห์แต่ละรายการของวงจรชีวิตของเพจกัน:
1. การเริ่มต้น
การเริ่มต้นสอดคล้องกับเหตุการณ์ Init และวิธีการ OnInit ของเพจ
หากคุณต้องการเขียนใหม่ MSDN แนะนำให้โอเวอร์โหลดเมธอด OnInti แทนที่จะเพิ่มพรอกซีสำหรับเหตุการณ์ Init มีความแตกต่างระหว่างทั้งสอง หลังสามารถใช้ได้ในคลาสพาเรนต์เท่านั้น ดำเนินการหลังจาก OnInit (จริง ๆ แล้วเรียกว่าใน OnInit)
2. กำลังโหลดสถานะมุมมอง
นี่เป็นวิธีการที่สำคัญกว่า เรารู้ว่าแต่ละคำขอได้รับการประมวลผลโดยอินสแตนซ์คลาสเพจที่แตกต่างกัน เพื่อให้แน่ใจว่าสถานะระหว่างสองคำขอ ASP.Net ใช้ ViewState
วิธีการ LoadViewState รับสถานะสุดท้ายจาก ViewState และใช้การเรียกซ้ำเพื่อสำรวจแผนผังทั้งหมดตามโครงสร้างของแผนผังควบคุมบนเพจเพื่อคืนค่าสถานะที่สอดคล้องกันให้กับแต่ละตัวควบคุม
3. การประมวลผลข้อมูล postback
วิธีการนี้ใช้เพื่อตรวจสอบว่าสถานะของข้อมูลควบคุมที่ไคลเอ็นต์ส่งกลับมีการเปลี่ยนแปลงหรือไม่ ต้นแบบของวิธีการ:
LoadPostData เสมือนสาธารณะ (สตริง postDataKey, NameValueCollection postCollection)
postDataKey คือคีย์เวิร์ดที่ระบุตัวควบคุม (นั่นคือคีย์ใน postCollection) postCollection คือคอลเลกชันที่มีข้อมูล postback เราสามารถแทนที่วิธีนี้แล้วตรวจสอบได้ การส่งคืน ไม่ว่าข้อมูลที่ส่งจะมีการเปลี่ยนแปลงหรือไม่ หากเป็นเช่นนั้น จะส่งคืน True "LoadPostData ส่งคืน true หากสถานะการควบคุมเปลี่ยนแปลงเนื่องจาก postback มิฉะนั้นจะส่งคืน false กรอบงานเพจติดตามการควบคุมทั้งหมดที่ส่งคืน True และเรียก RaisePostDataChangedEvent บนตัวควบคุมเหล่านี้ . "(คัดลอกมาจาก MSDN)
วิธีการนี้กำหนดไว้ใน System.Web.WebControls.Control และยังเป็นวิธีการที่การควบคุมแบบกำหนดเองทั้งหมดที่ต้องจัดการเหตุการณ์จำเป็นต้องจัดการ สำหรับเพจที่เรากำลังพูดถึงในวันนี้ คุณสามารถทิ้งไว้ได้ ตามลำพัง.
4. การโหลด
สอดคล้องกับเหตุการณ์ Load และวิธี OnLoad ฉันเชื่อว่าเพื่อนส่วนใหญ่จะคุ้นเคยกับเหตุการณ์นี้ วิธี Page_Load ในเพจที่สร้างโดย VS.Net เป็นวิธีการตอบสนองต่อเหตุการณ์ Load เหตุการณ์จะถูกทริกเกอร์ วิธี Page_Load จะถูกดำเนินการด้วย ฉันเชื่อว่านี่เป็นขั้นตอนแรกสำหรับคนส่วนใหญ่ที่จะเข้าใจ ASP.Net
เมธอด Page_Load ตอบสนองต่อเหตุการณ์ Load ซึ่งถูกกำหนดไว้ในคลาส System.Web.WebControl.Control (คลาสนี้เป็นบรรพบุรุษของเพจและตัวควบคุมเซิร์ฟเวอร์ทั้งหมด) และถูกทริกเกอร์ในเมธอด OnLoad
หลายๆ คนอาจเคยเจอเหตุการณ์แบบนี้ พวกเขาเขียนคลาส PageBase แล้วตรวจสอบข้อมูลผู้ใช้ใน Page_Load ปรากฎว่าไม่ว่าการยืนยันจะสำเร็จหรือไม่ก็ตาม Page_Load ของเพจคลาสย่อยจะถูกดำเนินการก่อนเสมอ ในครั้งนี้ ข้อมูลบางส่วนอาจถูกทิ้งไว้ เนื่องจากเป็นความเสี่ยงด้านความปลอดภัย ผู้ใช้อาจดำเนินการวิธี Page_Load ในคลาสย่อยโดยไม่ต้องมีการรับรองความถูกต้อง
สาเหตุของปัญหานี้ง่ายมาก เนื่องจากวิธี Page_Load ถูกเพิ่มลงในเหตุการณ์ Load ใน OnInit และวิธีการ OnInit ของคลาสย่อยจะเพิ่มเหตุการณ์ Load ก่อน จากนั้นจึงเรียก base.OnInit ซึ่งทำให้คลาสย่อย Page_Load ถูกเพิ่มก่อน จากนั้นจึงดำเนินการก่อน
การแก้ปัญหานี้ทำได้ง่ายมากเช่นกัน มีสองวิธี:
1) โอเวอร์โหลดวิธี OnLoad ใน PageBase จากนั้นตรวจสอบสิทธิ์ผู้ใช้ใน OnLoad จากนั้นเรียก base.OnLoad เนื่องจากเหตุการณ์ Load ถูกทริกเกอร์ใน OnLoad ดังนั้นเราจึงสามารถ ตรวจสอบให้แน่ใจว่าได้ตรวจสอบสิทธิ์ผู้ใช้ก่อนเริ่มการทำงานของเหตุการณ์โหลด
2) First call base.OnInit ในเมธอด OnInit ของคลาสย่อยเพื่อให้แน่ใจว่าคลาสพาเรนต์ดำเนินการ Page_Load ก่อน
5. ส่งการแจ้งเตือนการเปลี่ยนแปลง postback
วิธีการนี้สอดคล้องกับการประมวลผลข้อมูล postback ในขั้นตอนที่ 3 หากมีการประมวลผลข้อมูล postback , คืนค่า True กรอบงานเพจจะเรียกใช้เมธอดนี้เพื่อทริกเกอร์เหตุการณ์การเปลี่ยนแปลงข้อมูล ดังนั้นจึงต้องทริกเกอร์เหตุการณ์การเปลี่ยนแปลงข้อมูล postback ของการควบคุมแบบกำหนดเองในเมธอดนี้
ในทำนองเดียวกัน วิธีการนี้ไม่มีประโยชน์มากนักสำหรับเพจ แน่นอนว่า คุณสามารถกำหนดเหตุการณ์การเปลี่ยนแปลงข้อมูลตามเพจได้
6. จัดการเหตุการณ์ postback
วิธีนี้เป็นที่ที่เหตุการณ์การควบคุมเซิร์ฟเวอร์ส่วนใหญ่ถูกทริกเกอร์ เมื่อคำขอมีข้อมูลเกี่ยวกับทริกเกอร์เหตุการณ์การควบคุม (เหตุการณ์ของการควบคุมเซิร์ฟเวอร์เป็นหัวข้ออื่น ฉันจะเขียนบทความอื่นเพื่อหารือในอนาคตอันใกล้นี้) การควบคุมหน้า วิธีการ RaisePostBackEvent ของตัวควบคุมที่เกี่ยวข้องจะถูกเรียกเพื่อทริกเกอร์เหตุการณ์ฝั่งเซิร์ฟเวอร์
คำถามทั่วไปอีกข้อหนึ่งเกิดขึ้น:
ชาวเน็ตมักถามว่าทำไมข้อมูลที่ส่งมาจึงไม่เปลี่ยนแปลงหลังจากการแก้ไข
ในกรณีส่วนใหญ่ พวกเขาไม่เข้าใจกระบวนการกระตุ้นของเหตุการณ์เซิร์ฟเวอร์ เราจะเห็นว่าเหตุการณ์เซิร์ฟเวอร์ถูกทริกเกอร์หลังจากโหลดเพจ กล่าวคือ เพจจะดำเนินการ Page_Load ก่อน จากนั้นจึงดำเนินการเหตุการณ์การคลิกของปุ่ม (นี่คือปุ่มเป็นตัวอย่าง) เพื่อนหลายคนผูกข้อมูลใน Page_Load แล้วจึงประมวลผลการเปลี่ยนแปลงในเหตุการณ์ของปุ่มที่นั่น เป็นปัญหาในเรื่องนี้ Page_Load จะถูกดำเนินการก่อนเหตุการณ์ปุ่มเสมอ ซึ่งหมายความว่าก่อนที่ข้อมูลจะมีการเปลี่ยนแปลง รหัสการเชื่อมโยงข้อมูลใน Page_Load จะถูกดำเนินการก่อน และข้อมูลต้นฉบับจะถูกกำหนดให้กับตัวควบคุม จากนั้นเมื่อ เหตุการณ์ของปุ่มถูกดำเนินการ สิ่งที่ได้รับจริงคือข้อมูลดั้งเดิม ดังนั้นการอัปเดตจะไม่มีผลกระทบอย่างแน่นอน
นอกจากนี้ยังง่ายมากที่จะเปลี่ยนปัญหานี้ แนวทางที่สมเหตุสมผลกว่าคือการเขียนโค้ดการเชื่อมโยงข้อมูลลงในวิธีการ สมมติว่าเป็น BindData:
private void BindData()
-
//ผูกข้อมูล
}
จากนั้นแก้ไข PageLoad:
โมฆะส่วนตัว Page_Load( ผู้ส่งวัตถุ,EventArgs e)
-
ถ้า(!IsPostBack)
-
BindData(); //ผูกข้อมูลเมื่อเข้าถึงเพจเป็นครั้งแรก}
}
สุดท้ายในเหตุการณ์ปุ่ม:
ส่วนตัว Button1_Click( ผู้ส่งวัตถุ,EventArgs e )
-
//อัพเดต dataBindData();//เชื่อมโยงข้อมูลใหม่
}
7.
การประมวลผลคำขอขั้นสุดท้ายสำหรับการเรนเดอร์ล่วงหน้าจะถูกแปลงเป็นการตอบกลับที่ส่งกลับไปยังเซิร์ฟเวอร์ ขั้นตอนการเรนเดอร์ล่วงหน้าคือการดำเนินการเปลี่ยนแปลงสถานะที่เกิดขึ้นก่อนการเรนเดอร์ครั้งสุดท้าย เนื่องจากก่อนเรนเดอร์การควบคุม เราจะต้อง สร้าง Html ตามคุณสมบัติ เช่น คุณลักษณะ Style ซึ่งเป็นตัวอย่างทั่วไปที่สุด ก่อนการเรนเดอร์ล่วงหน้า เราสามารถเปลี่ยนสไตล์ของคอนโทรลได้ เมื่อดำเนินการเรนเดอร์ล่วงหน้า เราสามารถบันทึกสไตล์และแสดง Html ได้ ข้อมูลสไตล์เป็นขั้นตอนการเรนเดอร์
8. บันทึกสถานะ
ขั้นตอนนี้มีไว้สำหรับสถานะการโหลด เราได้กล่าวไว้หลายครั้งว่ามีการประมวลผลอินสแตนซ์ที่แตกต่างกันระหว่างคำขอ ดังนั้น เราจำเป็นต้องบันทึกสถานะของหน้านี้และขั้นตอนการควบคุม .
9. ณ
จุดนี้ การประมวลผลคำขอของเพจได้สิ้นสุดลงแล้ว ในวิธีการ Render แผนผังการควบคุมของทั้งหน้าจะถูกเรียกซ้ำ วิธีการ Render จะถูกเรียกตามลำดับ และโค้ด Html ที่เกี่ยวข้องจะถูกเขียน เข้าสู่กระแสตอบรับครั้งสุดท้าย
10.
จริงๆ แล้วการกำจัดเป็นวิธีการกำจัด ในขั้นตอนนี้ ทรัพยากรที่ถูกครอบครอง เช่น การเชื่อมต่อฐานข้อมูล จะถูกปล่อยออกมา
11.
เมื่อสิ้นสุดการขนถ่าย เพจจะดำเนินการเมธอด OnUnLoad เพื่อทริกเกอร์เหตุการณ์ UnLoad ซึ่งจัดการการประมวลผลขั้นสุดท้ายก่อนที่ออบเจ็กต์เพจจะถูกทำลาย ที่จริงแล้ว ASP.Net ให้เหตุการณ์นี้สำหรับการพิจารณาการออกแบบเท่านั้น ของทรัพยากรเสร็จสิ้นในวิธี Dispose ดังนั้นวิธีนี้จึงไร้ประโยชน์
เราได้แนะนำวงจรชีวิตของเพจโดยย่อ และให้คำอธิบายเชิงลึกน้อยลงเกี่ยวกับการประมวลผลเหตุการณ์ฝั่งเซิร์ฟเวอร์ วันนี้ฉันอยากให้ทุกคนเข้าใจวงจรของการดำเนินการเพจเป็นหลัก ฉันจะเขียนเพิ่มเติมเกี่ยวกับเหตุการณ์และอายุการใช้งาน ของการควบคุมเซิร์ฟเวอร์ในอนาคตบทความที่จะหารือ
เนื้อหาเหล่านี้เป็นประสบการณ์บางส่วนของฉันในการค้นคว้าเพจเมื่อฉันเรียนรู้ ASP.Net รายละเอียดเฉพาะไม่ได้กล่าวถึงในรายละเอียด โปรดดูที่ MSDN สำหรับข้อมูลเพิ่มเติม แต่ฉันได้อ้างถึงข้อผิดพลาดและข้อผิดพลาดทั่วไปบางประการที่ทำโดยผู้เริ่มต้น ฉันหวังว่าจะสามารถนำแรงบันดาลใจมาสู่ทุกคนได้