在Nancy中,最為神奇的莫過於路由了,定義路由模塊是構成Nancy應用的骨架。在Nancy中定義路由,和在 ASP.NET MVC那些類似的框架中有着非常大的區別。
以 ASP.NET MVC 為例,通常情況需要創建一個控制類。多數情況下,這個類提供了路由的約定。通過定義您的控制器類名和該類中的方法的名稱,就能定義了該代碼所處理的“路由”
請看下面的例子:
using System; using System.Linq; using System.Web.Mvc; namespace Intranet.WebUi.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(); } } }
這段從標准ASP.NET MVC 應用程序摘錄的代碼定義了Home路由下的Index節點,用於將Http請求路由到這段代碼 ,請求地址應該是這樣的 /home/index 。 如果使用Nancy,就會有些不一樣了。
首先,在Nancy應用中,繼承NancyModule基類,才能定義路由。第二,不是每個路由都需要定義在一個單獨的類中(如 MVC示例),可以在模塊類的構造構造函數中定義路由,使用Rest動詞定義路由類型。
當然這可能導致過於龐大的構造函數,但是也有很多方式處理這個問題。
在往下看之前,我們需要先了解一些概念......
如果您習慣於看到從 web 瀏覽器的觸發的web 請求,你可能不知道,在它之下是相當復雜的協議。如果你從事於 web相關的開發工作,很可能聽說過稱為 HTTP 協議。HTTP通過使用一系列的動詞來表示客戶端希望服務器采取某些行動。
采用Nancy,也無需了解太多HTTP動詞的細節。實際上創建一個REST 風格的應用,用到下面的Rest動詞就好:
- GET
- POST
- PUT
- DELETE
GET,顧名思義,用來檢索數據從服務;同樣,刪除是習慣請求數據被刪除。PUT和POST可能經常會造成混亂。遵循規范, PUT意思是“整體替換指定的”,而POST用於“在現有基礎上添加”。許多開發人員創建基於 rest 風格的應用程序,也不過就是使用GET和POST。
這方面Nancy走的更進一步,不同於大多數其他 web 為基礎的框架,你可以定義自己的動詞。在某種意義上,允許您創建您自己的基於HTTP的特定領域的語言。讓我們深入剖析的Nancy路由模塊,看看是如何工作的。
我們的第一個Nancy路由模塊
看下面的代碼
using Nancy; namespace nancybook.modules { public class BaseRoutes : NancyModule { public BaseRoutes() { Get[@"/"] = _ => Response.AsFile("index.html", "text/html"); } } }
作為一個Nancy項目,這是例子再簡單不過了。
這個只有十一行的代碼,監聽所有向應用程序的"/"根路徑的請求,返回"Content"文件一個名為“index.html”HTTP頁面。
Content 文件夾是Nancy查詢文件的默認文件夾,在下一張關於視圖Views的章節,我們會涉及更多,但現在,只是確保項目有一個文件夾被稱為Content,所有的 HTML 文件都放置於此。
撇開通常命名空間和類的代碼部分 ,只有兩點是這個Nancy路由模塊添加的:繼承了NancyModule ,在構造函數中使用GET規則。
GET規則意味着這將響應使用 GET 動詞的 HTTP 調用,代碼將執行響應根路徑的 GET 請求。
如何你要擴展這個模塊處理 GET,POST,PUT,和DELETE,你需要這么處理:
using Nancy; namespace nancybook.modules { public class BaseRoutes : NancyModule { public BaseRoutes() { Get[@"/"] = _ => Response.AsFile("index.html", "text/html"); Put[@"/"] = _ => Response.AsFile("index.html", "text/html"); Post[@"/"] = _ => Response.AsFile("index.html", "text/html"); Delete[@"/"] = _ => Response.AsFile("index.html", "text/html"); } } }
模塊監聽的路徑或路由需要放置到動詞后面的方括號中。所以,舉個例子,你可以像下面是的修改:
using Nancy; namespace nancybook.modules25 { public class BaseRoutes : NancyModule { public BaseRoutes() { Get[@"/allpeople"] = _ => Response.AsFile("index.html", "text/html"); Put[@"/allpeople"] = _ => Response.AsFile("index.html", "text/html"); Post[@"/newperson"] = _ => Response.AsFile("index.html", "text/html"); Delete[@"/singleperson"] = _ => Response.AsFile("index.html", "text/html"); } } }
為了演示的目的,每個請求都返回一個靜態網頁。在真是環境中,每個實際的請求你可能都需要根據實際的功能需求編寫合適的處理代碼。本章接下來對這個話題進行更多的介紹。
你也可以為你的模塊編寫通用的路徑。試想下面的例子:
using Nancy; namespace nancybook.modules { public class BaseRoutes : NancyModule { public BaseRoutes() { Get[@"/single"] = _ => Response.AsFile("index.html", "text/html"); Put[@"/single"] = _ => Response.AsFile("index.html", "text/html"); Post[@"/new"] = _ => Response.AsFile("index.html", "text/html"); Delete[@"/single"] = _ => Response.AsFile("index.html", "text/html"); } } }
很快你就會發現代碼變得難以閱讀。 另外,如果你想用一致的命名方法來編寫你的API,重用single 和new 來處理應用程序中的其他資源。
再一次,Nancy展現了其簡單的處理方式,僅僅通過在模塊類中重載父類NancyModule的構造函數並傳遞根目錄路徑。
namespace nancybook.modules { public class BaseRoutes : NancyModule { public BaseRoutes() : base("/people") { Get[@"/single"] = _ => Response.AsFile("index.html", "text/html"); Put[@"/single"] = _ => Response.AsFile("index.html", "text/html"); Post[@"/new"] = _ => Response.AsFile("index.html", "text/html"); Delete[@"/single"] = _ => Response.AsFile("index.html", "text/html"); } } }
通過添加父類構造函數的調用,瞬間已經更改了您的模塊將響應的所有 Url:
- GET /single
- PUT /single
- POST /new
- DELETE /single
轉變為:
- GET /people/single
- PUT /people/single
- POST /people/new
- DELETE /people/single
加上一點創造性思維和一些聰明的軟件開發點子,你甚至可以在很多地方重用同一個控制器。
在我們繼續之前,還是要提一個關於“Rest動詞”的警告。一些托管環境(包括ASP.NET/IIS)默認是不支持一些常用的動詞。
在前面的示例中,如果運行在 IIS 中,你會發現PUT和DELETE導致服務器返回以下錯誤: 503 方法不被允許。
這並不是Nancy的問題,而是,IIS 只允許兩個最常見動詞(GET 和 POST)。如果你參考下Stack Overflow的文章,這個問題不難解決。
路由參數
正如其他的web工具包,您的路由模塊也可以接收各種各樣的數據。這些數據包括簡單的 URL 參數,如記錄的 ID 或博客分類號,也有通過POST或PUT傳遞的復雜對象。
在這一章,我們會講解基於路由的簡單數據,以后的章節再介紹復雜的對象。
你已經看到了,為響應給定的請求,在Nancy路由模塊中修改URL非常簡單。但如果需要在URL中傳遞記錄ID該怎么辦?
using Nancy; namespace nancybook.modules { public class BaseRoutes : NancyModule { public BaseRoutes() : base("/people") { Get[@"/{id}"] = parameters => { var myRecordId = parameters.id; return Response.AsFile("Pages/index.html", "text/html"); }; } } }
如果你想限定參數的類型,請看下面示例:
using Nancy; namespace nancybook.modules { public class BaseRoutes : NancyModule { public BaseRoutes() : base("/people") { Get[@"/{id:int}"] = parameters => { var myRecordId = parameters.id; return Response.AsFile("Pages/index.html", "text/html"); }; } } }
注意在路由參數上增加了int限制;任何嘗試傳遞非整數參數都會導致404未找到的錯誤。Nancy定義許多這些的限制,基本上都綁在.NET 基元類型:
- long
- decimal
- guid
- bool
- datetime
你可以在URL中添加很多的參數,如下:
using Nancy; namespace nancybook.modules { public class BaseRoutes : NancyModule { public BaseRoutes() : base("/people") { Get[@"/person/{age:int}/{surname}/categories/{category}/{city}"] = parameters => { return Response.AsFile("Pages/index.html", "text/html"); }; } } }
總結
在本章中,您已經學到了如何使用路由模塊創建應用程序的骨架,了解到了Nancy與ASP.NET MVC在路由上定義的不同。你已經看到了如何定義路由路徑,不再通過類的名字控制路由定義,了解了如何使用動詞和在URL中傳遞參數。在下一章中,我們會看看視圖引擎,看看如何返回一些其他東西,不只是普通的 HTML 文檔。