.NET Web開發(fā)之.NET MVC框架介紹
MVC是一種架構(gòu)設(shè)計(jì)模式,該模式主要應(yīng)用于圖形化用戶界面(GUI)應(yīng)用程序。那么什么是MVC?MVC由三部分組成:Model(模型)、View(視圖)及Controller(控制器)。
Model即應(yīng)用程序的數(shù)據(jù)模型。任何應(yīng)用程序都離不開數(shù)據(jù),數(shù)據(jù)可以存儲(chǔ)在數(shù)據(jù)庫中、磁盤文件中,甚至內(nèi)存中。Model就是對(duì)這些數(shù)據(jù)的抽象,不論數(shù)據(jù)采取何種存儲(chǔ)形式,應(yīng)用程序總是能夠通過Model來對(duì)數(shù)據(jù)進(jìn)行操作,而不必關(guān)心數(shù)據(jù)的存儲(chǔ)形式。數(shù)據(jù)實(shí)體類就是常用的一種Model。例如,一個(gè)客戶管理應(yīng)用程序使用數(shù)據(jù)庫來存儲(chǔ)客戶數(shù)據(jù),數(shù)據(jù)庫表中有一個(gè)客戶表Customer,相應(yīng)的程序中一般會(huì)建立一個(gè)數(shù)據(jù)實(shí)體類Customer來與之對(duì)應(yīng),這個(gè)實(shí)體類即使客戶表的Model。
View是應(yīng)用程序的界面。用戶通過View來操作應(yīng)用程序,完成與程序的交互。View提供了可視化的界面來顯示Model中定義的數(shù)據(jù),用戶通過View來操作數(shù)據(jù),并將對(duì)Model數(shù)據(jù)操作的結(jié)果返回給用戶。在桌面應(yīng)用程序中,View可能是一個(gè)或多個(gè)Windows窗體。在Web應(yīng)用程序中,View是由一系列網(wǎng)頁構(gòu)成,在ASP.NET網(wǎng)站中即為.aspx頁面。
Controller 定義了程序的應(yīng)用邏輯。用戶通過View發(fā)送操作命令給Controller,由Controller按照程序設(shè)計(jì)的邏輯來更新Model定義的數(shù)據(jù),并將操作結(jié)果通過View返回給用戶。
MVC這一概念最早由美國教授Trygve Reenskaug于1979年提出。1988年MVC這一設(shè)計(jì)模式正式在《A Cookbook for Using the Model-View-Controller User Interface Paradigm in Smalltalk -80》一書中提出。伴隨著微軟Windows操作系統(tǒng)的迅速發(fā)展與普及,圖形化用戶界面應(yīng)用程序逐漸成為主流,很多編程語言都出現(xiàn)了MVC框架,以方便開發(fā)人員使用該模式來設(shè)計(jì)應(yīng)用程序。這些框架中大部分都是針對(duì)Web應(yīng)用程序。
.NET Web開發(fā)中MVC設(shè)計(jì)模式的實(shí)現(xiàn)
ASP.NET 1.x中使用了CodeBehind技術(shù),徹底終結(jié)了傳統(tǒng)ASP程序開發(fā)的夢(mèng)魘:程序邏輯與HTML界面元素混雜在一起。CodeBehind技術(shù)將代表程序界面(View)的.aspx文件與邏輯(Controller)代碼.vb/.cs文件的分離即是一種MVC式的設(shè)計(jì)。ASP.NET 2.0中又出現(xiàn)了CodeBeside技術(shù),即一個(gè).aspx文件可以有多個(gè).vb/.cs文件,這又方便了界面與邏輯代碼的進(jìn)一步分離。
2008年3月微軟發(fā)布了針對(duì)ASP.NET 3.5 的MVC框架 (Preview 2 版本)。這是一個(gè)真正意義上的ASP.NET MVC框架。該框架可以說是對(duì)之前為開發(fā)人員所熟悉的基于Web Form的應(yīng)用程序開發(fā)方式的"顛覆"。變化可謂"震撼":
1. 使用URL Routing技術(shù):Web程序的URL不再是指向具體的物理頁面.aspx,而是指向某個(gè)Controller的某個(gè)方法。一個(gè)典型的MVC架構(gòu)的程序,其URL可能如下所示:
http://www.mysite.com/Customer/Index
使用該MVC架構(gòu)的程序其URL不必有文件擴(kuò)展名。上面這個(gè)URL中的Customer即為Controller的名字。而Index是Customer定義的一個(gè)方法名。
2. Web程序的界面.aspx不再使用服務(wù)器端的Form:
<asp: form runat="server"></form>
那么與服務(wù)器端的Form相關(guān)的Postback以及頁面生命周期的事件也不存在了。
3. 頁面中不再有View State。MVC下將不能使用View State來存儲(chǔ)程序狀態(tài)信息。
4. 不再提供依賴于服務(wù)器端Form的服務(wù)器控件事件,開發(fā)人員熟悉的Button_Clicked事件在MVC下將不再需要。
NET MVC示例
安裝完 ASP.NET MVC Preview 2后,VS2008中會(huì)添加一個(gè)新的項(xiàng)目模板"ASP.NET MVC Web Application", 如下圖所示
新建該項(xiàng)目后, VS2008自動(dòng)生成項(xiàng)目的文件結(jié)構(gòu)如下, MVC三個(gè)組成部分各有一個(gè)文件夾來存儲(chǔ)各自的程序文件。
前面提到的URL Routing即在Global.asax.cs中設(shè)置:
public class GlobalApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
// 注意: IIS7以下的IIS版本需將URL格式設(shè)置為 "{controller}.mvc/{action}/{id}" to enable
routes.Add(new Route("{controller}.mvc/{action}/{id}", new MvcRouteHandler())
{
Defaults = new RouteValueDictionary(new { action = "Index", id = "" }),
});//設(shè)置URL Routing格式
routes.Add(new Route("Default.aspx", new MvcRouteHandler())
{
Defaults = new RouteValueDictionary(new { controller = "Customer", action = "Index", id = "" }),
});//設(shè)置默認(rèn)URL指向Customer Controller的Index方法
}
protected void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}
}
下面來實(shí)現(xiàn)Customer 的Model、Controller及View:
Model: 在項(xiàng)目中的Model文件夾下,新建一個(gè)"Linq to SQL Classes",將Northwind數(shù)據(jù)庫中的Customer表拖拽到其設(shè)計(jì)視圖中。這樣就完成了Customer對(duì)應(yīng)的Model。如圖4
Controller: 在項(xiàng)目中的Controller文件夾下,新建一個(gè)"MVC Controller Class",命名為CustomerContoller.cs。 在此類中添加一個(gè)公有方法Index,此方法及為在Global.asax.cs中設(shè)置好的默認(rèn)URL所映射的方法。
public class CustomerController : Controller
{
public void Index(string id)
{
Northwind.Models.NorthwindDataContext dc = new Northwind.Models.NorthwindDataContext();
IList<Northwind.Models.Customer> customers = dc.Customers.Take(10).ToList();//取數(shù)據(jù)庫中的10個(gè)Customer記錄
RenderView("Index", customers);//返回Index View
}
}
【代碼2】:CustomerController.cs
View: 上面Index方法的代碼表示CustomerContoller的Index方法執(zhí)行后,需要返回一個(gè)名稱為Index的View,以便將數(shù)據(jù)呈現(xiàn)給用戶。下面來添加這個(gè)Index View:在項(xiàng)目的View文件中,新建一個(gè)子文件夾Customer。與Customer Controller有關(guān)的View將保存在此文件夾下。新建一個(gè)"MVC View Class"并命名為Index.aspx。在前面的RenderView("Index", customers)方法中,customers參數(shù)是Controller傳遞給View所需的數(shù)據(jù),該參數(shù)的類型為IList<Northwind.Models.Customer>。為了在View中方便使用此強(qiáng)類型的數(shù)據(jù),View.aspx.cs使用了如下代碼:注意粗體部分
public partial class Index : ViewPage<IList<Northwind.Models.Customer>>
{
}
【代碼3】:Index.aspx.cs
View.aspx代碼如下:ViewData這一成員變量的類型及為上面提到的IList<Northwind.Models.Customer>類型。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Edit.aspx.cs" Inherits="Northwind.Views.Customer.Edit" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
</head>
<body>
<div>
<table>
<tr>
<td>Edit</td>
<td>Customer ID </td>
<td>Company Name </td>
<td>Contact Name </td>
<td>Contact Title </td>
</tr>
<% foreach (Northwind.Models.Customer customer in ViewData)
{%>
<tr>
<td><a href="Customer.mvc/Edit/<%= customer.CustomerID %>">Edit</a></td><!—URL指向Customer Contoller的Edit方法 -->
<td></td>
<td> <%= customer.CustomerID %></td>
<td> <%= customer.CompanyName %></td>
<td> <%= customer.ContactName %></td>
<td><%= customer.ContactTitle %></td>
</tr>
<%} %>
</table>
</div>
</body>
</html>
【代碼4】:Index.aspx
下面來實(shí)現(xiàn)Customer Controller的Edit方法。在CustomerController.cs中添加如下代碼:
public void Edit(string id)
{
Northwind.Models.NorthwindDataContext dc = new Northwind.Models.NorthwindDataContext();
Customer c = dc.Customers.Single(cus => cus.CustomerID == id);//從數(shù)據(jù)庫中取出參數(shù)id所對(duì)應(yīng)的的一個(gè)Customer記錄
RenderView("Edit", c);//返回Edit View
【代碼5】:CustomerController.cs中的Edit方法
相應(yīng)的在項(xiàng)目中的View/Customer/文件夾下,添加Edit View Edit.aspx:
public partial class Edit : ViewPage<Northwind.Models.Customer>
{
}
【代碼6】:Edit.aspx.cs
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Edit.aspx.cs" Inherits="Northwind.Views.Customer.Edit" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
</head>
<body>
<!—下面的 html form 將用戶的輸入提交到Customer Contoller的Update方法 -->
<%using( Html.Form<Northwind.Controllers.CustomerController>(cc=>cc.Update(ViewData.CustomerID))){ %>
<div>
Customer ID: <%= ViewData.CustomerID %> <br />
Company Nmae: <%= Html.TextBox("Customer.CompanyName", ViewData.CompanyName) %> <br />
Contact Name: <%= Html.TextBox("Customer.ContactName",ViewData.ContactName) %><br />
Contact Title: <%= Html.TextBox("Customer.ContactTitle",ViewData.ContactTitle) %>
</div>
<%= Html.SubmitButton("Save") %>
<%} %>
</body>
</html>
【代碼7】:Edit.aspx
代碼7中使用了MVC框架中的一個(gè)幫助類Html。此類可以生產(chǎn)View中常用的界面元素,例如 html form,文本輸入框等。
下面來實(shí)現(xiàn)CustomerController的Update方法:
public void Update(string id)
{
Northwind.Models.NorthwindDataContext dc = new NorthwindDataContext();
//從數(shù)據(jù)庫中取出參數(shù)id所對(duì)應(yīng)的的一個(gè)Customer記錄:
Customer cust = dc.Customers.Single(c => c.CustomerID == id);
//將Edit View中的用戶的更改賦值到cust對(duì)象:
BindingHelperExtensions.UpdateFrom(cust, Request.Form);
dc.SubmitChanges();
RedirectToAction("Index");//跳轉(zhuǎn)到Index View
}
【代碼8】:CustomerController.cs中的Update方法
上面的代碼通過ASP.NET MVC框架實(shí)現(xiàn)了Customer的列表、編輯及更新功能,可以看出MVC將應(yīng)用程序的Model、View及Controller三部分"優(yōu)雅的"分離,真正實(shí)現(xiàn)了高內(nèi)聚、低耦合的靈活架構(gòu),大大降低了程序的復(fù)雜性,提高了可擴(kuò)展性及可重用性。這一框架對(duì)Web開發(fā)帶來的影響不僅是是技術(shù)上的變化,更是Web程序設(shè)計(jì)思想的變化 -- Web程序不再是一些列功能頁面的集合,而是又Controller控制的功能單元的集合,Web程序更像是一組通過其URL對(duì)外開放的"API"。
相關(guān)文章
asp.net及javascript判斷是否手機(jī)訪問的方法
這篇文章主要介紹了asp.net及javascript判斷是否手機(jī)訪問的方法,結(jié)合實(shí)例形式對(duì)比分析了asp.net及javascript實(shí)現(xiàn)判斷訪問端類型的相關(guān)技巧,需要的朋友可以參考下2016-06-06詳解將ASP.NET Core應(yīng)用程序部署至生產(chǎn)環(huán)境中(CentOS7)
這篇文章主要介紹了詳解將ASP.NET Core應(yīng)用程序部署至生產(chǎn)環(huán)境中(CentOS7),具有一定的參考價(jià)值,有需要的可以了解一下。2016-12-12.NET異步編程總結(jié)----四種實(shí)現(xiàn)模式代碼總結(jié)
本篇文章主要介紹了.NET異步編程總結(jié)----四種實(shí)現(xiàn)模式,詳細(xì)的介紹了每種方法的實(shí)現(xiàn)和實(shí)例,具有一定的參考價(jià)值,有興趣的可以了解一下。2016-12-12.NET某消防物聯(lián)網(wǎng)后臺(tái)服務(wù)內(nèi)存泄漏分析
這篇文章主要為大家介紹了.NET某消防物聯(lián)網(wǎng)后臺(tái)服務(wù)內(nèi)存泄漏分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06.NET MVC中ViewData,ViewBag和TempData的區(qū)別淺析
這篇文章主要介紹了.NET MVC中ViewData,ViewBag和TempData的區(qū)別,分析了ViewData,ViewBag和TempData在賦值、功能特性等方面的區(qū)別于用法,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-01-01Asp.net中獲取應(yīng)用程序完整Url路徑的小例子
Asp.net中獲取應(yīng)用程序完整Url路徑的小例子,需要的朋友可以參考一下2013-06-06asp.net Page.EnableEventValidation 屬性驗(yàn)證服務(wù)器控件的回發(fā)和回調(diào)事件出現(xiàn)的錯(cuò)誤
Page.EnableEventValidation 屬性驗(yàn)證服務(wù)器控件的回發(fā)和回調(diào)事件出現(xiàn)的錯(cuò)誤前兩天用jQuery做了一個(gè)包含DropDownList聯(lián)動(dòng)的頁面,數(shù)據(jù)通過Ajax請(qǐng)求得到的。2010-10-10