Skip to main content

[探索 5 分鐘] 淺談 ASP.NET MVC 路由 (routing)

路由 (routing) 的組合千變萬化, 但對於 ASP.NET routing 的起手式, 就是這一條:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.MapRoute(
     name: "Default", // Route name
     url: "{controller}/{action}/{id}", // URL with parameters
     defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
    );
}
進階的用法非常多, 但專案需求若沒有非常特殊(如多層 routing, 或安全性考量故意混淆), 使用大家約定俗成的 pattern, 其實易於維護。當然還有一種用於 Web API 的 routing 方式, 稱為 Attribute Routing。就是在 Action 或 Controller 上方標上一行清楚到不行的 routing rule, 個人是滿推薦的, 像下方這樣:

public class BooksController : ApiController
{
    [Route("api/books")]
    public IEnumerable<Book> GetBooks() { ... }

    [Route("api/books/{id:int}")]
    public Book GetBook(int id) { ... }

    [Route("api/books")]
    [HttpPost]
    public HttpResponseMessage CreateBook(Book book) { ... }
}
是不是非常清楚呢 ?

Web API如何Routing

從技術上來看, Web API 是如何做 routing 呢 ? 參考微軟 Routing in ASP.NET Web API 文章, 他用一個不錯的起頭 :
Web API routing is very similar to MVC routing. The main difference is that Web API uses the HTTP method, not the URI path, to select the action. You can also use MVC-style routing in Web API.
也就是說, Web API 的 routing 跟 MVC 的 routing 方式差不多, 但更強調 HTTP 方法的呼叫方式 (HTTP 這個 uri schema 以及 GET, POST, PUT, DELETE 這些方法)。那怎麼處理一個呼叫 ? 也就是客戶端發出一個 HTTP request, Web API 服務怎麼 handle ?
In ASP.NET Web API, a controller is a class that handles HTTP requests. The public methods of the controller are called action methods or simply actions. When the Web API framework receives a request, it routes the request to an action.
有時候看英文實在覺得怎麼可以寫得這麼精簡就表達這個過程, 翻為中文卻比較囉嗦。重點就是 :
  1. Controller 是處理 HTTP 請求的基本類別
  2. Action 是處理 HTTP 請求的處理方法, 是 Controller 的公開函式
  3. Web API Framework 是透過 routing 路由方式將一個 HTTP 請求轉到某個 Action 去處理的
用Visual Studio 創建 Web API 專案, 有個路由設定檔 WebApiConfig.cs

位置在 ~/App_Start/WebApiConfig.cs, 而沒有修改任何路由邏輯的樣子是:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
         name: "DefaultApi",
         routeTemplate: "api/{controller}/{id}",
         defaults: new { id = RouteParameter.Optional }
        );
    }
}
當然喜歡改為這樣也行 :

routes.MapHttpRoute(
    name: "CustomApi",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional }
);
跟 ASP.NET MVC 的 routing 非常像吧, 不過習慣上路由規則是 "api/" 開頭, 區別 MVC 與 Web API 的路由。

常見問題

Question: 一個 Url 若 match 多個 routing rule, 會出錯嗎 ?

不會, 依序找尋第一個適合的 rule 就是了。

Question: 可否將 routing 設為 "{controller}/{id}"  (Url 不需輸入Action, 交給 Default 來設定)

可以, 參考這篇 stackoverflow, 那麼 Url 就不需輸入 Action, 交給 Default 來指定 Action。

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
    routes.MapRoute(
     name: "NoAction",
     url: "{controller}/{id}",
     defaults: new { controller = "Home", action = "Details" },
     constraints: new { id = @"\d+" }
    );
    
    routes.MapRoute(
     name: "Default",
     url: "{controller}/{action}/{id}",
     defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

Question: 可否將 routing 設為 "{action}/{controller}"  (Controller 與 Action 故意相反)

可以, 類似這樣, 就實驗出一個 reverse 版本了, 可在本機打 http://localhost/reverse/home 試看看

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
    routes.MapRoute(
     name: "Reverse",
     url: "{action}/{controller}",
     defaults: new { controller = "Home", action = "Reverse" }
    );
    
    routes.MapRoute(
     name: "Default",
     url: "{controller}/{action}/{id}",
     defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

參考資料

  • https://msdn.microsoft.com/zh-tw/library/cc668201.aspx
  • https://docs.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api
  • http://blog.miniasp.com/post/2009/07/20/ASPNET-MVC-Developer-Note-Part-8-Routing.aspx
  • http://blog.miniasp.com/post/2011/08/01/ASPNET-MVC-Developer-Note-Part-21-Routing-Concepts-and-Skills.aspx
  • https://stackoverflow.com/questions/18038284/asp-net-mvc-4-routes-controller-id-vs-controller-action-id
  • https://docs.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2
  • https://forums.asp.net/t/1736055.aspx

Comments

  1. 請問可以不要{controller}只要{action}/{id} 但我action的函示有兩個
    這樣可以嗎

    ReplyDelete

Post a Comment