越來越多的我發現自己在我的一些較大的Web項目中丟失了文件。有很多內容要處理 - HTML視圖,幾個派生CSS頁面,頁面級CSS,腳本庫,應用程序范圍的腳本和頁面特定的腳本文件等等。幸運的是,我使用Resharper和Ctrl-T 轉到任何自動完成你到任何文件,快速鍵入,成員。令人敬畏的除了當我忘記 - 或者當我不太確定我正在尋找的名字。項目導航仍然很重要。
有時在一個項目工作時,我似乎有30個或更多的文件打開,試圖找到另一個新的文件打開在解決方案通常最終是一個精神鍛煉 - “我在哪里放這個東西?”這是一些猶豫,傾向阻止工作流程的頻繁發生。
為了使客戶端框架和腳本的NuGet軟件包變得更糟,將資料轉儲到通常不使用的文件夾中。我從來沒有在MVC中的“內容”文件夾的粉絲,這只是一個空白的層,不能用於很多目的。這通常是我在每個MVC項目中的第一件事。對我來說,項目根是一個網站的實際內容的地方 - 是否真的需要添加另一個文件夾來強制使用每個資源的另一個路徑?它是丑陋的,也是低效的,因為它為您嵌入頁面的每個資源鏈接添加了額外的字節。
備擇方案
最近我一直在玩不同的文件夾布局,發現移動我的奶酪實際上使得項目導航更容易。在這篇文章中,我展示了一些我發現有用的東西,也許你會發現一些這些有用的東西,或至少得到一些想法可以改變,以提供更好的項目流程。
我一直在做的第一件事是添加一個根代碼文件夾,並將所有服務器代碼放入。我將Web項目根文件夾視為Web根文件夾的大粉絲,所以所有內容來自根,而不需要像Content文件夾那樣進行嵌套。通過將所有服務器代碼移出根樹(代碼除外),當您刪除Controllers,App_Start,Models等並將其移動到代碼下方時,根樹將立即變得很干凈。是的,這為服務器代碼添加了另一個文件夾級別,但它只會在一個地方留下代碼相關的東西,這更容易來回跳轉。另外,我發現自己在服務器端代碼上做得更少,而且客戶端代碼我想要與之分離的服務器代碼。
根文件夾本身就作為根內容文件夾。具體來說,我有它下面的Views文件夾,以及Css和Scripts文件夾,僅用於保存通用庫和全局CSS和腳本代碼。建立SPA風格應用程序的這幾天,我也傾向於擁有一個應用程序文件夾,在那里我保留我的應用程序特定的JavaScript文件,以及客戶端SPA應用程序(如角度)的HTML視圖模板。
以下是一個相對較小的項目的例子:
目標是保持相關的東西在一起,所以我不會在解決方案中最終跳出來,以獲得具體的項目項目。“代碼”文件夾可能會引起您的一些困惑,並回到非Web應用程序項目中的App_Code文件夾的日子,但是這些天我發現自己的服務器端代碼多了很多,客戶端文件更多 - HTML,CSS和JavaScript。一般來說,我一次處理一個控制器 - 一旦打開它,它通常是唯一的服務器代碼,我正常工作。業務邏輯完全在另一個項目中生效,因此除了控制器和ViewModels之外,還沒有在代碼文件夾中訪問很多代碼。所以把這個從根本上分離出來似乎是一個容易的勝利。
嵌套頁面特定內容
在我現有的很多應用程序中,純粹的服務器端的MVC應用程序可能與某些JavaScript相關聯,我傾向於具有頁面級的javascript和css文件。對於這些類型的頁面,我實際上更喜歡存儲在與父視圖相同的文件夾中的本地文件。所以通常我有一個與同一個文件夾中的視圖名稱相同的.css和.js文件。
這看起來像這樣:
為了使其工作,您還必須在/Views/web.config文件中進行配置更改,因為使用BlockViewHandler阻止訪問該文件夾的內容的Views文件夾。通過將路徑從*更改為* .cshtml或* .vbhtml來簡化修復,以使視圖檢索被阻止:
< system.webServer > < handlers > < remove name = “ BlockViewHandler ” /> < add name = “ BlockViewHandler ” path = “ * .cshtml ” verb = “ * ”
preCondition = “ integratedMode ”
type = “ System.Web.HttpNotFoundHandler ” /> </ handlers > </ system.webServer >
有了這個,從你的意見里面,你可以參考這些相同的資源,如下所示:
< link href =“〜/ Views / Admin / QuizPrognosisItems.css” rel =“stylesheet”/>
和
< script src =“〜/ Views / Admin / QuizPrognosisItems.js”> </ script >
工作正常 Views文件夾中的JavaScript和CSS文件就像.cshtml文件一樣部署,也可以從該文件夾引用。
這樣做並不像Visual Studio那么簡單,不幸的是,直接從VS IDE中獲取文件嵌套是不方便的(您必須修改.csproj文件)。
然而,Mads Kristensen有一個很好的Visual Studio加載項,通過一個快捷菜單選項提供文件嵌套。使用此選項可以選擇每個“子”文件,然后將其嵌套在父文件下。在上面的情況下,我選擇.js和.css文件並嵌套在.cshtml視圖下。
我甚至想把controller.cs文件放到Views文件夾中,但是這可能有點太遠了:-)但是,由於Visual Studio不會發布.cs文件,編譯器不會關心文件的位置。有很多選擇,如果你認為這將使生活更輕松,另一個選擇是幫助將相關事情組合在一起。
這有什么缺點嗎?可能 - 如果您使用ASP.NET Bundle或Grunt / Gulp等自動化小型化/包裝工具與Uglify,將腳本和css文件分組進行分組變得更加困難,因為您可能會最終查找多個文件夾而不是單個夾。但是,再次,這是一個一次性的配置步驟,易於處理,而且更少的侵入性,然后不斷搜索項目中的文件。
客戶端文件夾
上述屏幕截圖中顯示的特定項目是傳統的服務器端ASP.NET MVC應用程序,大多數內容呈現在服務器端的Razor頁面中。在這些頁面上也有相當數量的客戶端的東西 - 具體而言,這些頁面中的幾個是自包含的單頁角度應用程序,處理1或可能2個單獨的視圖,我上面顯示的布局真的專注於服務器端其中有Razor視圖與相關的腳本和css資源。
對於以客戶為中心並具有更多腳本和基於HTML模板的內容的應用程序,我傾向於為服務器組件使用相同的布局,但是客戶端代碼通常可以不同地被分解。
在SPA類應用程序中,我傾向於遵循App文件夾方法,其中所有使SPA應用程序的應用程序結束於App文件夾下方。
這是我看起來像這樣 - 這是一個AngularJs項目:
在這種情況下,App文件夾包含應用程序特定的js文件以及加載到此單個SPA頁面應用程序中的部分HTML視圖。
在具有與特定部分視圖相關聯的控制器的特定Angular SPA應用程序中,我更願意保留與視圖相關聯的腳本文件 - 在這種情況下為Angular Js控制器 - 與實際部分。再次,我喜歡視圖與視圖關聯的主要代碼,因為90%的UI應用程序代碼被寫入這兩個文件之間。
這種方法運行良好,但只有控制器與部分數據相當緊密。如果您有很多更小的子控制器或許多指令,視圖和代碼之間的對齊更加分段,這種方法開始分崩離析,您可能會更好地使用js文件夾中的單獨文件夾。遵循Angular約定,您將擁有控制器/指令/服務等文件夾。
請注意,我不是說這些方式是對或錯 - 這只是為我工作,為什么!
與Resharper一起跳過項目導航
我已經在項目樹中談了一些項目導航,這是一種常見的導航方式,至少在某些時候我們都使用,但是如果您使用像Resharper這樣的工具,它具有Ctrl-T跳轉到任何東西,您可以使用快捷鍵快速瀏覽並自動完成搜索。
這就是Resharper跳到任何東西的樣子:
Resharper的Goto Anything框允許您輸入並快速搜索整個解決方案的文件,類和成員,這是通過完全傳遞解決方案資源管理器,在您的項目中找到所需內容的一種非常快速而強大的方式。只要你記得使用(有時我不會),你知道你在找什么,它是迄今為止在項目中找到最快的方法。很遺憾,這種簡單的搜索界面不是本機Visual Studio IDE的一部分。
工作你喜歡工作
最終,這一切都歸結為工作流程以及您喜歡的工作方式,以及什么使您*更有成效。遵循預先定義的模式是很好的一致性,只要它們不會妨礙你的工作方式。Visual Studio for ASP.NET MVC中的許多默認文件夾結構在不同的情況下進行了定義。這幾天我們處理的項目內容比ASP.NET MVC最初引入的項目內容多得多,如果項目組織不適合您的工作流程,項目組織肯定是可以得到的。所以看看看什么是好的,什么可以從組織文件不同的好處。
與ASP.NET一樣多的東西,隨着事物的發展和變得越來越復雜,我發現我最終打了一些慣例。好消息是,您不必遵守公約,您可以自由地為您做任何事情。
即使我在這里顯示的內容與會議有所不同,我也不認為任何人都會絆倒這些相對較小的變化,即使在較大的項目中也不會立即弄明白事情的存在。但是,在打破這些慣例之前,盡管如此,如果沒有一個很好的理由來打破這些慣例,或者改變不能提供改進的工作流程,那么這樣做是不值得的。打破規則,但只有有可量化的好處。
您可能不同意我在本文中選擇從標准項目結構中轉移的方式,但也可能會為您提供一些想法,您可以如何混合使您的現有項目流程更好一點,並使其更容易瀏覽為您的環境。



![FileNesting [1] FileNesting [1]](/image/aHR0cDovL3dlYmxvZy53ZXN0LXdpbmQuY29tL2ltYWdlcy8yMDE0V2luZG93cy1MaXZlLVdyaXRlci81NDY0MzA5NDdlMWZfMTE4RjYvRmlsZU5lc3RpbmclNUIxJTVEX3RodW1iLnBuZw==.png)

