2013年7月5日 星期五

ASP.NET MVC 使用 Area - 以 Backend 後台為例

對於開發 ASP.NET WebForms 的程式設計人員來說,假如網站規模不是很大,但又需要一個後台管理功能時,通常都會在網站根目錄下建立一個「Backend」或「Admin」目錄,然後所有的後台管理功能頁就會全部放在這個目錄裡,而開發網站改使用 ASP.NET MVC 時,對於此技術不甚了解的朋友就會直接在 Controllers 目錄下去建立 Backend 子目錄並建立相關的 Controller 檔案(例如 AdminController.cs),至於 View 的部份就會選擇使用「手動」建立的方式直接在 Views 目錄下建立子目錄「Views/Backend/Admin」,而當執行時就會出現找不到檢視檔案或是無法執行的錯誤。

用 ASP.NET MVC 所開發的網站可以使用 Areas 技術,增加一個區域,然後把後台相關功能都放在這裡,除了後台功能可以使用 Area 外,也可以依照網站的功能不同,將不同的功能性質的網頁使用 Area 來做開發,例如會員中心也適合使用 Area 。

以下簡單說明怎麼在 ASP.NET MVC 使用 Area,這可是相當基礎的技術喔。

 


如同前言所講的,在開發 ASP.NET WebForm 網站時,如果有需要做一個後台管理功能,我們可以在網站根目錄下建立一個「Backend」目錄,然後將後台功能都放在這個目錄裡,

image

如此一來,要進入這個網站的後台管理功能只輸入類似這樣的目錄「http://www.ooo.xxx/Backend/」就可以進入,

image

不過通常規模比較大的網站並不會把前後台都放在同一個網站專案底下,而是會各自獨立一個專案來做開發,這樣的形式在使用 ASP.NET MVC 開發網站也是一樣的,但如果網站規模不是很大,不想分成兩個網站專案,想要把前後台放在一起,然後也想要用路徑區別的方式,一樣使用「http://www.ooo.xxx/Backend/」這樣的路徑進入後台,又該怎麼做呢?

 

如果開發人員對於 ASP.NET MVC 不是很熟悉,所以會很直覺的在 Controllers 目錄就建立了子目錄「Backend」然後增加一個「AdminController.cs」,

image

而如果 AdminController 所對應的 View 並不是透過功能表使用「加入檢視」的方式,而是自己用手動方式去增加 View 檔案,然後又依照目錄階層的概念在 Views 目錄下去手動增加「Views/Backend/Admin/」目錄以及「Index.cshtml」檔案,

image

當以為一切就緒並且覺得如此簡單的功能應該可以輕鬆達成,執行的結果卻是……

image

於是可能會跑去增加 RouteConfig.cs 的 route 設定,

image

但執行後卻發生這樣的錯誤,

image

於是就直接在 AdminController 的 Index Action 裡將 return View(); 修改為直接指定 View 的位置,

image

而這樣修改過後就可以正常執行並顯示了….

image

但這樣子的作法,對嗎?

這樣的作法並非正確,因為在 Controllers 裡不需要為了想要在網址裡顯示 Backend 路徑名稱就去建立一個「Backend」的子目錄,而相對應的 Views 目錄裡,也不需要去為了同樣的理由而建立「Backend/Admin」目錄,ASP.NET MVC 所開發的網站,網址的呈現以及經由網址去執行,主要是依據 Route 的設定,這也就是為什麼上面有一個修改是增加 Route 設定後就可以執行 AdminController(雖然還找不到 Index.cshtml),而找不到 Index.cshtml 的錯誤訊息裡可以看出 ASP.NET MVC 在 Render View Page 時是怎麼尋找要顯示的 cshtml 檔案,

image

會先 Views 目錄裡 AdminController 所要對應的「~/Views/Admin」目錄找起,而不是從「~/Views/Backend/Admin」這個目錄找,在 「~/Views/Admin」目錄找不到目標檔案後就會去找「~/Views/Shared」目錄,而尋找的順序則是會先以 WebForm ViewEngien 的 aspx ascx 檔案開始找,然後才是 Razor View Engine 的 cshtml vbhtml。

所以我們可以把網站的 Controllers 與 Views 內容做個修正,而 Route 設定就不做更改,依然保留「Backend」的 RouteMap 設定,

image

而 AdminController 裡的 Index Action 所 return 的 View 不用再去指定 Index.cshtml 的路徑,

image

執行結果

image

 

然而當網站裡的 Controller 檔案越來越多時,這時候就會發現到前後台的 Controller 與 View 都混在一起,在管理與編輯程式、頁面時候容易造成混亂,甚至於在多人共同開發的時候就 容易產生問題,為了避免這樣的情況發生,可以使用 Area (區域)技術,在 MVC 網站專案裡加入 Area ( 區域 ),將 Backend 相關的 Controller 與 View 都集中在 Area 當中,而 Route 路徑也不需要另外去做設定,因為 Area 的 route 就有路徑的設定了。

依照下圖的操作順序加入區域,

image

輸入區域名稱「Backend」

image

完成 Area「Backend」的建立

image

BackendAreaRegistration.cs 內容

image

接下來先把原本在 App_Start 裡的 RouteConfig.cs 所增加的 route 設定給移除,

image

接著就是把原本在 Area 外面 Controllers 目錄的 AdminController.cs 給搬到 Backend Area 下,但是這邊要注意,不是說檔案直接搬到 Backend Area 的 Controllers 目錄下就可以,要注意有 Namespace 的差異,所以建議先在Backed Area 的 Controllers 目錄下新增同名的 Controller 檔案,然後把原本 Controller 的程式內容給複製過去,最後再把外面的 Controller 檔案移除,

image

而 View 檔案也是可以直接搬移過去,不過要注意如果所使用的主版頁面,如果 Area 的 Shared 目錄有一個主版頁面檔名與外面 Shared 目錄的主版頁面檔名是一樣的話,在 Area 的 View 會優先選用 Area Shared 目錄下的主版頁面,另外一些路徑的問題也需要多加留意。

在建立 View 檔案的時候,要注意 View 的目錄名稱是否對應到 Controller 名稱,另外就是在 Views 目錄下除了 Shared 之外的目錄,都是對應 Controller 名稱的,不需要為了增加所謂路徑而去「手動」建立子目錄。

在 ASP.NET MVC 4 之前,加入檢視的方式大多都是在 Controller 的 Action 方法內按下右鍵,然後在顯示的功能表裡點選「加入檢視」,就可以一併建立 Admin 的 View 目錄(如果尚未建立該目錄)與 Index.cshtml 檔案,

image

image

image

不過這個方式在 ASP.NET MVC 5 之後就會以 scaffold(支架)的功能所取代,這邊稍微提一下,以後有機會再寫一篇 ASP.NET MVC 5 的網站建立介紹。

 

完成以上的修改之後,就可以重新建置網站然後執行,最後執行結果如下:

image

 

最後再來看看使用 Area 後的網站架構與內容,

image

 


這邊介紹了 ASP.NET MVC 的 Area 技術基本應用,以 ASP.NET MVC 開發時會經常使用到 Area,將相同功能的 Controller 給集中在 Area 之中,一個網站可以依據需求或是功能模組的不同而建立多個 Area,這麼一來就可以讓網站裡的 Controller 與 View 全部擠在一起而顯得雜亂,在管理上以及多人開發時就可以方便管理與區別。

 

延伸閱讀:

MSND - 逐步解說:使用區域組織 ASP.NET MVC 應用程式

 

以上

12 則留言:

  1. 把我弄錯的東西全部寫了出來XDD
    謝謝大大的文章~!!

    回覆刪除
  2. 您好:
    您的例子中 建立Area後的網址為 【XXXXX/Backend/Admin/Index】 ,那想請教是否可以藉由RouteArea 或RoutePrefix 將網址
    改成【XXXX/Backend】,該怎麼做呢? 謝謝

    回覆刪除
    回覆
    1. Hello,
      你有試過嗎
      其實這部落格裡也有兩篇說明 Attribute Routing 的文章,其中第二篇所描述的應該跟你想要的情境是差不多的。
      http://kevintsengtw.blogspot.tw/2013/12/aspnet-mvc-attribute-routing.html
      http://kevintsengtw.blogspot.tw/2013/12/aspnet-mvc-attribute-routing_17.html

      刪除
  3. 您好,在一年後拜讀到您這篇文章著實幫助不少
    另外對此有一個疑問是在robot.txt中應該要以route來設定還是依照資料夾來設定呢?

    回覆刪除
    回覆
    1. Hello,
      請參考以下連結的文章
      KingKong Bruce記事: ASP.NET MVC 5 如何正確加入robots.txt?
      http://blog.kkbruce.net/2015/01/aspnet-mvc-5-correct-add-robots-txt.html#.V4TKErh97Dc

      刪除
    2. 抱歉,小弟看完您的文章以及保哥的參考資料後還是有點疑惑
      因我有MVC4或5,主機環境有IIS6 7 8(三台server)的搭配組合
      看文章的意思是其實我不需要設定web.config也不需要另外設定路由,跟MVC版本還有IIS其實也沒關係
      (IIS6的isapi.dll可能有點協助關係?)
      只需要在robots.txt中設定的是/Backend/就可以運作嗎?
      我不太懂的部分是MVC背後這個流程怎麼知道robots.txt並把內容回應出去
      對不起我不知道我這樣描述明不明確QQ

      刪除
    3. 你的提問內容跟這篇文章並無直接相關性
      我建議你去問別人吧
      因為我不清楚你要問的是什麼,已經偏離這篇文章的內容了

      刪除
  4. 請問一下,把後台網站寫到Area是不是意味著發行整個Web Project時,前後台網站都一起對外公開了呢?
    如果客戶需要後台網站不想對外公開讓人存取,該怎麼辦呢?

    回覆刪除
    回覆
    1. 你沒有認真看文章喔,文章標題已經說明了文章內容的走向,用 asp.net mvc 的 Area 功能建立路徑名稱為 Backend 的後台管理功能,當初會寫這篇也是因為看到有人直接開了一個名為 BackendController 控制器類別,然後把一堆後台功能放進去,所以才介紹使用 Area 的做法。

      文章裡有一段提到:
      通常規模比較大的網站並不會把前後台都放在同一個網站專案底下,而是會各自獨立一個專案來做開發,這樣的形式在使用 ASP.NET MVC 開發網站也是一樣的...

      看客戶需求,如果客戶不希望由 internet 就能連到後台,那就另外建立後台的網站,放在只能用 intranet 才能連到的 server 上。
      如果 user 要能夠由 internet 去連後台,那麼安全機制就要做好。

      刪除
  5. 您好,請問若前台與後台都會有登入頁面,但不要共用登入的Cookie
    請問有任何方向可以提供去解決此問題嗎?謝謝!

    回覆刪除

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。