使用MvcContrib分離ASP.NET MVC項目


概述

在ASP.NET MVC復雜項目的開發中,隨着項目規模的擴大,我們可能需要對不同模塊按需進行分離。可以使用ASP.NET MVC框架提供的“區域(Areas)”功能來組織項目,具體參見《使用Areas分離ASP.NET MVC項目》。但是從上文可以看出,幾個項目都是圍繞Areas,通過“Build Event”最后整合到一起,總是有些“藕斷絲連”的感覺。可以說,通過Areas獨立出來的項目,並沒有達到徹底的分離。在上文的評論中,有朋友指出可以使用MvcContrib,於是學習了一下。

MvcContrib(Portable Area)可以將一個MVC項目里的所有內容(包括Views,Controllers,Scripts等)都編譯到一個dll里面。如此一來,該MVC項目就可以作為一個“插件(或部件)/Plugin(or Widget)”為其他項目使用,具有很強的重用性。

環境准備

仍然考慮上文中的場景:將面向用戶的前台和面向管理員的后台進行分離。

  1. 首先新建一個ASP.NET MVC3項目MyPortableAreaDemo(前台項目),項目模板選擇“Internet Application”,視圖引擎選擇“Razor”。
  2. 新增一個空的MVC項目MyPortableAreaDemo.Admin(后台項目),刪除Global.asax.
  3. 在MyPortableAreaDemo.Admin項目上面右鍵,添加一個類AdminAreaRegistration.cs並輸入以下內容:
        public class AdminAreaRegistration : AreaRegistration
        {
            public override string AreaName
            {
                get
                {
                    return "Admin";
                }
            }
    
            public override void RegisterArea(AreaRegistrationContext context)
            {
                context.MapRoute(
                    "Admin_default",
                    "Admin/{controller}/{action}/{id}",
                    new { action = "Index", id = UrlParameter.Optional }
                );            
            }
        }

安裝MvcContrib

使用NuGet為MyPortableAreaDemo.Admin安裝MvcContrib:

2012-6-6 21-52-49

或者在Package Manager Console里面輸入:Install-Package MvcContrib 進行安裝。

2012-6-6 21-59-31

使用MvcContrib

打開AdminAreaRegistration.cs,然后將其基類AreaRegistration修改為PortableAreaRegistration,將RegisterArea方法聲明修改為(重要!):

public override void RegisterArea(AreaRegistrationContext context, IApplicationBus bus)

為默認路由加上命名空間限制,並且在RegisterArea方法中加入RegisterAreaEmbeddedResources()。現在看起來應該是這樣子:

2012-6-10 19-39-00

在MyPortableAreaDemo.Admin/Controllers下面添加一個HomeController和Index的Action,並且添加相應的View文件:

2012-6-10 19-40-13

下面這一步非常重要:

將所有的css,js,image靜態文件的屬性-生成操作(Build Action)選擇“嵌入的資源(Embedded Resources)”。這意味着這些靜態文件都將被編譯進dll文件里面,而不是像之前那樣,以單獨物理文件存在。這樣做的好處是整個項目里面的結構都是相對固定的,一個dll就包括了整個工程里的所有內容,可復用性高。缺點是每次修改了這個項目里的內容(即便是修改js或view等靜態內容),也必須要重新編譯整個項目。這就要看個人的取舍了,你可以權衡這樣做是否值得。

2012-6-10 17-34-03

現在在主項目里面引用Admin項目。在主項目里面添加一個叫做Areas的文件夾,並將MyPortableAreaDemo/Web.config復制到新建的Areas文件夾下。

為什么需要這樣做呢?這是因為Admin項目里的Portable Area在被主項目加載時,會被映射到這個Areas文件夾里,此時Controller就會在Areas下面去尋找對應的Views(而不是在主項目里尋找)視圖。

好了,現在編譯(記住,Portable Areas項目修改任何內容都必須重新編譯!)整個解決方案,從主項目啟動后訪問:/Admin/Home/Index,如果一切順利,你會看到:

2012-6-10 18-49-47

訪問靜態文件

前面我們提到所有的靜態文件(js,css,image)都被編譯到了dll中,那么我們如何訪問這些靜態內容呢?嘗試直接訪問/Admin/Scripts/jquery-1.4.4.min.js,瀏覽器會提示“無法找到資源”。因此我們還需要修改一下AdminAreaRegistration.cs,添加如下路由:

            context.MapRoute(
                "ResourceRoute",
                base.AreaRoutePrefix + "/resource/{resourceName}",
                new { controller = "EmbeddedResource", action = "Index" },
                new[] { "MvcContrib.PortableAreas" }
            );

這段路由的意思是將所有的靜態資源都交給MvcContrib.PortableAreas.EmbeddedResource去處理,因此現在我們可以使用:/Admin/resource/Scripts.jquery-1.4.4.min.js來訪問jquery。注意其中的“Scripts.jquery-1.4.4.min.js”中間是“.”而不是“/”。

在View視圖中,還可以用<%= Url.Resource("Scripts.jquery-1.4.4.min.js") %>的訪問形式。Url.Resource()方法集成在MvcContrib中。

通過這種方式,我們可以完全控制程序集中的所有靜態內嵌資源,如果想通過訪問物理文件的方式訪問內嵌資源,可以添加如下路由:

            //Scripts
            context.MapRoute(
                AreaName + "_Scripts",
                base.AreaRoutePrefix + "/Scripts/{resourceName}",
                new { controller = "EmbeddedResource", action = "Index", resourcePath="Scripts" },
                new[] { "MvcContrib.PortableAreas" }
            );
            //Content
            context.MapRoute(
                AreaName + "_Content",
                base.AreaRoutePrefix + "/Content/{resourceName}",
                new { controller = "EmbeddedResource", action = "Index", resourcePath = "Content" },
                new[] { "MvcContrib.PortableAreas" }
            );

注意其中的resourcePath的值。現在我們就可以直接使用/Admin/Scripts/jquery-1.4.4.min.js這種方式來訪問內嵌資源了。

總結

通過MvcContrib Portable Area我們可以將MVC項目進行有效分離,並且使用內嵌資源的方式,將整個分離出來的項目編譯成一個dll,可以隨意復制引用,可重用性較好。

但是,這種方式也存在以下不足之處:

  1. 由於所有靜態資源都被編譯到dll中,這就不可避免造成dll的體積變得越來越大,尤其在圖片比較多的情況下更為明顯。
  2. 靜態資源的訪問形式。如果上面的Content,Scripts文件夾下面還有子文件夾(這是很常見的情形),只能通過resource的方式訪問,而不能通過偽物理地址的方式,不算太友好。

基於上面兩點,建議只將view視圖文件作為內嵌資源編譯到dll中,所有的靜態文件(js,css,image)可以放到主項目中,直接訪問。或者放在Admin項目里面,通過Build Event的方式同步到主項目相應目錄里(參考上文)。

接下來准備研究一下nopCommerce的項目分離方式,插件式開發,希望每天都能進步一些。

項目源碼下載:http://files.cnblogs.com/dingji/MyPortableAreaDemo.zip


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM