บทความนี้จะสอนให้ท่านเข้าใจวิธีทำงานของคอนโทรลเลอร์ใน MVC Framework รวมถึงกลไกการตัดสินใจเลือกเส้นทาง (routing rule) หลังจากที่คอนโทรลเลอร์ได้รับ HTTP request เข้ามา ผมจะใช้โปรเจ็กต์เว็บแอพพลิเคชัน ASP.NET MVC ที่สร้างขึ้นในตอนที่ 1 เพื่อประกอบการอธิบายนะครับ
ย้อนกลับไปดูไดอะแกรม Model-View-Controller คำถามคือ ASP.NET รู้ได้อย่างไรว่าจะต้องนำรีเควสต์อย่าง /home/about ไปยังคอนโทรลเลอร์ชื่อ HomeController? คำตอบอยู่ในตัว routing engine หมดแล้ว
routing engine เป็นส่วนประกอบแกนหลักของ ASP.NET ไม่ได้ผูกกับ MVC Framework โดยตรง ท่านอาจใช้ routing engine หาเส้นทางเดินของรีเควสต์ให้กับ web form หรือ WCF service ก็ได้ แต่ในกรณี MVC เราจะใช้ routing engine นำรีเควสต์ไปยังคอนโทรลเลอร์ที่ถูกต้องตามที่ระบุไว้ในแผนที่นำทาง (route map)
ตอนนี้ให้รันโปรแกรม Visual Studio เปิดโปรเจ็กต์ที่ทำค้างในบทความตอนที่ 3 และเปิดไฟล์ Global.asax.cs เวลาแอพพลิเคชันเริ่มต้นทำงาน โค้ดภายในเมธอด Application_Start() จะถูกเอ็กซิคิวต์หนึ่งครั้งก่อนที่คอนโทรลเลอร์ตัวใดตัวหนึ่งจะเอ็กซิคิวต์เสมอ และเป็นบริเวณที่เราจะตั้งค่าคอนฟิกูเรชันที่จำเป็น เช่น routing configuration (ดู RouteConfig) ที่มีการรับค่า global routing table หรือตารางเก็บเส้นทางฯ ทั้งหมดของแอพพลิเคชันเข้าไป
แรกสุดตาราง global routing table จะว่างเปล่า แต่พอเรียกใช้เมธอด RegisterRoutes จะมีการเพิ่มเอ็นทรีต่างๆ เข้าไปในตารางนี้ หากเลื่อนเมาส์ไปคลิกขวาที่ RegisterRoutes > Go To Definition (หรือกดแป้น F12) โปรแกรม Visual Studio ก็จะเปิดไฟล์ App_Start\RouteConfig.cs ขึ้นมา
โปรแกรม Visual Studio สร้างไฟล์ RouteConfig.cs ให้เราอัตโนมัติตอนสร้างโปรเจ็กต์ สิ่งที่ต่างจาก ASP.NET MVC เวอร์ชันก่อนๆ คือโค้ดสตาร์ทอัพที่เคยกระจุกรวมอยู่ใน Global.asax.cs ตอนนี้จะได้รับการซอยออกเป็นคลาสย่อยๆ เก็บไว้ในโฟลเดอร์ App_Start คลาสทั้งหมดนี้จะถูกเรียกใช้โดยเมธอด Application_Start() ใน Global.asax.cs
ตามที่ทราบดีว่า หน้าที่ของเราติงเอ็นจิ้นคือพิจารณา URL ที่ผู้ใช้ป้อนเข้ามาและตัดสินใจว่าจะส่งรีเควสต์ไปที่ไหนต่อเพื่อประมวลผล ซึ่งในแอพพลิเคชัน MVC เราต้องการ URL เพื่อระบุคอนโทรลเลอร์ที่จะส่งต่อ และแอ็กชั่นที่จะกระตุ้นให้ทำงานต่อ
ดังนั้นจึงมีการระบุ URL pattern ในไฟล์ RouteConfig.cs เพื่อให้เราติงเอ็นจิ้นรู้จัก URL pattern ที่สามารถใช้พิจารณาและค้นหาพารามิเตอร์ที่อยู่ใน URL นั้นๆ กล่าวคือ คำที่อยู่ข้างในเครื่องหมายปีกกาจะเป็นชื่อพารามิเตอร์ หากเราติงเอ็นจิ้นไม่สามารถค้นหาข้อมูลบางชิ้นจาก URL ได้ เช่น ชื่อคอนโทรลเลอร์ หรือชื่อแอ็กชั่น เราติงเอ็นจิ้นก็จะหันไปหยิบข้อมูลเหล่านี้จาก default parameter แทน
สมมติผู้ใช้ป้อน /Home/Index ในเว็บบราวเซอร์ กรณีนี้ เราติงเอ็นจิ้นจะมอง Home เป็นชื่อคอนโทรลเลอร์ มอง Index เป็นชื่อแอ็กชั่น แต่ไม่มี id ปรากฎอยู่ใน URL ไม่เป็นไรครับ เพราะเราได้มีการระบุค่าดีฟอลต์ไว้แล้วใน route map หรือหากผู้ใช้ป้อนแค่ /Home ถึงจะไม่มีชื่อแอ็กชั่นใน URL แต่เราติงเอ็นจิ้นก็จะเลือกแอ็กชั่นจากค่าดีฟอลต์นั่นคือ Index
เมื่อเราติงเอ็นจิ้นแยก URL ออกเป็นชิ้นๆ มันจะสร้างโครงสร้างชั้นข้อมูล (data structure) ขึ้นเพื่อส่งไปยัง MVC framework จากนั้นเฟรมเวิร์กจะพิจารณาโครงสร้างชั้นข้อมูลฯ เพื่อดูว่าอะไรคือคอนโทรลเลอร์ อะไรคือแอ็กชั่น แล้วใช้ข้อมูลตรงนี้เพื่อนำรีเควสต์ไปสู่คอนโทรลเลอร์ เช่น HomeController เป็นต้น ลองสลับไปเปิด/แก้ไขไฟล์ Controllers/HomeController.cs เพื่อดูว่าเราจะ track ข้อมูลเหล่านี้ได้อย่างไรบ้าง ผมต้องการพิสูจน์ว่าเว็บบราวเซอร์เปิดหน้า Index ขึ้นมาได้นั้นเป็นผลจากคอนโทรลเลอร์ตัวไหน แอ็กชั่นอะไร ก็ต้องไปขอพึ่งข้อมูลจากโครงสร้างชั้นข้อมูล RouteData ที่สร้างโดยเราติงเอ็นจิ้น ซึ่งทำได้โดยการแก้โค้ดดังรูป แล้วรันแอพพลิเคชัน:
คราวนี้ ลองพิมพ์ URL เป็น http://localhost:{เลขพอร์ตที่ท่านใช้}/Home หรือ http://localhost: {เลขพอร์ตที่ท่านใช้}/Home/Index ก็ยังได้หน้าตาเหมือนเดิม แต่พอพิมพ์เป็น http://localhost: {เลขพอร์ตที่ท่านใช้}/Home/Index/256 จะได้หน้าจอเช่นนี้:
ถึงจุดนี้ ผมเพียงต้องการแสดงให้เห็นว่า เราติงเอ็นจิ้นมีหน้าที่แยก URL ออกเป็นส่วนๆ แล้วสร้างโครงสร้างชั้นข้อมูลที่ไม่เพียงให้ MVC framework มองเห็นเพื่อตัดสินใจเลือกเส้นทางเท่านั้น แต่เราเองก็สามารถมองเห็นได้ โดยข้อมูลเส้นทาง (route data) สามารถมีอยู่ในคอนโทรลเลอร์ก็ได้ อยู่ในวิวก็ได้ แต่ปกติ โค้ดที่เราเขียนกันจะไม่ปฏิบัติต่อข้อมูลเส้นทางแบบในตัวอย่างนี้ แต่เป็นหน้าที่ของ MVC framework ที่จะใช้ข้อมูลเพื่อค้นหาคอนโทรลเลอร์ที่เหมาะสม บทความตอนต่อไปจะสอนวิธีสร้างคอนโทรลเลอร์ขึ้นใช้เอง รวมถึงการสร้างแอ็กชั่นและเรียกใช้พารามิเตอร์ต่างๆ โปรดติดตามครับ