介紹ASP.NET MVC中的MvcAjaxPanel
也有評論認為,Controller中的邏輯不該根據一個請求AJAX與否而進行不同處理(Nikhil的解決方案使用RenderPartial 來替代RenderView為AJAX操作進行輸出),因此這個解決方案破壞了MVC的職責。我不這么認為,但是我希望能做到這一點,因為做到這一點即意味著絕對的透明。絕對透明則意味著Controller將一個應用程序是否AJAX的決定權完全交給了客戶端,這點非常理想,因為AJAX完全是一個表現層的概念。ASP.NET AJAX中的UpdatePanel在這方面的表現可圈可點(雖然還遠不夠完美),因此我最后決定也為ASP.NET MVC開發一款類似UpdatePanel的組件。值得慶幸的是,ASP.NET MVC默認使用WebForm頁面作為視圖模板,在這個強大的模型之下,構建出這樣一個AJAX解決方案(的原形)似乎并不十分困難。
我將這個控件命名為MvcAjaxPanel。MvcAjaxPanel與UpdatePanel最大的區別在于后者接收的是PostBack,而前者接收的只是普通的HTTP請求。Post“Back”意味著Post過后回到了原來的Page,而ASP.NET MVC的請求往往會被引導至不同的頁面。因此如何跨頁面進行內容更新是MvcAjaxPanel首要解決的問題。最終我選擇了為每個MvcAjaxPanel指定一個UpdateAreaID的做法。
- <mvc:MvcAjaxPanel runat="server" ID="mvcAjaxPanel" UpdateAreaID="Header">
- ...
- </mvc:MvcAjaxPanel>
當頁面向服務器端發出一個AJAX請求時將會附帶頁面中的UpdateAreaID信息,而服務器端的Action并不會意識到這一點,因此依舊按照尋常邏輯指定一個視圖模版并輸出HTML。不過,如果視圖模板中的 MvcAjaxPanel發現這個請求實際上是一個符合約定的AJAX請求(請注意,只有View組件意識到這是個請求的性質),則會使用新的方法來替換標準的輸出。這時候模板就會根據客戶端傳遞過來的UpdateAreaID,尋找頁面上具有同樣屬性值的MvcAjaxPanel,有選擇性地輸出內容。在客戶端就會有對應的JavaScript代碼接收服務器端的數據,并且更新頁面中的相應區域。
很明顯,MvcAjaxPanel的工作原理與UpdatePanel有頗多相似之處,也做到了一定程度上的透明。而且與Nikhil的解決方案相比,一個非常重要的優勢就是可以一次更新頁面中的多個區域——其實這也就是UpdatePanel的特性之一。而且這種對Controller透明的做法又有一個天然的特點,那就是能夠輕松地在不支持AJAX的瀏覽器中使用傳統的方式切換頁面。
【編輯推薦】