REST on ASP.Net MVC (and Future)

MVC和REST是兩種不同的世界觀. 前者更多的是對行爲的建模,後者則更強調數據(狀態及狀態的變遷). 前者給出的是內部實現方面的指導, 把程序結構分離爲Model, View及Controller. 後者提供的則是從外部觀察系統的視角: 一組被超媒體誘導的系統變遷.

 

MVC和REST從兩種不同的維度來描述世界, 而不是同一緯度上兩種相反的觀點, 因此基於現存的大量MVC框架來開發符合REST要求的應用是可能的. 但工具是世界觀的反映, MVC框架對REST的支持總不是那麼直接. 我們在使用MVC框架來開發REST應用時,要注意避開可能的衝突, 而專注於那些符合REST要求的特性. 下面我們來看看ASP.Net MVC對REST的支持

 

Client–server

 

客戶-服務器約束背後的原則是分離關注點, 比如用戶接口和數據存儲. 對於Web來說, 最重要的是這種關注點的分離允許組件獨立地進化.

 

ASP.Net MVC 是server端開發框架, 在這個約束上它沒有貢獻也沒什麼過失. 它產生符合標準的HTML代碼, 對客戶端的能力沒什麼特別的要求.

 

Stateless

 

ASP.Net MVC提供了Session的概念. 可以把它理解成server端保存的針對某個特定客戶端的狀態. 使用這個特性將會違反Stateless的約束, 造成可伸縮性的下降. 開發者若要確保不會無意中破壞這個約束, 可以通過一系列配置來禁用session, 比如在Web.config加上<sessionState mode="Off" />, 或者通過代碼來對單個Controller進行配置:

 

 

ASP.Net MVC也提供了對Cookie的支持, 而Cookie是違反REST約束的一種特性. “Cookie被定義爲被附加在任何將來的請求上, 對於特定的一組資源標識符, Cookie通常是與一個完整的站點相關聯, 而不是與瀏覽器中特定的應用狀態(當前呈現的表述的那一組狀態)相關聯. 並且它允許數據在沒有充分表明其語義的情況下進行傳遞”. ASP.Net提供了cookieless的選項, 使我們可以關閉對cookie的支持.

 

Cacheable

 

ASP.Net MVC提供了一個叫做 OutputCache 的ActionFilter來支持緩存. OutputCache 有點過於強大, 它不僅支持客戶端與服務器之間的緩存, 還支持服務端應用代碼與數據庫之間的緩存. 還可以設定緩存的位置, 比如是放在客戶端瀏覽器(即在Response中加上標準的Http Cache Control Headers)還是放在服務端. 除了支持整頁緩存, 它還支持部分頁面緩存(我理解這時它就只能緩存在服務端了)

 

 

當大量獨立的客戶端請求同樣的內容時, 比如同一幅圖片或視頻, 服務端緩存要比客戶端緩存更有效. 然而針對這個問題, 有一種叫做反向代理的組件, 可以將這部分職責從服務端應用代碼中剝離出來, 把它變成Web基礎設施的一部分, 前提是服務端要設置標準的那些Http Cache Control Headers. 在此情況下, 這類緩存通常被稱爲共享緩存. 後面談到分層的時候我們會再提一下這個問題.

 

所以對REST應用來講, 個人感覺還是優先應用客戶端緩存, 這樣可以最大程度的利用現有的各種Web基礎設施.

 

Layered system

 

跟Client-server約束類似, ASP.Net MVC在此無功無過. 但是一些特性會導致不能完全發揮那些中間層的作用.

 

比如說Session對Load Balancer的影響. 如果服務端將session存在同一應用進程如w3wp.exe的內存中, 則Load balancer將不得配置 Session Sticky 的策略, 從而不能做到真正的load balancing

 

再比如服務端緩存將使反向代理髮揮不出應有的作用.

 

Code on demand (optional)

 

.Net 平臺上native的Mobile Code Style的支持, 就是Silverlight, 但ASP.Net MVC對此並沒有提供任何支持, 比如並沒有一種基於Silverlight的View Engine.

 

對於JavaScript, ASP.Net MVC提供的支持也有限, 只是提供了一些輔助性的代碼, 可以在View中產生一些AJAX Call的代碼, 比如AjaxHelper.ActionLink, AjaxHelper.BeginForm等

 

Server端也提供了一種叫 JsonResult 的Representation, 可供客戶端JavaScript方便的操縱. 但這更多的是對多種Representation的支持, 後面會提到.

 

Uniform interface

 

"使REST架構風格區別於其他基於網絡的架構風格的核心特徵是,它強調組件之間要有一個統一的接口. 通過在組件接口上應用通用性的軟件工程原則, 整體的系統架構得到了簡化, 交互的可見性也得到了改善. 實現與它們所提供的服務是解耦的, 這促進了獨立的可進化性. 然而, 付出的代價是, 統一接口降低了效率, 因爲信息都使用標準化的形式來轉移, 而不能使用特定於應用的需求的形式. REST接口被設計爲可以高效地轉移大粒 度的超媒體數據, 並針對Web的常見情況做了優化, 但是這也導致了該接口對於其他形式的架構交互並不是最優的

 

爲了獲得統一的接口, 需要有多個架構約束來指導組件的行爲. REST由四個接口約束來定義: 資源的識別(identification of resources), 通過表述對資源執行的操作(Manipulation of resources through these representations), 自描述的消息(self-descriptive messages), 以及作爲應用狀態引擎的超媒體(Hypermedia as the engine of application state)" -- from <<REST_cn >>

 

Identification of resources

 

資源的識別或標識是一種概念或語義上的抽象, 它明確的區分了資源本身的物理實現和返回給客戶端的資源的表述. 如何從概念上爲一個資源定義一個標識是開發者的責任, ASP.Net MVC幫不上任何忙. ASP.NET MVC能做的, 只是幫忙將資源的標識映射到資源的實現(這是通過UrlRoutingModule來實現的). 換句話說, 一個URL是否是 RESTful的, 不在於你是否通過高超的路由技術讓它看起來很乾淨沒參數, 而在於它本身是否是一個永久性的概念, 是否可以更改底層實現而無需調整.

 

由於同一個URL上可以進行多種標準的HTTP操作, 比如POST, PUT, GET, DELETE等, 一個好的路由映射應該能夠將不同的HTTP操作映射到不同的對象或方法上. ASP.NET MVC提供了這種支持:

 

 

 

Manipulation of resources through these representations

 

在ASP.Net MVC中, 資源的Representation是通過一個叫做ActionResult的概念來表達的. 比如產生HTML的 ViewResult, 產生Json的 JsonResult, 產生Javascript的JavaScriptResult等. 當我們需要定義自己的媒體類型的時候, 擴展ActionResult就可以了.

 

Self-descriptive messages

 

通常來講, 這裏指的是Http Header中的各種信息的存取. ASP.Net MVC通過HttpRequest和HttpResponse兩個class提供了對元數據的支持. 當然, 解析這些數據, 理解其含義, 遵循其指示, 並設置合適的響應, 還是開發者的責任.

 

Hypermedia as the engine of application state

 

終於到了REST最核心的特性, ASP.Net MVC並沒有有意識的提供支持. 不奇怪, 首先MVC更傾向於一種RPC的設計思路而不是REST, 其次這個約束還是更多的靠開發者來實現而不是什麼神奇的框架.

 

HTML是ASP.Net MVC支持的唯一一種Hypermedia. 在一個叫做HtmlHelper的類中, 提供了大量方法來方便的產生合法的HTML, 以及最重要的, 到其它資源的link, 比如HtmlHelper.ActionLink(...)

 

到其它資源的Link是Hypermedia的核心. 它可以被用在非HTML媒體類型中, 比如ATOM Feed. ASP.Net MVC提供了UrlHelper來產生各種link.

 

 

ASP.Net MVC Future

 

ASP.Net MVC Future 包含了一組ASP.NET MVC team認爲將來可能會加到ASP.Net MVC正式Release中的特性. 在目前的版本中(ASP.Net MVC 3 RTM), ASP.Net MVC Future加入了更多對REST的支持.

 

更多的超媒體類型比如Atom Feed : AtomEntryActionResult和AtomFeedActionResult兩個類爲Atom提供了支持. 這兩個類其實很簡單就是設置了一下Content-type, 真正核心的功能都委託給了SyndicationFeed和SyndicationItem. 後者是.Net Framework提供的.

 

JSON和Xml的Model Binder : 可以支持將請求中Json和Xml類型的負載直接綁定爲Action以對象形式定義的參數.

 

流行的"RESTful"的路由 : 這是通過RouteCollectionExtensions和ResourceControllerFactory實現的. 比如前者可以幫你建立如下的路由:

 

 

然而對於一個很多開發者期待的特性, 就是根據HttpRequest Header中Accept的值進行路由, 無論是ASP.Net MVC還是Future, 都沒有提供. 比如目前並不支持如下的寫法:

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章