ASP.NET MVC第001天_Webform跟MVC差在哪?_MVC專案架構概述
在很久以前有用Java swing來模擬實作MVC的概念
https://coolmandiary.blogspot.com/2019/01/java-mvcmvcjava-gui.html
也有在Java EE中淺淺地帶過MVC的概念
https://coolmandiary.blogspot.com/2018/03/day1j2eejava-2-enterprise.html
今天要來分享一下網頁上開發透過.NET MVC的實作初體驗
在以前的web form 強調事件驅動跟Page Life Cycle和一些狀態儲存的觀念
而.NET MVC跟Webform的差別
我們可用下面的圖呈現
Weborm中有區分所謂屬於form的跟非form的元素
Webform中由於有肥大的ViewState內容,使得在傳送網頁過程網頁資料量比較大
Webform控件雖然一開始是為了節省開發時間而封裝但也使得對於html控制不夠直覺
不太容易撰寫單元測試(不容易導入TDD)
相較於WebForm的上述缺點 MVC帶來的是
https://coolmandiary.blogspot.com/2019/01/java-mvcmvcjava-gui.html
也有在Java EE中淺淺地帶過MVC的概念
https://coolmandiary.blogspot.com/2018/03/day1j2eejava-2-enterprise.html
今天要來分享一下網頁上開發透過.NET MVC的實作初體驗
在以前的web form 強調事件驅動跟Page Life Cycle和一些狀態儲存的觀念
而.NET MVC跟Webform的差別
我們可用下面的圖呈現
Weborm中有區分所謂屬於form的跟非form的元素
Webform中由於有肥大的ViewState內容,使得在傳送網頁過程網頁資料量比較大
Webform控件雖然一開始是為了節省開發時間而封裝但也使得對於html控制不夠直覺
不太容易撰寫單元測試(不容易導入TDD)
相較於WebForm的上述缺點 MVC帶來的是
1.淺顯的關注點分離SoC(Separation of Concerns),開發人員只需要關注目前物件上一次性解決
不會受到其他物件的干擾或連動影響
2.易於測試及分工,由於江M、V、C職責拆分出來所以網頁設計人員和前端都可以直接參與View層設計,但實際上可能較多仍是一個人去負責View跟後端Model , Controller的整合。
在設計上保持的原則就是View愈單純愈笨愈好不將業務邏輯寫於此
3.HTTP的輸出內容較有完全的控制權(寫的風格有點像Classic ASP)
4.更容易導入IoC (Inversion of Control)或 DI (Dependency Injection)
4.更容易導入IoC (Inversion of Control)或 DI (Dependency Injection)
從Webform轉移到MVC必須捨棄的特性
1.ViewState
2.頁面事件模型(Event Model)
3.封裝的控制項
4.頁面追蹤機制(Page Trace)
以上這些於.net mvc都不太支援了
但其餘的asp.net特性基本上仍保留
Application Life Cycle , Web Caching , Session , Authentication 等等
MVC職責再次說明
Model(模型):即定義資料型態和DB溝通、保存程式狀態並執行相應業務邏輯的地方
絕大多數時候可能會是用DB中某Table的某一Record Entity各項Column Data Type或是
View(檢視):網頁畫面(html , 和一些js 、css)
Controller(控制器):判斷及請求某個Model、判斷和導向某個View
Controller會接受Routing分析出的路由,也負責和Model傳遞資料輸出到View。
建立一Webform範例專案跟MVC範例專案
進行比較
Webform
從首頁、關於這兩個網頁檔案
就可以明確觀察到以前的Webform遵循的是「網址路徑」即「檔案路徑」
首頁
http://localhost:12081/Default
http://localhost:12081/
預設都是對應網站根目錄下的
/Default.aspx
/Default.aspx.cs
關於
http://localhost:12081/About
/About.aspx
/About.aspx.cs
但到了MVC則是必須透過asp.net mvc的架構中的網址路由(Routing)來找尋檔案的
其定義於Global.asax.cs檔案中
首頁
http://localhost:12047/
對應程式位置
/Views/Home/Index.aspx
/Controller/HomeController.cs
在Global.asax.cs檔案中
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing; namespace WebApp_Template { public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); } } }
可以看到間接調用到RouteConfig去設置網址路由
在RouteConfig.cs檔案中
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace WebApp_Template { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", //路由名稱 url: "{controller}/{action}/{id}", //URL和參數 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } }
可以清楚看到明確預設load進來就指定導向首頁的View
url: "{controller}/{action}/{id}"
此句是用來定義網址路徑如何對應MVC參數的
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
IgnoreRoute
主要是去設定*.axd格式網址路徑不透過asp.net MVC方式執行
(Ex:內建的Trace.axd 或預設的HttpHandler)
routes.MapRoute( name: "Default", //路由名稱 url: "{controller}/{action}/{id}", //URL和參數 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } );
MapRoute方法定義三參數
1.路由名稱
2.網址路徑要如何對應到控制器、動作和路由值設定串
在定義Routing時看到的大括號包覆的一變數名稱也就是所謂的路由變數!
當中必要的{controller}、{action}
若沒有設定預設值就會使MVC無法正常運作
此兩核心變數會傳給System.Web.Mvc.MvcHander class接著交給DefaultControllerFactory進行創建
其餘路由變數則可自訂
以About此範例來看就可得知
{controller}代表Home
{action}代表About
因此.net mvc底層機制會先到Controllers的folder下
找到Home 這個Controller (HomeController.cs)
再到此Controller內的About 這個publc method 也就是此action (網頁主程式進入點)了
HomeController.cs檔案內容
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace WebApp_Template.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(); } public ActionResult About() { ViewBag.Message = "Your application description page."; return View(); } public ActionResult Contact() { ViewBag.Message = "Your contact page."; return View(); } } }
3.控制器、動作跟其他路由值的預設設定內容
若只輸入預設的本機localhost url
http://localhost/
則會透過Routing比對後得知網頁目的位址不存在
而採用default的首頁設定,也就是Home
網頁就會從Controllers目錄去尋找Home 控制器的程式(HomeController.cs)
去找public 的Index method,該方法就是對應的action對應作為網頁入口。
在MVC專案下
一個Action(ActionResult)會對應一個View
以HomeController為例
就有Index , About , Contact三個Action
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace WebApp_Template.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(); } public ActionResult About() { ViewBag.Message = "Your application description page."; return View(); } public ActionResult Contact() { ViewBag.Message = "Your contact page."; return View(); } } }
各自對應到的三個View
在Views/Home/ 下
那預設如果是新手通常觀察就知道
Views就是一些前端網頁
然後就習以為然的在下方新增網頁了
這裡右鍵->加入->檢視(V)
輸入好名字加入
MyWeb 的View預設程式
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>MyWeb</title> </head> <body> <div> </div> </body> </html>
就產生了
但直接執行狀況就會是報錯
主要是因為MVC設計上是不允許你直接瀏覽View
而是透過Controller先訪問後由Action來指定到哪
這裡資源找不到就是因為Controller沒定義導向MyWeb 這個View的Action
於Controller補上程式後就可以正常顯示了
所以在MVC中一律要先有一Controller去主導做某一Action才能順利指向View
留言
張貼留言