วันพุธที่ ๒๔ ตุลาคม พ.ศ. ๒๕๕๐

ASP.Net Site Navigation

เมื่อวันก่อนมีคนมาถามที่ http://www.greatfriends.biz เรื่อง Response.Redirect กับ
Server.Transfer ว่าต่างกันอย่างไร ผมเห็นเรื่องนี้มีถามกันบ่อยพอสมควร แม้แต่ใน webboard
ต่างประเทศก็มีถามกันบ่อยๆ เลยถือโอกาสนี้เอามาลงบล๊อกซะเลยครับ

เรื่องนี้ถือว่าเป็นเรื่องสำคัญเรื่องหนึ่ง จนหนังสือ
MCTS 70-528
Microsoft .Net Framework 2.0 Web-based Client Development Book
เขียนเป็นหัวข้อสำคัญบทหนึ่งทีเดียว นั่นคือเรื่อง Site Navigation ในหนังสือกล่าวว่า การทำ Navigate Pages หรือการเปลี่ยนหน้า
page นั้นสามารถทำได้ 4 วิธีครับ ได้แก่

1. สร้าง client-side code หรือ markup สำหรับ request page ใหม่
2. ทำ Cross-page
3. สั่ง client-side browser redirect
4. สั่ง server-side transfer

สำหรับวิธีที่1 ได้แก่การเขียนคำสั่ง javascript เช่น

<script language="javascript" type="text/jscript">
function Button1_OnClick(){
document="Page2.aspx";
}
</script>

หรือจะกำหนดที่ tag ของ Control ก็ได้ เช่น
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/test.aspx">HyperLink<asp:HyperLink>

สำหรับวิธีที่2 การทำ Cross-paging หมายถึงการที่มีการใส่ข้อมูลที่
page ที่หนึ่ง และทำการ process ข้อมูลที่ page ที่สอง ซึ่งในกรณีนี้ page ที่สองจะมี
property ชื่อ ProviousPage สำหรับเก็บ object ของ page ที่หนึ่ง เพื่อที่ page
ที่สองจะสามารถเข้าถึง property และ object ต่างๆใน page ที่หนึ่งได้ เช่นการไปเอาข้อมูลจาก
web control เป็นต้น


การทำ Cross-paging ได้แก่การกำหนด PostbackURL เพื่อไปเรียกใช้ page ปลายทางเช่น

<asp:LinkButton ID="LinkButton1" runat="server" PostBackUrl="test.aspx"> LinkButton
asp:LinkButton>

สำหรับวิธีที่ 3 ก็คือการสั่ง Response.Redirect นั่นเอง ตามชื่อหัวข้อ
client-side browser redirect ก็บอกอยู่แล้วครับ ว่าเป็นวิธีที่เกิดขึ้นที่ client-side
หรือ browser นั่นเอง การทำงานวิธีนี้ก็คือ เมื่อเราเขียนโค้ด Response.Redirect ที่
Server-side script ทาง Web Server ซึ่งก็คือ IIS จะทำการส่ง response กลับไปยัง browser
ซึ่งจะระบุ location ของ page ใหม่ไปให้ เมื่อ browser ได้รับ response แล้ว browser
ที่สนับสนุน Redirect (ซึ่งก็ทุกยี่ห้อนั่นแหละ) จะทำการส่ง Request กลับมาที่ Web Server
เพื่อขอข้อมูลของ page ใหม่ที่ต้องการ ทาง Web Server ก็จะ process แล้วส่ง response
ซึ่งก็คือ Page ใหม่ไปให้ ดังนั้นเราจะเห็นได้ว่าวิธีนี้จะเกิด round-trip คือจะมีการรับส่ง
request-response ระหว่าง browser กับ Web Server หลายเที่ยว ทำให้กิน resource ของ network


ทีนี้เราลองมาดูคำสั่ง Response.Redirect จะพบว่ามันมี 2 overload ครับ
คือ

Response.Redirect(url As String) กับ

Response.Redirect(url As String, endResponse as Boolean)

โดย default ถ้าเราไม่กำหนด endResponse มันจะมีค่าเป็น false ครับ หมายความว่าทาง
Web Server จะต้องทำการ Process Response รวมถึงงานต่างๆให้เสร็จก่อน ถึงจะส่ง Reponse.Redirect
กลับไปยัง Server ถ้าเรากำหนดเป็น True ทาง Web Server จะทำการยกเลิกงานอื่นๆทันที หมายความว่าโค้ดใดๆก็ตามที่คุณเขียนหลังบรรทัดนี้จะไม่ถูก
process ครับ Web Server จะส่ง Response กลับไปที่ Browser ทันที

ทีนี้การใช้ Response.Redirect มีจุดหนึ่งที่ต้องระวังครับ คือ ปกติการส่ง
Response กลับไปยัง browser นอกจากคำสั่ง redirect แล้วยังอาจจะมีข้อมูลอื่นๆส่งไปด้วย
ดังนั้นถ้ามี data อื่นๆส่งไปแล้ว browser ทำการ process ก่อนที่จะทำการ redirect จะทำให้เกิด
HttpException ทันที (แม้แต่ส่ง HTTP header ไปก็ไม่ได้ครับ) เพื่อป้องกันการเกิด Error
เราจึงควรกำหนด Response.BufferOutput เป็น True ไว้ด้วยครับ

Response.BufferOutput = True

Response.Redirect("test2.aspx")


สำหรับกรณีที่คุณใช้ MS Ajax เพื่อไม่ให้เกิด Exception คุณต้องกำหนด
endResponse เป็น True ไปด้วยเสมอ เพื่อให้แน่ใจว่า WebServer ส่งแค่ Redirect อย่างเดียวไม่ส่ง
data อย่างอื่นพ่วงไปด้วยครับ


Response.BufferOutput = True

Response.Redirect("test2.aspx", True)

เมื่อ Response.Redirect ทำงานเสร็จสมบูรณ์ Web Server จะส่ง Response code
302 ไปให้ browser พร้อมทั้ง URL ของ page ใหม่ ดังนั้นที่ browser ตรงช่อง address
คุณจะเห็น URL ของ page เปลี่ยนไปเป็น page ปัจจุบัน

การที่คุณใช้ Response.Redirect คุณจะไม่สามารถใช้ Previous Page Property ได้ครับ

สำหรับวิธีที่ 4 ก็คือการสั่ง Server.Transfer
การใช้ Server.Transfer จะต่างจากการใช้ Response.Redirect เนื่องจาก
Server.Transfer จะเป็นการทำงานที่ Web Server คือเมื่อมีการ Postback กลับมาที่ Web
Server แล้ว ทาง Web Server จะทำการ process งานตามลำดับจนเมื่อเจอคำสั่ง Server.Transfer
แล้ว Web Server จะทำการไปเรียกใช้งาน Page ใหม่ทันที ดังนั้นข้อดีก็คือจะไม่มี round-trip
เกิดขึ้น เป็นการประหยัด network traffic ไปในตัวครับ
แต่มีข้อเสียคือ
Server.Transfer สามารถสั่งเรียก page เฉพาะใน Server เท่านั้น ไม่สามารถ Transfer ไปที่
Web Server ตัวอื่นได้ (ไม่เหมือน Response.Redirect คุณสามารถ redirect ไปที่ web ไหนก็ได้
server ตัวไหนก็ได้ครับ)


คำสั่ง Server.Transfer ก็มี 3 overload เหมือนกันครับ ลองไปศึกษาเพิ่มเอง
แต่มี parameter ตัวหนึ่งน่าสนใจคือ preserveForm ถ้าคุณกำหนดเป็น True ค่าของ page แรกจะถูกเก็บไว้ใน PreviousPage Property ของ Page ปลายทางครับ นั่นคือมันจะทำ Cross-paging ให้ด้วยในตัว
ดังนั้นที่ page ปลายทาง คุณสามารถสั่ง
PreviousPage.FindControl
เพื่อไป get control ของ Page แรกได้ครับ

1 ความคิดเห็น:

oO Nuch Oo กล่าวว่า...

ขอบคุณค่ะ พี่หนึ่ง (พี่จวบ) บทความอ่านแล้วเข้าใจเลยค่ะ แบบไม่มีข้อสงสัย และตอบโจทย์ ที่เคยพบปัญหามา...นุชค่ะ