<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      上篇博客【寫自己的ASP.NET MVC框架(上)】 我給大家介紹我的MVC框架對于Ajax的支持與實現原理。今天的博客將介紹我的MVC框架對UI部分的支持。

      注意:由于這篇博客是基于前篇博客的,因此有些已說過的內容將會直接跳過,也不會給出提示。
      所以,如果要想理解這篇博客,那么閱讀上篇博客【寫自己的ASP.NET MVC框架(上)】則是必要的。

      MyMVC的特點

      在開發MyMVC的過程中,我吸取了一些ASP.NET WebForm的使用經驗,也參考了ASP.NET MVC,也接受了Martin Fowler對于MVC思想的總結。 在設計過程中,我只實現了一些必要的功能,而且沒有引入其它的類庫與組件,因此,它非常簡單,且容易使用。

      我們可以這樣理解MyMVC:它是一個簡單,容易使用,且符合MVC思想的框架。

      在MyMVC框架中,View仍然采用了WebForm中的Page,畢竟Page已經使用了十年,能經得起時間的檢驗,它仍然是我們可信賴的技術。 另一方面,Page也是ASP.NET中默認的HTML輸出技術,使用它會比較方便。

      MyMVC與微軟的ASP.NET MVC不同的是:
      1. 不依賴于URL路由組件。
      2. 不提供任何HtmlHelper
      3. Controller只是一個Action的容器,沒有基類的要求。
      4. Action處理的請求不區分POST, GET
      5. URL可以直接對應一個網站目錄中的aspx頁面(View)。
      6. View的使用是使用路徑來指定,與Controller,Action的名字無關。

      說明:URL雖然可以與網站中的頁面對應,但這種對應并不是必須的,也可以不對應。
      而且本質上與WebFrom中的頁面執行過程并不相同。
      下圖反映了在MyMVC中,一個頁面請求的執行過程:

      介紹示例項目

      為了讓大家對MyMVC有興趣,也為了檢驗MyMVC的設計,我在開發MyMVC的過程,還專門開發一個基于MyMVC的ASP.NET網站示例項目。 網站提供了三種顯示風格(也就是三種View),下面以“客戶管理”頁面為例來展示三種View的不同:

      風格1

      View對應的代碼如下:

      風格2

      View對應的代碼如下:

      風格3

      View對應的代碼如下:

      這是三種截然不同的風格,在服務端的代碼也是完全不同的。

      其中第二種風格,是采用了我上篇博客中總結的【純AJAX網站】的風格來開發,因此在服務端頁面的開發過程中,最為簡單,它需要輸出的HTML最少,UI部分由客戶端的JS來實現。

      對于第一種和第三種風格,它們的HTML結構是不同的,頁面所能完成的功能也是不同的, 除此之外,它們應該是比較類似的,都是從下面這個泛型類型繼承而來:

      
      Inherits="MyPageView<CustomersPageModel>"
      
      

      從泛型類型繼承的好處是:我可以在設計頁面時,對于涉及Model的訪問,都會有智能提示。比如:

      由于有智能提示的支持,可以提高開發效率,并可以避免一些低級的拼寫錯誤。

      雖然前面我們可以從圖片中看到訪問【同一個URL地址】出現【三個不同的頁面】,但它們背后的Controller卻是同一個:

      通過上面代碼可以看到我用了4個[PageUrl],這意味著其實我可以使用4種不同的URL都能訪問到這三個頁面, 而且每一個URL都會根據當前用戶所選擇的風格,呈現對應的頁面。

      事實上,我還可以為這個Action指定更多的[PageUrl],讓它可以處理更多的URL。關于[PageUrl]的使用與設計目的,請繼續往下閱讀。

      關于URL路由

      隨著 .net framewrok 3.5 的問世,微軟發布了一個【ASP.NET 路由】組件,它的出現給當時的URL優化方法提供了另外一種選擇, 不僅如此,它還提供了一些URL重寫組件沒有的功能:生成URL 。

      隨著AP.NET MVC的出現,【ASP.NET 路由】成為此框架的直接依賴組件,我們很難有其它的選擇, 而且,想不用都不行。

      有趣的是:【ASP.NET 路由】這個后生小子的出現,并沒有很好地遵守ASP.NET制定的一些規則, 其中最為明顯的是:它跳過了【處理器的映射】階段,導致ASP.NET MVC在支持Session時,很為難。 直到最后ASP.NET 4.0,微軟修改了Session的部分實現方式,這樣ASP.NET MVC才能最終借此機會解決Session的完整支持問題。

      ASP.NET 路由雖然可以生成URL,但它引入了RouteData的概念,要想支持它,需要在框架層面上做許多基礎工作。

      而且,我認為:
      1. 并不是每個網站都需要這種技術,對于不需要URL優化的網站來說,URL路由的使用只是白白地浪費性能。
      2. 另一方面,即使需要URL優化,我們還有眾多的URL重寫組件可供選擇,這樣可以不用改變現在構架。

      因此,MyMVC雖然不支持URL路由,但并不表示不能實現URL優化。

      在MVC思想中,Controller應該是處理請求的地方,也是最先運行的部分。 然而在傳統的WebForm編程模型中,aspx頁面負責處理請求。 因此,必須采取一種方式讓最先處理請求的地方從aspx頁面中轉移,并能提前執行。

      而且,將代碼從頁面移出還有另外二個好處:
      1. 被移出的代碼肯定是與UI部分無關的,因此,會比較容易測試。
      2. 代碼與UI的分享也意味著:可以根據運行條件,有選擇地將結果交給不同的View來呈現。

      考慮到Action可以選擇將結果交給不同的View來呈現,而Session也需要支持的問題, 最終我決定,在框架內部使用一個專門的HttpHandler來執行用戶的Action,根據Action所要求的Session支持模式, HttpHandlerFactory創建不同的HttpHandler來支持。由于需要使用HttpHandlerFactory,所以必須在web.config中注冊。

      配置MyMVC框架

      MyMVC在使用時,需要在web.config中簡單的配置:

      <httpHandlers>
          <add path="*.aspx" verb="*" type="MyMVC.MvcPageHandlerFactory, MyMVC" validate="true"/>
      </httpHandlers>
      

      如果使用IIS7,則參考以下配置:

      我們可以把MvcPageHandlerFactory理解成MyMVC在ASP.NET管線的入口。

      注意:
      1. 上面的配置代碼中,選擇aspx這個擴展名并不是必須的,您也可以選擇喜歡的擴展名。
      2. 如果不喜歡擴展名的映射,可以使用HttpModule,MyMVC中提供的方法也能替代這個過程。

      映射處理器(入口)

      在web.config中注冊MvcPageHandlerFactory后,所有符合條件的請求將會進入MvcPageHandlerFactory。
      我們來看一下MvcPageHandlerFactory的實現代碼:

      從代碼中可以看到,MyMVC首先會根據當前的請求地址查找有沒有一個Action可以處理它,如果沒有,則采用ASP.NET默認的方式來處理。 因此,把【*.aspx】交給MvcPageHandlerFactory是不會有問題的。

      說明:創建一個空殼類型AspnetPageHandlerFactory的原因是:不能直接調用PageHandlerFactory的構造函數。

      內部初始化

      MyMVC在第一次處理請求時,要做一個初始化的過程,這個過程是由MvcPageHandlerFactory中的一個調用引發的:

      
      // 嘗試根據請求路徑獲取Action
      InvokeInfo vkInfo = ReflectionHelper.GetPageActionInvokeInfo(virtualPath);
      
      

      ReflectionHelper有個靜態構造函數,雖然上次我已貼出它的代碼,但那只是部分代碼,以下才是完整的初始化代碼:

      從以上代碼可以看出,在初始化時,MyMVC加載了全部的PageAction ,而AjaxAction卻沒有采用這種方式來實現,為什么呢? 請繼續閱讀。

      從URL到Action的映射過程

      前面我們看到了MyMVC的初始化過程,其實是在ReflectionHelper的構造函數中完成的。 在這個初始化之后,MvcPageHandlerFactory調用ReflectionHelper.GetPageActionInvokeInfo(virtualPath)便可以得到要調用的Action的具體描述。 我稱這個過程為:從URL到Action的映射。

      GetPageActionInvokeInfo方法的實現代碼如下:

      在介紹這個映射過程之前,讓我們再來回顧一下Action的聲明代碼:

      通過ReflectionHelper構造函數中所完成的初始化過程,每個Action的描述會根據[PageUrl]的數量而生成多個字典條目, 因此,在GetPageActionInvokeInfo的實現過程中,也只是簡單的查找了這個字典而已,就可以得到所需要的調用信息,從面完成映射的過程。 整個過程可以用以下圖形來表示:

      在上面的示例中,我使用了"/mvc/Customers"這種URL,顯然它并不符合我在web.config中為MvcPageHandlerFactory注冊時所指定的URL模式要求。 那么,又該如何處理呢?

      雖然這種URL雖然沒有擴展名,但我仍然可以通過配置httpHandler的方式來解決,下面的配置就是我們需要的:

      在介紹MvcPageHandlerFactory時,MyMVC提供了另一個方法TryGetHandler供外部使用。 因此,在示例網站中,我還可以在Global.asax中調用這個方法來解決前面的那個問題:

      對于切換HttpHandler的操作,我有以下建議:
      1. 盡量放在HttpModule中去實現。因為可以通過修改配置來切換規則(啟用或者禁止),所以會比較靈活。
      2. 如果可以通過HttpHandler映射能實現的,盡量首選HttpHandler映射方式。原因:更快,更標準。

      PageUrl的設計思想

      在前面的示例代碼中,我為一個Action添加多個[PageUrl],來標記這個Action可以處理多個URL, 因此,一個Action能處理哪些URL是通過指定[PageUrl]來實現的。

      為什么要叫【PageUrl】?
      我想或許有些人會有這個疑問。
      下面我就來回答這個問題,也可以讓大家了解我設計PageUrl的原因:
      1. 我們請求一個URL通常是為了得到一個頁面顯示,因此可以認為一個URL最終可以表示成一個頁面。
      2. 我也想過使用[Url]這種名稱,但感覺太短了,而且Ajax請求也有URL,那么必須顯式地加以區分。
      所以,我最終決定使用[PageUrl]這個名字。

      在Ajax部分,我認為通常只需要完成獲取數據以及處理提交數據的功能就可以了。 因此,絕大多數情況下是不要需View的,而且,一個功能與一個URL對應,這樣還可以簡化問題。 所以,在Ajax部分,我提倡在URL中直接指出要調用哪個Controller中的哪個Action。

      在Page部分,事實上也需要一個Action,本來也是可以繼續使用這種做法的, 不過,我并沒有這種做,理由如下:
      1. 我們創建View其實也是創建Page,使用Page的路徑不是更好嗎?而且WebForm的粉絲或許會更喜歡。
      2. 多URL的匹配功能。后面會有詳細說明。

      由于以上種種原因,我將[PageUrl]設計成與[Action]是獨立關系,并且[PageUrl]可以多次指定的。

      注意:
      1. Url參數中指定的字符串,可以對應一個aspx頁面。也可以不對應aspx頁面。
      2. Url參數中,不要包含QueryString,否則根本不能匹配。
      3. 如果您使用URL重寫組件,那么此處應該是重寫后的路徑。

      由于我在MvcPageHandlerFactory中使用ASP.NET框架傳入的virtualPath并不包含查詢參數, 因此,把它理解成頁面路徑也是非常合適的。

      多URL的匹配功能

      或許有些人認為多URL匹配一個Action是沒有意義的,比如下面的這個Action會更符合常理:

      是的,通常情況下,一個Action處理一個URL也是較為常見。
      但仍然有二種情況需要這個功能。首先來看下面的示例:

      代碼所涉及的4個頁面在呈現時,由于并不需要數據,但為了能夠實現多樣式的支持,它們可以共用一個Action,因此這里只是切換一個View的路徑而已。

      理解上面那句話,可能還需要知道StyleHelper的實現代碼:

      示例網站的目錄結構如下圖:

      在示例網站中,由于三種風格的截然不同,尤其是在功能與HTML結構上就完全不同,因此根本不可能通過CSS或者SKIN的方式來解決, 所以我為三種風格創建了三個目錄,分別存放相應的頁面文件。 最終根據用戶的選擇(Cookie)來決定使用哪個目錄下的頁面來呈現。

      用戶設置風格的JS代碼如下,

      服務端的C#代碼如下:

      說明:CookieHelper是設計成支持單元測試的,所以不要懷疑這里的代碼不符合MVC,后面會專門談它。

      所以,在這種情況下,多個URL映射到一個Action是有意義的。這是【多URL的匹配功能】的第一個用途。

      解決老的URL兼容問題

      在一個網站的成長過程中,一般會有重構的過程。在重構過程中,或許會刪除以前的某些頁面,或許調整URL格式。 然而,用戶也可能會收藏這個網站的鏈接,但由于頁面重構了,老的鏈接可能會因此而失效,造成404錯誤。 此時就要解決URL的兼容問題。

      在ASP.NET中,我們可以在web.config配置urlMappings節點來做這樣的映射轉換。 還有另一種方法是,創建一個HttpModule專門判斷是否在請求一些老的URL,如果是,則重定向到新的頁面。 總之,不管使用哪種方法,都需要為每個傳入請求檢查URL是否是老格式的URL, 這個過程會根據一個列表來逐一檢查,不過,可惜的是:絕大部分請求可能都是新的URL格式, 而那些兼容方案無疑會浪費很多的CPU資源。

      在MyMVC中,可以簡單地處理這個問題,就像下面的這個示例一樣:

      這個“客戶管理”頁面可能經過了多次重構,沒關系,只要把各個版本的地址用[PageUrl]標識出來就可以了,完全不用前面所說的兼容方案, 因此,在URL的兼容處理上沒有任何負擔,也不會影響性能。

      說明:[PageUrl]的順序并不重要,可以隨意調整。

      對身份認證的支持

      MyMVC也支持一些基本的身份認證,可以通過在Action方法中添加[Authorize]修飾屬性來指示。
      AuthorizeAttribute的實現代碼如下:

      認證檢查發生在調用Action之前,代碼如下:

      下面的示例代碼演示了它的用法:

      注意:
      1. 如果一個Action沒有使用[Authorize],則表示允許任意用戶訪問(包括未登錄用戶)。
      2. [Authorize]對于AjaxAction仍然有效。

      View的設計方式

      在MyMVC中,View采用了ASP.NET Page,不過,我并不建議使用CodeFile文件。 不使用CodeFile文件,我想這是很多喜歡WebForm的人不能接受的。 他們更愿意在CodeFile文件中獲取數據,綁定數據,響應事件,處理用戶的提交數據。 也正是由于這個原因,才會讓其它人認為WebForm是一種對單元測試極差的編程模型。

      這里我要表達一下我的觀點:代碼是否可支持單元測試,這其中最主要的原因還是開發人員自身造成的, 框架的選擇只是起到促進或是部分限制的作用。 就算讓一些人使用ASP.NET MVC,他們所編寫的代碼未必就能支持單元測試, 有些人實在太依賴于HttpContext.Current,甚至在ASP.NET MVC中還在寫這種代碼。

      好吧,還是回到Page的設計這個話題上來。MyMVC所提倡的做法與ASP.NET MVC的做法類似, 那就是直接在Page中采用內聯的方式顯示數據,而不是在CodeFile中綁定數據。 許多人一看到ASP.NET MVC的這種內聯寫法,感覺又回到了ASP時代,認為是在倒退,其實這只是表面現象。 表面的背后是:代碼遠離了UI。,也可以理解成:邏輯遠離了UI。 這也是正是ASP.NET MVC一直所提倡的:分離關注點。 在新的開發理念中,原來的Page分解成View和Controller,在實現它們時,只關注自身那一部分就可以了, 因此,如果單看Page時,可能是會有前面所說的那種感覺。 另一方面,由于代碼遠離了UI,或許可以有更多的機會重構它們,使它們的重用性更高。

      下面還是來回顧一下MyMVC中Page的代碼:

      此時,對于呈現所需的數據可以直接從Model對象中獲取,但要求在Page指令中指出Model的類型,這樣還可以有智能提示的優點。 如果頁面需要顯示數據,請務必從MyPageView<>繼承,它的實現代碼如下:

      其實也就是一個簡單的類型,包含了Model這個屬性而已。 至于MyBasePage的實現代碼,我們可以忽略它,它是直接從System.Web.UI.Page繼承的。

      再來一段用戶控件的代碼:

      基本上,與Page的開發方式差不多,只是基類換成了MyUserControlView<>而已。

      在這里我認為要補充一點的是:
      與ASP.NET MVC不同,MyMVC不提供任何HtmlHelper。
      我認為HtmlHelper與MVC思想完全沒有關系,因此不提供這些方法。
      另一方面,很多人希望更好地控制HTML代碼,因此就更沒必要提供這些方法了。
      如果您認為需要一些必要的HtmlHelper方法,那么可以實現自己喜歡的HtmlHelper類庫。

      最后我想說的是:頁面繼承泛型類,還需要一些額外的處理。比如下面的代碼:

      
      Inherits="MyPageView<CustomersPageModel>"
      
      

      要讓這種設置能夠通過編譯,需要在web.config中做如下配置:

      
      <pages  pageParserFilterType="MyMVC.ViewTypeParserFilter, MyMVC"  >
      
      

      ViewTypeParserFilter的實現代碼較長,我就不在此貼出了,可以從本文結尾處下載。

      Controller,Action的設計方式

      在MyMVC中,Action分為二種:AjaxAction和PageAction。
      PageAction與AjaxActioin在方法的定義上并沒有什么差異,只要是個public方法就可以了。
      不過,PageAction與AjaxAction不同點在于:
      1. Controller的容器名稱不同,PageAction要求Controller的名字必須以Controller結尾。
      2. 必須有一個有效的[PageUrl]的修飾屬性指出可以處理的URL
      3. Action的名字與URL無關,可以隨意取名。

      在MyMVC中,2種Action還有另一特點是:不區分GET,POST 。
      原因是:我喜歡用JQuery,用它實現客戶端的Ajax時,GET, POST,只是一個參數的差別而已。 另一方面,對于HTML表單來說,GET, POST也只是一個參數的差別,大部分表單也可以通過GET方式來提交,只要您愿意。 所以,我想,既然客戶端可以這樣靈活地切換,服務端也就沒有必要再去做那樣限制。 或許有些人認為區分二者會更安全,但我認為它們對安全性基本上不構成影響。 反而,如果服務端忽略它們,只會讓客戶端更容易調用。

      還有一種情況下可能需要區分二者:請求與提交是同一個地址。
      這應該可以算得上是我在上篇總結的【以服務端為中心的網站】的開發方式。
      事實上,在使用MyMVC的項目中,<form>標簽應該需要手寫,可能更多的時候會提交到另一個地址,
      因為,我更建議使用Ajax方式提交數據。
      所以,最終我決定:MyMVC的Action不區分GET, POST.

      在設計MyMVC時,我一直沒有忘記將View和Controller的分離,而且對于Controller,只有名字上的約束, Action的約束也較少,因此,我們在實現Action時,完全可以把它們獨立到【類庫項目】中,
      就像示例項目這樣:

      這樣做的好處是:測試Actioin會更容易。
      此時網站可能只是一堆aspx,js, css文件。我一直期待能將aspx也交給美工去維護,這樣設計但愿能讓可能性更大一些。

      輸出HTML的方式

      MyMVC提供二種方式在Action中返回HTML,分別是返回PageResult或者UcResult,表示需要呈現一個頁面或者一個用戶控件。 當在Action返回這二種結果時,Action的部分就執行完畢了。 剩下的處理是在MyMVC框架中進行的,MyMVC框架會對這二種結果,以IActionResult接口的方式調用Ouput方法輸出結果給客戶端。
      PageResult和UcResult的實現代碼如下:

      這二個類型的使用方式是一樣的,都需要提供二個參數,第一個參數表示頁面或者用戶控件的存放路徑,第二個參數表示給頁面或者用戶控件所需的顯示數據。 比如下面這個示例:

      設計這二類結果,我的本意是:
      1. UcResult給Ajax請求使用,因為有可能會要求服務端輸出一段HTML
      2. PageResult用于整頁面的響應。

      在MyMVC中,執行頁面或者用戶控件,需要指出頁面或者用戶控件的路徑,而不是采用什么約定關系。
      我認為約定會造成名字耦合,約定也會影響限制靈活,因此,必須明確指定(允許為null)。

      PageResult多用于PageAction,而PageAction又有[PageUrl]來指示可以處理哪些URL,雖然一個PageAction可以處理多個URL, 但通常情況下,還是以一個PageAction處理一個URL的情況居多。此時,MyMVC允許在返回PageResult時, 第一個參數可以設置為null,表示使用當前請求地址。 如果此時當前請求地址有一個aspx頁面與之對應,自然就會方便很多。 可以參考下面的示例:

      在MyMVC框架中,PageResult最終會調用PageExecutor.Render()來獲取頁面的生成代碼,具體過程如下:

      UcResult則會調用UcExecutor.Render()生成用戶控件的輸出代碼,具體過程如下:

      HTML分塊輸出

      注意哦,前面介紹的2個Render方法的可見性都是public,這樣設計的想法是讓框架提供對外生成HTML的能力,或許有些用戶有這樣的需求。 另一方面,或許還有些用戶打算在Action的執行過程中,將原來較大的HTML頁面分塊輸出給客戶端。 BigPipe就使用了這種想法: 整個請求不用等到全部數據獲取成功后一次性輸出,而是將頁面按業務邏輯拆分,并在獲取到相應的數據后,立即向客戶端輸出部分片段。

      其實HTML分塊輸出在ASP.NET中并不是什么新的技術,而是在ASP.NET一出現時就已經存在了, 那就是在輸出的過程中不斷調用Response.Flush();

      由于MyMVC將生成HTML做為一種基礎功能,因此在MyMVC中,只要您調用Response.Flush();便可以方便地實現分塊輸出。 不過,為了讓調用更簡單,我提供了二個輔助方法來簡化這個過程。

      在PageExecutor類型中的ResponseWrite方法:

      在UcExecutor類型中的ResponseWrite方法:

      注意:由于這二個方法在內部使用了HttpContext.Current,因此如果在Action中調用它們,會造成Action不能支持單元測試。

      關于單元測試的支持

      提到MVC思想,我想就不得不談單元測試了。
      因為MVC的主要思想還是想把這三個字目對應的事物分開,以方便開發與測試。 這里面,我認為尤其是View與Controller的分離最為重要,因為有UI的地方比較難測試, 反過來,如果沒有UI的東西就比較容易測試了。

      不過,在ASP.NET中,影響單元測試的不僅僅只是UI元素,還有HttpContxt, HttpRequest, HttpResponse這之類的核心對象。 比如:即使我們將Controller放在類庫項目中實現,但在Action中還在訪問QueryString,Form,甚至發起重定向的請求,你說這樣的代碼如何測試。

      我認為判斷一個方法是否可支持單元測試有一個簡單的辦法:寫個控制臺的程序去調用它,看它能否正常運行。

      通常,用戶的輸入數據主要有三個來源:QueryString, Form, Cookie。而且前二者居多,Cookie則多用于保存用戶偏好設置。 因此,在MyMVC中,可以讓Action不再去直接訪問QueryString, Form,替代的方式是:將要讀取的名字做為C#方法的參數名明確指出。 這樣,Actioin中的代碼就遠離了QueryString, Form。至于Cookie的訪問,MyMVC則提供一個輔助類來支持訪問:

      重定向也是常見的需求。MyMVC則是通過提供RedirectResult來支持的:

      說明:Ouput方法由框架調用,不影響Action的單元測試。
      示例代碼:

      在ASP.NET項目開發過程中,還有一類需求較為常見,那就是:訪問一些當前環境變量。
      MyMVC則是通過以下二個類型來處理的。

      注意HttpContextHelper這個類,我將平時訪問的一些與請求或者與ASP.NET運行環境相關的屬性全部封裝在這里了。 如果不夠,還可以繼續添加。有了這些代碼,我就可以簡單在控制臺程序中調用它們(您也可以移到單元測試項目中):

      用過ASP.NET MVC的人可能會問我:
      為什么不使用System.Web.Abstractions定義的那些類型,那樣不是更容易支持單元測試嗎?
      是啊,我也知道那種做法的好處。但那樣做的工作量也會更大。
      根據目前的MyMVC設計方式,如果要引入HttpContextBase, HttpRequestBase, HttpResponseBase這類對象, 就需要設計Controller基類,并且創建Controller的過程也會比目前復雜, 或者要把ASP.NET MVC那套創建Controller的過程搬過來,否則仍然會不完整。 然而,我還是打算自己再設計另一種簡單的方法 盡可能 地去解決這個問題。 上面的方法就是我的設計,雖然不夠完整,卻是簡單有效的,而且測試代碼也會簡單很多。 另一方面,我不提供Controller基類,但可以設計諸如HttpContextHelper.Current這樣的訪問方式, 最終的結果仍然是可以支持單元測試的,況且HttpContextHelper.Current這種用法也不會讓人難以適應。 不提供還有另外的好處:允許設計自己的基類。

      還有一點要補充的是:MyMVC框架內部也沒有使用System.Web.Abstractions,是的,我知道。
      這也只能說:框架的代碼不能進行單元測試而已。 但不影響用戶的Action代碼的單元測試。
      再說框架中的代碼有些也很難做單元測試,畢竟太依賴于ASP.NET,而且我沒那么多的空閑時間以及驅動力。

      MyMVC還有一個沒有支持的是文件的上傳與下載。
      這里我來說說對于這塊功能訪如何去實現:
      1. 可以直接訪問HttpContext.Current ,并忽略這些代碼的單元測試能力。
      2. 自行實現我前面沒有實現的HttpContextHelper.Current 。
      是的,我的確沒有完成這個功能,而把它留給了用戶,抱歉。

      關于框架代碼與示例代碼

      在本文的未尾,我提供了MyMVC框架的代碼,以及全部示例代碼。

      以前我也提供過我的老版本框架的演示示例, 我認為我已經考慮地相當周到了:
      1. 沒有IIS,沒有VS,一樣可以運行我的DEMO,因為我把FishAspnetLoader放進去了,調用的BAT文件也準備好了。
      2. SQL SERVER如果支持【用戶實例】模式,部署會容易。
      3. 在數據方面,我不但提供了mdf文件,還提供了sql腳本。
      4. 還準備了一些說明文件。

      然而,事實卻沒有我想像那么好,還是有很多人給我發郵件,問我示例為什么不能運行。
      不能運行的環境也是讓我完全沒有想到的:
      1. 有人把它部署到了IIS6,擴展名的映射遇到問題。
      2. 有人把它部署到了IIS7,可我沒有提供對IIS7的配置!
      3. 有人沒有安裝SQL SERVER。這個只能是沒有辦法了!
      4. 有人不能完成示例程序所需的SQL SERVER配置。
      5. 有人用VS2010打開項目并升級了.net版本,遇到一些說不清楚的問題。

      吸取前面的教訓后,這次我的示例采用XML文件做為數據源,而且增加了IIS7的配置。
      不過,有一點我不能替您設置的是XML文件的寫入權限。
      如果數據不能保存,請檢查目錄的寫入權限,此時程序沒有任何提示。

      再補充二點:
      1. 如果您使用VS2010打開示例項目,請不要選擇升級.net版本,不要盲目點擊確定。
      2. 如果在IIS中部署示例網站遇到問題,那么建議使用VS運行示例網站。

      如果您還有配置ASP.NET應用程序的問題,那么請關注我的后續博客。
      下篇博客我打算談一下在部署ASP.NET網站時,IIS6/7 以及SQL SERVER中必須知道的一些設置。

      點擊此處下載示例代碼

      posted on 2012-02-21 21:38  Fish Li  閱讀(63557)  評論(124)    收藏  舉報
      主站蜘蛛池模板: 97亚洲色欲色欲综合网| 国产三级无码内射在线看| 男男车车的车车网站w98免费 | 欧美国产日韩久久mv| 成人免费无遮挡在线播放| 日韩在线观看 一区二区| 国内少妇偷人精品免费| 成人午夜电影福利免费| 一区二区三区精品偷拍| 老熟女重囗味hdxx69| 狠狠色噜噜狠狠亚洲AV| 蜜臀av无码一区二区三区| 天堂av在线一区二区| 成人午夜电影福利免费| 国产做a爱片久久毛片a片| 在线播放国产精品三级网| 日韩中文字幕有码av| 久久亚洲精品中文字幕| 国产精品小视频一区二页| 91高清免费国产自产拍| 丰腴饱满的极品熟妇| 国产亚洲精品久久77777| 偷自拍另类亚洲清纯唯美| a4yy私人毛片| 在线精品国精品国产不卡| av午夜福利一片免费看久久| 国产精品一区二区香蕉| 亚洲精品成a人在线观看| 久久国产精品伊人青青草| 成人AV专区精品无码国产 | 国产精品色呦呦在线观看| 好吊妞视频这里有精品| 久久精品夜色噜噜亚洲aa| 人妻蜜臀久久av不卡| 欧美色综合天天久久综合精品| 久久se精品一区精品二区国产| 亚洲精品综合久中文字幕| 国产一区二区三区色噜噜| 美腿丝袜亚洲综合第一页| 久久影院午夜伦手机不四虎卡| 日本免费精品|