應用程序框架實戰三十三:表現層及ASP.NET MVC介紹(二)

  最近的更新速度愈來愈慢,主要是項目上比較忙,封裝EasyUi也要花不少時間。不過你們請放心,本系列不會半途夭折,而且代碼乾貨也會持續更新。本文繼續介紹表現層和Asp.net Mvc,我將在本篇討論一些重要的設計問題和封裝技巧。css

是否須要將控制器分離爲獨立項目

  常常有人問我,是否有必要將控制器從Web項目中分離出來,下面談一下個人認識,僅供你參考,不必定正確,請根據你本身的實際狀況決定。html

  控制器的做用是調用業務邏輯,將得到的結果傳給視圖顯示。從根本上說,控制器只是起協調做用,它不該該自身完成複雜的業務邏輯。jquery

  不過哪怕你將業務邏輯儘可能放到了領域層,控制器上仍是會有很多代碼,好比查詢條件的設置,事務控制等。在這種狀況下,將控制器分離到一個獨立的程序集,彷佛說得過去。web

  可是分離控制器代碼有不少方法,好比引入應用層服務,應用層服務能夠當作是控制器的延伸,控制器上大部分代碼被轉移到應用層服務中,控制器變成很薄的一層,這種狀況下,分離控制器到獨立項目,沒有任何價值。緩存

  將控制器分離到一個獨立程序集後,你會發現查找控制器對應視圖變得更加困難,哪怕Resharper能夠幫你定位跳轉。從目錄結構上看,也再也不遵循你們熟悉的約定,實際上下降了可維護性,增長了學習成本。服務器

  最後的結論就是,若是你採用了應用層服務,就不要分離控制器。架構

是否須要將MVC項目拆分爲多個

  對於表現層的模塊化,MVC提供了Areas(區域)技術來支持較大項目的開發。每一個區域包含獨立的控制器和相關視圖,爲每一個業務模塊建立一個區域,對於通常項目的管理,應該都夠用了。框架

  我在學習一些流行的應用開發框架時發現,有些應用開發框架將同一個Asp.Net Mvc項目,拆分爲多個Mvc項目,以實現網站級別的模塊化。其中一個是主Web項目,包含大部分WEB資源,好比圖片、CSS、JS等。其它一些附屬Web項目,包含其它業務模塊,若是包含js文件,該文件的生成操做須要設置成「嵌入的資源」,包含的cshtml文件還須要用RazorGenerator插件手工生成類。最後主Web項目引用其它附屬Web項目,從而整合爲一個網站。模塊化

  這種架構的好處是容許複用業務UI模塊,包括視圖,同時方便團隊協做,不一樣成員開發不一樣模塊時干擾更小。工具

  可是這種架構也有不少問題,將JS設置成「嵌入的資源」,cshtml文件使用RazorGenerator生成類,會致使JS和頁面調試部署都很不方便,調試時常常會碰上緩存問題。

  解決UI複用和協同工做的另外一個辦法是,多個網站獨立開發部署,採用單點登陸鏈接成一個系統。

  對錶現層的模塊化建議以下:普通項目採用單Mvc項目架構,經過Areas進行模塊化, 更大項目採用多Mvc項目架構,單獨開發部署,以單點登陸方式集成,儘可能不要將js、cshtml等頁面元素嵌入程序集,會致使更難維護,僅在具備特殊需求時採用,好比插件式開發。

Asp.Net Mvc抽象封裝技巧

  對於技術和業務邏輯,咱們進行了複雜的分層和封裝,那麼對於頁面自己,還要不要抽象?

  Html由標籤組成,大量的Html標籤,讓你沒法清晰的看出頁面結構。當須要修改頁面上某個區域時,若是頁面很長很複雜,你須要在雜亂的Html標籤中來回掃描,以定位目標,這與幾百行的長方法相似。有經驗的開發人員,老是以單一職責原則SRP爲指導,經過提取方法和組合方法重構,保持方法的簡短,同時得到清晰的代碼結構。

  除了定位困難之外,未進行抽象的頁面,將包含大量重複的Html,而冗餘代碼是可維護性的天敵。

  對於Asp.Net WebForm,抽象封裝主要依賴母版頁、服務器控件、用戶控件等元素。

  母版頁用於管理通用頁面結構,幫助劃分區域,它相似於抽象類,能夠提供一部分具體實現,它將多個頁面共享的部分抽取上來,並提供了內容佔位符,佔位符相似於虛方法或抽象方法,以方便具體頁面填充內容。

  服務器控件用於封裝可以高度複用的UI元素,提供加強功能,好比自定義文本框,通常的文本框只能輸入文本,自定義文本框能夠進行驗證,甚至能進行權限控制等。

  用戶控件是比服務器控件更輕量的封裝方式,用戶控件通常用於封裝頁面上的元素或區域。母版頁的工做方式相似於繼承,有經驗的同窗知道,繼承的靈活性是比較低的,因此設計上流傳一句話「多用委託,少用繼承」,WebForm的「委託」就是用戶控件,它一樣能夠切割頁面,而且提供了更好的靈活性。

  若是不少頁面都須要分紅上中下三個區域,每一個區域有一些固定的元素,這時候採用母版頁就是合適的。但若是隻有一個或幾個頁面須要這個結構,採用母版頁將是大炮打蚊子,用戶控件則是更好的選擇。

  用戶控件除了可以封裝Html之外,還包含後置代碼,能夠處理邏輯。

  瞭解了WebForm的基礎封裝元素後,再來看Asp.Net Mvc提供了哪些元素,與Web Form的元素是如何對應的。

  首先看母版頁,母版頁的功能是提供佈局結構,Mvc提供了佈局頁來支持相似功能。打開Mvc項目Views\Shared目錄,會發現一個名爲_Layout.cshtml的文件,這是系統定義的佈局頁,_Layout這個名稱不是必須的,它可以起做用的緣由是Views目錄下的_ViewStart.cshtml設置指向它。不過沒事不要亂改系統定義的文件名,這樣會破壞約定,增長維護成本。

  _ViewStart.cshtml包含了Layout的設置,它的做用是爲視圖提供默認佈局設置,值得一提的是,根目錄Views下的_ViewStart.cshtml設置不能繼承,Areas各模塊必須添加本身的_ViewStart.cshtml。

  對於較複雜的系統,僅依靠一個_Layout.cshtml來抽象頁面冗餘是不夠的,通常須要多層繼承結構,_Layout.cshtml僅放置通用性很強的內容,好比js,css引用等,更具體的抽象可定義本身的佈局頁,繼承_Layout.cshtml。

  Asp.Net Mvc再也不提供服務器控件這種可視化元素,但相關的封裝思想卻從未間斷。Mvc提供了HtmlHelper、UrlHelper、AjaxHelper等幾個幫助類來封裝相關操做,其中HtmlHelper包含表單元素的封裝,是與WebForm服務器控件相對應的東西,咱們封裝控件主要從它下手。

  Mvc容許在視圖中經過Html屬性訪問HtmlHelper,能夠看到,全部控件都是經過擴展方法的方式添加上去的,這也給咱們提供了一種思路。我在前文已經屢次提到,使用擴展方法要很當心,特別是擴展系統的類,由於可能形成大面積污染。

  對於HtmlHelper,我通常僅擴展少許方法,首先是通用UI技術的封裝,我會把須要在視圖上用到的通用技術封裝到@Html.X()方法中,好比導入一個Js文件,能夠這樣調用@Html.X().ImportJs(「xx」),固然如今導入Js通常用Bundle,本篇後續再介紹。

  其次是對特定UI技術的封裝,好比Dwz,EasyUi,Ext等,也多是其它組件,好比圖表FusionCharts,ECharts等。對於每個要用到的組件,都僅爲其在HtmlHelper擴展一個方法,以EasyUi爲例,你不能這樣擴展,@Html.EasyUiTextBox(),@Html.EasyUiCombox(),這樣會在HtmlHelper中擴展大量方法,致使查找其它方法變得困難,更好的方法是@Html.EasyUi().TextBox() ,@Html.EasyUi().Combox()。這裏設計的核心是EasyUi方法返回一個接口,將EasyUi全部操做所有放到這個接口中。關於Mvc的控件封裝,我會在後續EasyUi系列詳細講述。

  最後,須要在HtmlHelper中擴展的是業務UI組件,好比字典、省市區三級聯動、人員選擇等,我會把全部業務UI組件擴展到@Html.Ui()方法中,以方便開發某些業務模塊時複用,好比字典@Html.Ui().Dic()。

  下面來看WebForm用戶控件在Mvc中有哪些對應元素。

  若是頁面中的某個區域很複雜,根據邏輯結構,將區域分解爲更小的部分,每一個部分放到一個用戶控件中,從而獲得清晰的結構。

  Mvc提供的@Html.Partial()方法容許將Html分離到部分視圖中,並能夠給這個部分視圖傳遞一個實體,以進行數據綁定。

  不過部分視圖的能力是有限的,你的主視圖必須可以提供部分視圖相關數據,這就要求主視圖的實體攜帶更多的數據,這在不少時候都不太方便。打個比方,你的頁面上須要顯示一個下拉人員列表,列表的內容是用另外一個表的數據填充的,若是採用部分視圖來封裝這個列表,你的主視圖對應的實體就必須提供人員集合。

  Mvc提供了更爲強大的@Html.Action()方法,Action也用於操做部分視圖,但它可以獨立的爲視圖提供數據。仍是剛纔的下拉人員列表,如今主視圖的實體再也不須要攜帶人員數據了,調用Action後,人員列表已加載完成。

  雖然Action更強大,但它須要設置Url信息,以肯定這個功能由哪一個控制器的方法提供,當某個Action操做用得很是頻繁時,考慮將該操做擴展到HtmlHelper中,這樣能夠封裝掉Url和參數信息,以簡化調用。

  以上簡單介紹了Mvc的一些封裝元素,以供你編寫出更清晰的UI代碼。同時比較了Asp.net WebForm與Mvc的元素對應狀況,你若是具備WebForm的基礎,相信Mvc的封裝也會很快上手。

  補充一點,雖然我用方法與Html長度類比,但不能認爲Html的封裝粒度越細越好,我曾經嘗試過很細粒度的UI拆分,最終效果並不理想,合適的拆分粒度更好維護,這方面根據本身的習慣進行摸索。

Bundle介紹

  如今的系統Js和Css文件都不少,若是一個網站引用太多Js或css文件,對性能是有必定影響的,由於每一個文件會發送一個請求。

  我之前的辦法是使用AjaxMinifier工具手工壓縮Js,再手工合併,Css也採用相似辦法,後面使用了一個第三方的工具,也比較麻煩。

  Asp.Net爲此提供了一個叫Bundle的打包壓縮技術,它可以在運行時將js或css文件打包壓縮,這正是我須要的。

  不過在使用過程當中,發現它並非想像中那麼易用,問了一些人,也用起來有問題。還有一些人沒碰到啥問題,但觀察他的代碼,實際上沒有起做用,由於他沒有設置啓用優化的選項。

  使用Bundle有幾點須要注意:

  1. 若是文件中的代碼對路徑很敏感,好比css中用了相對路徑,你在配置Bundle時,虛擬路徑就不能很隨意,由於會破壞路徑關係,致使失敗。
  2. 若是沒有在代碼中設置BundleTable.EnableOptimizations = true,也沒有在web.config進行相應配置,則打包壓縮不會起做用,只是讓你在引用文件時省點力。
  3. 已經壓縮過的文件,好比jquery.min.js,不要用Bundle配置,使用常規方式引入,否則運行時可能出錯。

Util最新代碼示例更新

  除了以前的大量代碼已重構外,主要更新了EasyUi的行內編輯方式。

結束語

本文簡單介紹了Mvc相關的一些問題和技巧,有不一樣意見,歡迎交流。

下載地址:下載時請順手推薦,以支持本人寫做.

http://files.cnblogs.com/files/xiadao521/Applications.2015.3.16.1.rar

http://files.cnblogs.com/files/xiadao521/Framework.2015.3.16.1.rar

http://files.cnblogs.com/files/xiadao521/Data.2015.3.5.1.rar

 

注意:本人每次發佈新版本時,會刪除老版本

 

.Net應用程序框架交流QQ羣: 386092459,歡迎有興趣的朋友加入討論。

.Net Easyui開發交流QQ羣(本羣僅限Easyui開發者,非Easyui開發者勿進):157809322

謝謝你們的持續關注,個人博客地址:http://www.cnblogs.com/xiadao521/

相關文章
相關標籤/搜索