ใน ASP.NET MVC เราสามารถออกแบบ URL ขึ้นมาแล้วส่ง request ไปยัง action ที่กำหนดไว้ได้ ทำให้ URL ของเว็บของเราไม่ขึ้นอยู่กับโครงสร้างของไฟล์ที่อยู่บนดิสก์จริงๆ โดย ASP.NET MVC อาศัย URL Routing ที่เพิ่มเข้ามาใน ASP.NET 3.5 SP1
หลังจากเราสร้าง Project Web Application ขึ้นมาแล้ว ลองเปิดดูที่ Global.asax จะเห็นว่าต่างจาก ASP.NET Web Application ธรรมดา เพราะจะมาการทำ Routing มาให้แล้ว
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
}
กฏง่ายๆของการ Routing คือ
- หน้าไปหลัง เริ่มทำการทดสอบจากกฏที่เพิ่มเข้าไปก่อนเป็นลำดับแรก เจออันไหนก่อนก็จะ route ไปตามนั้น
- ใช้ {} เพื่อเก็บค่าตัวแปร เราสามารถตั้งตัวแปรสำหรับ URL ได้ เช่น
/blog/{year}/{month}/{day} จะ match กับ /blog/2009/1/2 โดยจะเกิดตัวแปรของ URL ชื่อ year, month และ day ขึ้นโดยมีค่าเป็น 2009, 2 และ 1 ตามลำดับ - ใช้ * เพื่อระบุว่าเป็น parameter ที่ไม่ทราบจำนวน
ASP.NET Routing จะต้องมี Routing Handler ซึ่งจะต้องเป็นคลาสที่ implement interface IRouteHandler ซึ่งปกติใน ASP.NET MVC จะแอบใช้ System.Web.Mvc.MvcRouteHandler
จากด้านบน เราสามารถแปลได้ง่ายๆว่า
- ไม่ต้องสนใจถ้า request url ที่เป็น .axd โดยส่วนที่อยู่หน้า . จะถูกเก็บไว้ในตัวแปรชื่อ request ส่วนที่เหลือทั้งหมดจะถูกเก็บใน pathInfo
- Request URL จะถูก Route ไปยัง controller และ action โดยระบุพารามิเตอร์ชื่อ id โดยอัตโนมัติหากไม่มีการกำหนดค่าใดๆ
เรามาลองสร้าง Flickr Mashup ขึ้นมาเล่นๆดูดีกว่า
ก่อนอื่นสร้าง PhotoController ขึ้นมาใหม่ โดยมีโค้ดดังนี้
public class PhotoController : Controller
{
public ActionResult Index()
{
Flickr f = new Flickr();
Photos p = f.PhotosGetRecent(25, 1);
return View(p.PhotoCollection);
}
}
จากแอคชันข้างต้น เราดึงรายละเอียดของรูปที่ถูกอัพโหลดขึ้นไปไว้ใน Flickr จำนวน 25 รูปแล้วเก็บไว้ใน ViewData โดยมีใช้
โดยใช้ View ง่ายๆ ชื่อ Index คือ
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Photo.Index" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>MVC Flickr Sample</title>
</head>
<body>
<div>
<% foreach (var p in ViewData.Model)
{ %>
<a href="<%= p.WebUrl %>">
<img src="<%= p.SquareThumbnailUrl %>" alt="<%= p.Title %>" />
</a>
<% }%>
</div>
</body>
</html>
โดยที่ View นี้เป็น Strong typed view
namespace MvcApplication1.Views.Photo
{
public partial class Index : ViewPage<FlickrNet.Photo[]>
{
}
}
หลังจากเราตั้งค่า Flickr API เรียบร้อยตาม Document ก็ทดลองรันดูด้วย Url /photo/
ทีนี้เราลองเพิ่มอะไรขึ้นมาเล็กน้อยด้วยการเพิ่ม Route เข้าไปดังต่อไปนี้
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Search", // Route name
"search/{key}/{page}", // URL with parameters
new { controller = "Photo", action = "Search", key = "", page = 1 }, // Parameter defaults
);
routes.MapRoute(
"User", // Route name
"photo/{username}/{page}", // URL with parameters
new { controller = "Photo", action = "PhotoByUser", page = 1 }, // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
จะเห็นว่าเราส่ง Request ไปยัง Action ใดๆ ก็ได้โดยไม่ขึ้นกับชื่อ กล่าวคือ เราจะทำการค้นหารูปหาก Request URL อยู่ในรูปแบบ search/คำค้น/หน้า และหากเป็น /photo/ชื่อผู้ใช้/หน้า ก็จะแสดงรูปของผู้ใช้คนนั้นแทนโดยเราไม่จำเป็นจะต้องสร้าง Search controller แต่อย่างใด แต่เราจะส่งไปที่ action Search และ PhotoByUser ตามลำดับ
โค้ดของ action ทั้งสองเป็นดังนี้
public ActionResult PhotoByUser(string username, int page)
{
Flickr f = new Flickr();
FoundUser u = f.PeopleFindByUsername(username);
if (u != null)
{
Photos p = f.PeopleGetPublicPhotos(u.UserId, 25, page);
return View("index", p.PhotoCollection);
}
return View("index");
}
public ActionResult Search(string key, int page)
{
Flickr f = new Flickr();
PhotoSearchOptions option = new PhotoSearchOptions();
option.Page = page;
option.Text = key;
Photos p = f.PhotosSearch(option);
return View("index", p.PhotoCollection);
}
เมื่อเราทดสอบด้วยการเปิด URL /search/grassland/ และ /photo/wiennat จะปรากฎรูปขึ้นมาตามต้องการ
แล้วถ้าเราลองเปิดด้วย /search/grassland/ข้อความ และ /photo/wiennat/ข้อความ ล่ะ
ผลลัพธ์คือเกิด error ขึ้นเนื่องจากพารามิเตอร์ page นั้นมีค่าเป็น NULL แต่ว่าเราต้องการพารามิเตอร์ที่เป็นตัวเลข เรามีทางแก้สองทางคือ
1. กำหนดให้ประเภทพารามิเตอร์ page ให้เป็น int?
2. จำกัดรูปแบบของพารามิเตอร์ โดยกำหนด Constrain ให้รับแต่ตัวเลข เท่านั้น
routes.MapRoute(
"Search", // Route name
"search/{key}/{page}", // URL with parameters
new { controller = "Photo", action = "Search", key = "", page = 1 }, // Parameter defaults
new { key="[A-Za-z0-9]+", page="[0-9]*" }
);
เมื่อผู้ใช้เข้ามาด้วย /search/grassland/ข้อความ ก็จะปรากฏข้อความที่บอกว่าไม่พบเอกสารดังกล่าวแทน
เป็นอันจบวิธีการใช้งาน URL Routing อย่างง่ายๆแล้ว สำหรับตอนหน้า เราจะมาดูว่าเราจะใช้ URL Routing ใน Web Form กันอย่างไร
สำหรับการใช้งานอื่นกรุณาทิ้งไว้ใน comment




