[Asp .Net MVC] Controller and View 的應用

[Asp .Net MVC] MVC 架構與說明 ( 以Asp .Net MVC C# 為例 )

本篇除了簡單說明 MVC 概念,也進一步說明 Asp .Net MVC Web Application 專案架構。
呈現環境為visual studio 2015 community:
連結:https://www.visualstudio.com/zh-tw/products/visual-studio-community-vs.aspx。

若有觀念錯誤或建議,也請各位先進不吝指導。

介紹

MVC 一種軟體架構模式,把系統分成三個種核心,分別為:Model, View, Controller。
主要將網頁分成邏輯處理(物件操作)、視覺呈現與路由控制(發送、接收請求),各種元件
處理不同的工作,強調職責分離,開發與維護人員可以更快速對於目的與問題,找到該
處理的程式,讓程式的修改與功能擴充簡化,提高程式可用性。

 

在不同的原件中,各有自己的特色:
Model : 包含所有的邏輯、物件,內容豐富。
Controller : 盡量輕量,這裡盡量不撰寫邏輯與物件,而以路由以傳遞資料為主。
View : 僅呈現,故盡量單純(笨笨)的呈現即可。

MVC架構的並不是容易做到,通常需要有良好的設計(或有相當經驗的架構師),才能將
工作分割的相當完美。早期MVC架構推廣相當不易,尤其對於小型專案,開發人員需要
花費大量時間在建構與維護MVC架構,其花費的成本遠大於小型專案的成本。雖然以大
型專案與專案長遠發展的角度來說,MVC架構是非常有幫助的,但入門門檻過於高,而
導致許多專案打退堂鼓。

但近年來,由於開發環境的成熟與各家語言、框架、套件等日新月異,MVC架構之維護
方式日趨簡易且一致,讓中、小型專案也不會因為維護複雜度高的缺點,無法導入MVC
架構,MVC架構也逐漸成為近年來開發主流方式之一。

簡單整裡MVC重點如下:

優點:
-使程式結構更加直覺
-增加程式可用性
-程式方便管理
-程式擴充性高
-有例於團隊開發

缺點:
-不適用於小型專案
-管理文件增加
-嚴謹的系統架構與規劃
-需要重覆的測試

下圖為一個示意圖,簡單介紹MVC在整個網頁系統流程:
使用者在網頁(View)表單(請求)送出後,皆會透過 Controller 接收後,決定給哪個model進行
處理。所有需求完成後,Controller 再回傳相對的結果,讓網頁(View)呈現相關資訊。

Asp .Net MVC Web Application 開啟範本專案操作步驟:
請依序下列步驟開啟一個範本專案:
Step 1.開啟 Visual Studio 2015,點選file -> new -> project
Step 2.選擇Web -> ASP.NET Web Application,點選OK
Step 3.點選MVC專案,點選OK,即可開啟範本專案。

Asp .Net MVC Web Application 架構說明:
一開始的範本專案,已經幫開發者做好分類,雖然開發者也可以依循自己的想法去更改
檔案位置,但個人還是強烈建議養成習慣,將各類型程式分類放置。Asp .Net MVC專案
的配置像相當好,開發者可以依循此架構開始專案(如下圖所示)。

個人的習慣除了下圖描述,個人會另開ViewModel放置ViewModel或DTO;另開Service放置
邏輯處理或呼叫API的程式;若撰寫angularjs,會另外建置一個app資料夾,放置相關js。
依據專案越來越大更改架構與配置。

重要的是,希望各個開發者以習慣代替配置,雖然MVC已經很明確將資料配置規定好,
但一個不注意,專案內的程式檔案就會亂放。團隊成員內相同的配置習慣一致,除了讓
專案好維護,在討論開發相關內容的更加順利。故每一位開發者,對於程式命名、配置
養成好的習慣,對專案開發是非常的有幫助的。
Routing Config
我們怎麼知道哪一個網址,對應哪一個 Controller 呢?
在專案中,我們透過 RouteConfig.cs 設定所有網址與Controller之間的對應。(上一篇的最後
,我們教您如何開啟一個範本Web application,我們以這個範本為例來進行說明)
我們可以在專案下找到 App_Start\RouteConfig.cs 這個檔案。

開啟 RouteConfig.cs,我們可以看到預設內容如下:

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

routes.IgnoreRoute 的語法表示不要透過 Routing 處理的網址,下列表示
www.yourdomain.com/xxx.axd/xxx/xxx.. 格式網址不進行處理
(* 表示後面無論接幾個路徑,如:/xxx/xxx或/xxx/xxx/xxx,皆不處理)

routes.MapRoute 的語法表示 routing 的規則:www.yourdomain.com/controller/action/id
第一層為 controller 名稱、第二層為 action 名稱、第三層為 id ;而若沒有controller、action、
id,直皆輸入www.yourdomain.com,預設的對應的路由為 www.yourdomain.com/Home/Index

這裡有一個非常重要的規則,就是順序。 當你的撰寫順序錯誤錯誤,在後面的規則可能永
遠對應不到。當然,不是只有撰寫規則在RouteConfig.cs就好,我們必須於網頁應用程式起
點Global.asax.cs的Application_Start 註冊 RouteConfig.cs 才會啟用,如下圖所示:

Controller
完成了設定,我們要開始建立我們的 Controller 。
Controller程式的命名規則,後面皆需要加上 Controller,如: HomeController

點開 Controllers資料夾,可以看見預設的HomeController。 當中有許多方法,回傳值為
ActionResult,我們稱為Action:
當我們想要呼叫名稱為Index的Action,只需要在網址上輸入
www.yourdomain.com/Home/Index即可;
當我們想要呼叫名稱為About的Action,只需要在網址上輸入
www.yourdomain.com/Home/About即可...
依此類推。

 

每一個 Action 可以對應一個 View, 對應的位置為View資料下的.cshtml檔案:
Controllers\HomeController 裡面的 Index => Views\Home\Index.cshtml
Controllers\HomeController 裡面的 About => Views\Home\About.cshtml
簡單的說,進入不同的Action,就會得到不同的網頁內容。
當你寫好一個Action,你可以右鍵點選這個Action,選擇Add View,Visual Studio會自動
在對應的位置加上.cshtml檔案。

ActionResult
當然,不一定要回傳一個 View (如About.cshtml),你可以回傳一串文字、一張圖片、一
段 javascript 或是儲存很多資訊的json與xml字串,每種ActionResult使用方式不同,可以
參考:ActionResult 。JsonResult範例如下圖所示:

 

參考資料:

1.ASP.NET MVC 開發心得分享 (21):Routing 觀念與技巧
http://blog.miniasp.com/post/2011/08/01/ASPNET-MVC-Developer-Note-Part-21-Routing-Concepts-and-Skills.aspx

開啟範例程式,我們先開啟Views\Home\Index.html 進行改寫,內容如下:

我們增加一個Html form(使用Post方法)、兩個文字輸入框與一個送出按鈕,文字輸入框的
name 屬性,分別為name 與 age。
開啟Controllers\HomeController,我們修改程式內容如下:

我們另外增加了一個Index action,設定接收條件HttpPost (與form的方法相同), 並且給予兩個
傳入參數,名稱分別為 name 與 age(接入參數名稱必須與 input 內的 name 屬性名稱相同,才
能接到傳入參數)。

我們要怎麼確定資料有傳遞進入HomeController呢?
我們可以透過點擊編寫程式碼視窗邊框增加一個中斷點,啟動專案、輸入資料並且送出,
即可將程式執行停留在中斷點,此時只需要將滑鼠移到變數上,即可看見目前的內容值,
確認參數有正確傳遞。

在這個範例中,我們限制限制透過Http Post接收,若對應的方法不正確,會出現404 not found
的訊息。

在Asp .Net MVC中,資料傳遞的方式是透過input name對應進行傳遞,如果遭遇name相同的情
況下,傳入參數會變成list進行傳遞。當然,您如果曾經寫過Web form相關程式,也可以直接
擷取Ruquest的資訊進行處理:您可以參考這篇文章 [ASP .NET] Request.QueryString and Request.Form (ASP .Net MVC Example)

如何從從controller傳遞參數至View進行呈現

在後端,我捫常常需要將處理好的資訊,傳遞到View中進行呈現,常見的傳遞方式與作法
如下:




我們還沒帶入ViewModel的概念,故我們先不介紹ViewModel方法。
我們以ViewBag的方式,介紹如何簡單傳遞資料的方法,ViewBag有個好處,就是不需要處
理型別(dynamic 型別包裝),而取出使用的時候在進行轉換型別即可使用。

我們只需要在相對應的action中輸入ViewBag.變數,即可直接使用,例如:
ViewBag.Name = "Duran";

而在相對應的View上直接輸入@ViewBag.Name,在畫面上,即可直皆印出Duran的文字。

結果

如此一來,您已經可以處理一個簡單的表單送出的資訊,並且回饋簡單訊息給使用者。
當然,這非常的基礎。一般作法會使用ViewModel(DTO)的方式,將資料傳遞到View進行呈
現。透過ModelBinding的方式,可以作到資料驗證、呈現變更、資料過濾...等許多方便的功
能。在某些情境下,我們不需要更改.cshtml,只需更改ViewModel上的filter attribute,即可達
到不同的效果。

整個 View 的基本結構如下圖,可以分成:
1. Cotroller-Action 呈現內容
從前兩篇我們可以知道Controller與View的關係:Views 資料夾配置了許多對應Controller
的子資料夾,而每一個子資料夾的內部,有許多對應action的.cshtml(partial view)檔案。
2. 共用內容
除此之外,在範本專案中,您也可以發現多一個Shared資料夾,與_ViewStart.cshtml、
_Layout.cshtml等檔案。一般來說,Shared資料夾我們會放置一些通用 View,無論是不
是partial view,這些.cshtml檔案可以被其他的View所共用,後續介紹的display template與
editor template 也會放在這裡。

3. View 起點
在View底下,您能找到_ViewStart.cshtml 這支程式,這是所有 View 的起點。而運作流程如下:

點開後可以發現預設內容指向Shared 資料夾的_Layout.cshtml:

4. 整體版面
_Layout.cshtml 這支程式是呈現整個網頁的全貌 (html + css)。
一個現代的網站配置,大概可以分為 header, content, sidebar 與 footer等區塊(如下圖),
依據設計師的規劃,各個區塊有不同的用途與視覺效果。
(理所當然,依照網站呈現設計不同,呈現的樣式也不同,非一定呈現如此)。
而範本程式的配置如下:
_Layout.cshtml內容中,我們能找到 @RenderBody() 這個語法,功能是呈現內容(content):
目的是將 controller\action 所回傳的 view 嵌入在 _Layout 的@RenderBody() 所在位置。如此
一來,外部樣式(header, footer, or side bar)即可共用,網頁切換時,不需要每個畫面撰寫重
複的html,而只須依據不同的controller與action,嵌入不同的 view。

我們也能將其他header, sidebar區塊作為另外建立patial view,再使用 @Html.Partial 與
@Html.RenderPartial語法嵌入。當然,這又是另一種應用了。當_Layout.cshtml版面撰寫好
了,我們只需專注在每一個partial view即可。

在View,我們能夠使用完整Html、CSS與JavaScript進行編輯,但如果需要將處理過的
資料從Controller傳遞到View,或是想在View進行一些邏輯運算,仍需要憑藉的Razor語
法實現,而如果您還有印象,上一篇我們曾經使用@ViewBag來顯示訊息。
下一篇,我會簡單介紹 進階View使用:Razor與htmlHelper的語法。

文章出處  Asp.Net MVC 微軟社群之星2015

[Asp .Net MVC] MVC 架構與說明

Controller and View 1 - Controller 架構篇

Controller and View 2 - 資料傳遞篇

Controller and View 3 - View架構篇

No Comments Yet.

Leave a comment