หากคุณมีนิสัยชอบดูซอร์สโค้ด HTML ของหน้าปัจจุบันที่คุณกำลังเรียกดูใน IE คุณมักจะเห็นข้อมูลโค้ดที่คล้ายกับต่อไปนี้:
<ประเภทอินพุต = "ซ่อน" ชื่อ = "__VIEWSTATE" value = "dDwtMzU5NzUyMTQ1O3Q8O2w8aTwwPjs+O2w8dDw7bDxpPDA+Oz47bDx0PDtsPG
...
ถ้าฉลาดคงถามแน่ว่านี่คืออะไร? มันทำอะไร? เกี่ยวข้องกับบทความนี้อย่างไร? นักอ่านที่รัก โปรดฟังฉันช้าๆ
อันที่จริงนี่คือประสิทธิภาพที่เป็นลักษณะเฉพาะของการประยุกต์ใช้เทคโนโลยี ViewState ของ MS ใน Asp.net เพื่อให้เพจยังคงสามารถอ่านข้อมูลสถานะดั้งเดิมของการควบคุมเซิร์ฟเวอร์หลังจาก PostBack นั้น Asp.net ใช้เทคโนโลยี ViewState ซึ่งโดยพื้นฐานแล้วจะใช้ฟิลด์แบบฟอร์มประเภทที่ซ่อนอยู่พร้อมชื่อเริ่มต้นของ "__VIEWSTATE" เพื่อบันทึกและถ่ายโอนข้อมูล (ข้อมูลเหล่านี้เป็นค่าสตริงที่เข้ารหัส Base64 และบันทึกไว้ก่อนเอาต์พุตโดยวิธี Page.SavePageStateToPersistenceMedium และโหลดโดย Page.LoadPageStateFromPersistenceMedium) แม้ว่าเราจะสามารถปิดใช้งานการเดินทางไปกลับของข้อมูลเหล่านี้ได้อย่างง่ายดายผ่านสามระดับ ผ่าน:
ชุดระดับเครื่อง <เพจ EnableViewStateMac='false' /> ใน machine.config
ที่ระดับแอปพลิเคชัน ให้ตั้งค่า
ที่ระดับหน้าเดียว ให้ตั้งค่า < %@Page EnableViewStateMac='false' %> ในเพจหรือตั้งค่า Page.EnableViewStateMac = false ผ่านโค้ด
อย่างไรก็ตาม หากเราสามารถแก้ไขภาระการรับส่งข้อมูลได้อย่างสมบูรณ์ด้วยการปิดการใช้งาน ViewState โดยไม่ก่อให้เกิดผลข้างเคียง สถาปนิก MS ก็จะไม่โง่จนน่ารักขนาดนี้ (จะทิ้งมันไว้เป็นสิ่งที่จ่ายไปจะมีประโยชน์อะไร) เพราะเรามักจะ ไม่สามารถแก้ปัญหาภาระการส่งข้อมูลนี้ได้โดยเพียงแค่ปิดการใช้งาน เราสามารถหาเส้นทางอื่นเพื่อทำให้ปริมาณการส่งข้อมูลในเครือข่ายไปกลับมีขนาดเล็กที่สุดเท่าที่จะเป็นไปได้ ดังนั้นการบีบอัดจึงกลายเป็นตัวเลือกแรกของเรา ตราบใดที่เราโอเวอร์โหลดเมธอด SavePageStateToPersistenceMedium() และเมธอด LoadPageStateFromPersistenceMedium() ของคลาส Page และบีบอัดและขยายข้อมูลในเมธอดโอเวอร์โหลด คลาส GZipInputStream และ GZipOutputStream จัดทำโดยโครงการโอเพ่นซอร์ส SharpZipLib รวมอยู่ในมุมมองของเรา เพื่อความสะดวก เราอาจเขียนคลาส CompressionHelper ด้วยโค้ดต่อไปนี้:
1using System.IO;
2ใช้ ICSharpCode.SharpZipLib.GZip;
3
4namespace Ycweb.ส่วนประกอบ
5{
6 /***//// <สรุป>
7 /// คำอธิบายโดยย่อสำหรับ CompressionHelper
8 /// สรุป>
9 CompressionHelper ระดับสาธารณะ
10 {
11 publicCompressionHelper ()
12 {
13 //
14 // สิ่งที่ต้องทำ: เพิ่มตรรกะคอนสตรัคเตอร์ที่นี่
15 //
16}
17
18 /***////// <สรุป>
19 /// บีบอัดข้อมูล
20 /// สรุป>
21 /// อาร์เรย์ไบต์ที่จะบีบอัด
22 ///
23 ไบต์สาธารณะแบบคงที่ [] CompressByte (ข้อมูลไบต์ [])
ยี่สิบสี่ {
25 MemoryStream ms = MemoryStream ใหม่ ();
26 สตรีม s=gZipOutputStream ใหม่ (ms);
27 วินาทีเขียน (ข้อมูล, 0, ข้อมูลความยาว);
28 วินาที.ปิด();
29 กลับ ms.ToArray();
30}
31
32 /***//// <สรุป>
33 /// ขยายขนาดข้อมูล
34 /// สรุป>
35 /// อาร์เรย์ไบต์ที่จะขยาย
36 ///
37 ไบต์สาธารณะแบบคงที่ [] DeCompressByte (ข้อมูลไบต์ [])
38 {
39 ไบต์ [] writeData = ไบต์ใหม่ [2048];
40 MemoryStream ms= MemoryStream ใหม่ ( ข้อมูล );
41 สตรีม sm = GZipInputStream (ms) ใหม่เป็นสตรีม;
42 MemoryStream outStream = MemoryStream ใหม่();
43 ในขณะที่ (จริง)
44 {
45 ขนาด int = sm.Read(writeData,0, writeData.Length );
46 ถ้า (ขนาด >0)
47 {
48 outStream.Write (writeData, 0, ขนาด);
49 }
50 อื่น ๆ
51 {
52 แตก;
53}
54 }
55 ซม.ปิด();
56 ไบต์ [] outArr = outStream.ToArray();
57 outStream.ปิด();
58 กลับออกArr;
59 }
60 }
61} จากนั้นเราโอเวอร์โหลดเมธอด LoadPageStateFromPersistenceMedium() และ SavePageStateToPersistenceMedium(Object viewState) ในคลาสฐานการควบคุมเพจที่ได้มาจากคลาส Page รหัสจะเป็นดังนี้:
1โหลดและบันทึกข้อมูล ViewState#ภูมิภาค โหลดและบันทึกข้อมูล ViewState
2 วัตถุแทนที่การป้องกัน LoadPageStateFromPersistenceMedium ()
3 {
4//อ่านข้อมูลจากโดเมนที่ซ่อนอยู่ __SmartViewState ที่ลงทะเบียนด้วยตัวเอง
5 สตริง viewState = Request.Form["__SmartViewState"];
6 ไบต์ [] ไบต์ = Convert.FromBase64String (viewState);
7 //เรียกวิธีคงที่ CompressionHelper.DeCompressByte() ที่ให้ไว้ข้างต้นเพื่อขยายขนาดข้อมูล
8 ไบต์ = CompressionHelper.DeCompressByte (ไบต์);
9 ตัวจัดรูปแบบ LosFormatter = ใหม่ LosFormatter();
10 ส่งคืนฟอร์แมตเตอร์ดีซีเรียลไลซ์ (แปลง ToBase64String (ไบต์));
11
12}
13
14 การแทนที่การป้องกันถือเป็นโมฆะ SavePageStateToPersistenceMedium (Object viewState)
15 {
16 ตัวจัดรูปแบบ LosFormatter = ตัวจัดรูปแบบ LosFormatter ใหม่ ();
17 ตัวเขียน StringWriter = ตัวเขียน StringWriter ใหม่ ();
18 ฟอร์แมตเตอร์ซีเรียลไลซ์ (ผู้เขียน, viewState);
19 สตริง viewStateString =writer.ToString();
20 ไบต์ [] ไบต์ = Convert.FromBase64String (viewStateString);
21 //เรียกวิธีคงที่ CompressionHelper.CompressByte() ที่ให้ไว้ข้างต้นเพื่อบีบอัดข้อมูล
22 ไบต์ = CompressionHelper.CompressByte (ไบต์);
ยี่สิบสาม
24 //ลงทะเบียนฟิลด์ที่ซ่อนใหม่ __SmartViewState คุณสามารถกำหนดได้ด้วยตัวเอง
25 นี้.RegisterHiddenField("__SmartViewState", Convert.ToBase64String(bytes));
26}
27#สิ้นสุดภูมิภาค
หลังจากการประมวลผลข้างต้น ซอร์สโค้ดในหน้าเอาท์พุตของเว็บจะเป็นดังนี้:
<ประเภทอินพุต = "ซ่อน" ชื่อ = "__ SmartViewState" ค่า = "H4sIAPtPoNwA/81ce1PbWJb/ ……
<ประเภทอินพุต = "ซ่อน" ชื่อ = "__VIEWSTATE" ค่า = "" />
ฟิลด์ที่ซ่อนอยู่เดิม "__VIEWSTATE" มีค่าว่าง และถูกแทนที่ด้วยฟิลด์ที่ซ่อนอยู่ใหม่ "__SmartViewState" ที่ลงทะเบียนด้วยตัวเองเพื่อจัดเก็บสตริงที่บีบอัด ด้วยวิธีนี้ เอฟเฟกต์การเร่งความเร็วจะเห็นได้ชัดเมื่อรวมกับโปรเจ็กต์ของเรา ตัวอย่างเช่น ค่าสตริง ViewState ดั้งเดิมของหน้าแรกของ DG3G.COM คือประมาณ 28K และจะเป็น 7K หลังจากการบีบอัด ในขณะที่ค่าสตริง ViewState ดั้งเดิมของหน้าแรกของ Acafa.com อยู่ที่ประมาณ 43K และจะเป็น 8K หลังการบีบอัด การประมวลผลแบบนี้ค่อนข้างน่าพอใจ แน่นอน หากคุณรู้สึกว่ายังไม่เพียงพอ คุณสามารถจัดเก็บสตริง ViewState ไว้ในเซสชันได้ อย่างไรก็ตาม หากคุณทำเช่นนี้ ความกดดันต่อหน่วยความจำของเซิร์ฟเวอร์จะเพิ่มขึ้นอย่างรวดเร็ว (โดยเฉพาะเมื่อมีการเข้าชมจำนวนมาก) ขอแนะนำอย่าใช้เบา ๆ หากเว็บเซิร์ฟเวอร์ของคุณมีหน่วยความจำ 10G หรือ 8G คุณก็อาจลองดูก็ได้ รหัสที่แก้ไขที่เกี่ยวข้องได้รับด้านล่าง:
เปลี่ยนรหัสในเนื้อหาวิธีการ LoadPageStateFromPersistenceMedium() ด้านบน:
สตริง viewState = คำขอแบบฟอร์ม ["__SmartViewState"];
แก้ไขเป็น:
สตริง viewState = เซสชัน ["__SmartViewState"].ToString();
ในเวลาเดียวกัน ให้เพิ่มโค้ดในส่วนเนื้อหา SavePageStateToPersistenceMedium() ข้างต้น:
this.RegisterHiddenField("__SmartViewState", Convert.ToBase64String(ไบต์));
แก้ไขเป็น:
Session["__SmartViewState"] = Convert.ToBase64String(bytes);
สุดท้ายนี้ โค้ดและวิธีแก้ปัญหาข้างต้นทั้งหมดมาจากแนวปฏิบัติการพัฒนา VS2003 ฉันไม่ได้ให้คำมั่นสัญญาใด ๆ ว่า VS2005 นั้นเหมาะสมหรือไม่ วิธีแก้ปัญหาฉันจะมีความสุขมาก