两周前
我发表了介绍将作为ASP.net特性的 MVC框架的技术文章
,该框架降低应用程序各部分之间的耦合程度,更有利于单元测试的进行并支持
TDD
工作流,同时它可以通过应用程序中的
URL
路径及其中的
HTML
代码提供更多的控制。
之后我答复了很多朋友关于这篇文章的问题,我想又必须要继续对该框架的使用做进一步的介绍,这篇文章是我本系列文章的第一篇。
一个简单的电子商务前端应用
我将用一个简单的网上商店应用程序来演示
ASP.net MVC
框架的工作原理。这篇文章将要演示其中产品列表
/
浏览的应用。
首先我们要建立一个前台显示页面,使得用户在访问网站的
/Products/Categories
路径时可以浏览产品目录:


当用户点击某一个具体产品,将会进入选择产品的详细信息显示页面
/Products/Detail/ProductID
。

我们要使用
ASP.net MVC
框架实现上述功能。这让我们可以清晰划分应用程序的不同组件,并使单元测试和测试驱动开发模型更容易被集成。
创建一个新的
ASP.net MVC
应用程序
包含
Visual Studio
项目模板的
ASP.net MVCFramework
使创建
web
应用程序变得更加方便。选择“文件”
->
“新建项目”菜单项,并点击“
ASP.net MVC Web Application
”模板创建一个新的
Web
应用程序。
当你用该选项创建项目时,
Visual Studio
默认创建一个解决方案并向其中添加两个项目,第一个项目是实现应用程序的
Web
应用程序,另一个是用于针对
web
应用程序编写单元测试的测试项目。

在
ASP.net MVC
框架中你可以使用任何一种单元测试框架(包括
Nunit, MBUnit, MSTest, Xunit
等等)。
VS2008
专业版内置了对
MSTest
测试项目(在先前的
VS2005
版本中需要安装
Visual Studio Team System SKU
)的支持,同时
ASP.net MVC
框架在
VS2008
中自动创建了这个项目。
我们会陆续提供适用于
Nunit, MBUnit
和其他单元测试框架的
ASP.net MVC
项目模板下载,因此如果你偏向于使用上述这些单元测试工具,你仍然可以通过这种简单的方式创建需要的应用程序以及对应的单元测试项目。
理解项目的目录结构
ASP.net MVC
应用程序默认有
3
个父级目录
- /Controllers
- /Models
- /Views
正如你所想象的那样,我们建议你将控制类放在
/Conrollers
目录中,数据实体类放在
/Model
文件夹中,视图模板放在
/Views
文件夹中。
虽然
ASP.net MVC
框架并没有强制要求你使用这种文件结构,但是除非你有更好的理由去使用其他的文件组织方式,我们仍然推荐你用这种默认方式组织你的应用程序。
将
URL
地址映射到控制类
在多数
Web
框架中(
ASP, PHP, JSP, ASP.net Form
等等)
URL
地址通常映射到磁盘上具体的物理文件,例如,对于路径“
/Products.aspx
”或“
/Products.php
”通常在磁盘上都有一个
Products.aspx
或
Products.php
文件与之相对应。当一个针对
Web
应用程序的
http
请求发送到服务器时,
web
框架将请求的处理权交由请求的文件,通常这个文件通过使用
HTML
标记来生成发送到客户端的回应内容。
MVC
框架使用另一种不同的方式将
URL
路径直接映射到服务器端的代码,也就是将
URL
直接映射到类而不是映射到物理文件。这些被影射到的类被称为“控制类”,他们可以处理服务器请求,处理用户输入和与用户进行交互,执行应用逻辑和数据逻辑等。控制类将会调用一个独立的“视图”组件来产生针对请求的
HTML
输出。

ASP.net MVC
框架包含了一个强大的
URL
映射引擎,可以处理多种复杂的
URL
到控制类的关系映射。你可以轻松的设置映射规则,使
ASP.net
遵循这些规则解析
URL
路径并调用相应的控制类,也可以使用
URL
映射引擎自动解析
URL
路径中的变量并将它们作为参数传递给控制类。我将在这个系列的后续文章中详细介绍
URL
映射引擎的高级使用。
ASP.NET MVC URL
到控制类的默认映射
ASP.net MVC
项目预置了一系列
URL
映射规则让用户不需要进行任何配置就可以开始开发应用程序,当然你也可以依照
Visual Studio
的
ASP.NET MVC
项目模板提供的的
Global.asax
文件中定义的应用程序类中声明的一系列默认
URL
名称映射规范进行开发。
默认的命名规范是将一个
HTTP
请求的
URL
的起始路径部分(例如:
/Products
)映射到一个具有
UrlPath
Controller
名称的类(例如:一个由
/Products/
开始的
URL
路径,将被映射到
ProductsController
类中)。
我们在项目中建立一个“
ProductsController
”类来实现电子商务的产品浏览功能(你可以点击
Visual Studio
中的“添加新项目”菜单项,根据模板创建一个控制类)。

我们的
ProductsController
类从
System.Web.MVC.Controller
基类中继承而来,但控制类并非必须继承自该积累,只是该基类中包含了很多我们后面要用到的很多有用的辅助方法和功能。

当我们在项目中创建了
ProductsController
类之后,
ASP.NET MVC
框架默认便将所有“
/Products
”引导的
URL
请求交由该类处理,这将意味着在处理诸如
"/Products/Categories",
“
/Products/List/Beverages",
或
"/Products/Detail/3"
这些我们在后面将要提到前端应用时都将调用这个控制类进行处理。
在下一篇文章里,我们将要继续添加
ShoppingCartController
(用于管理用户的购物车)和
AccountController(
用于管理用户的账号和登录注销操作
)
两个控制类,同样以
”/ShoppingCart/”
和
”Account”
开头的
URL
请求也将分别由这两个类进行处理。
提示:
ASP.net MVC
框架并不要求你一定遵循这个命名样式,我们之所以这样做是因为在
Visual Studio
中创建
ASP.net MVC
项目时,该默认的
URL
映射规则被自动添加到了项目的应用程序类中。如果你认为这种规则并不合理,你可以打开应用程序类文件(
Global.asax
文件)修改规则。在后面的文章里我将介绍这以操作(同时我会展示一些
URL
引擎提供的强大功能)。
理解控制方法
在创建
ProductController
类之后我们可以开始添加处理
”/Products/”
请求的逻辑了。
在文章开头部分定义电子商务的前端用例时,我曾提到我们要实现的三个功能:
1
)浏览产品目录,
2
)列出某一目录的所有产品和
3
)展示某一具体产品的详细信息。我们将要使用下面的
SEO
(
Search Engine Optimize
)友好路径来实现每种功能。
URL
格式
|
行为
|
示例
|
/Products/Categories
|
显示所有目录
|
/Products/Categories
|
/Products/List/Category
|
列出某一目录的产品
|
/Products/List/Beverages
|
/Products/Detail/ProductID
|
显示某产品的信息
|
/Products/Detail/34
|
我们可以通过多种方式来实现
ProductsController
类中对
3
种
URL
的处理功能,其中一种方式是通过重写控制基类
Controller
中的
”Execute”
方法,在其冲添加
if/else/switching
逻辑判断传入的
URL
并决定相应的处理逻辑。
然而,另一种更简单的方式是使用
MVC
框架为我们提供的内置特性:
MVC
框架允许我们自定义操作方法
(Action Method)
,同时
Controller
基类会根据当前应用程序中配置的
URL
映射规则自动调用相应的操作方法。
例如,我们可以在
ProductsController
类中添加下面三个控制类操作方法处理我们前面提及的三种功能:

项目创建时默认的
URL
映射规则规定
URL
中紧跟控制类名称的子路径是请求的控制方法名称,例如如果我们收到一个
/Products/Categories
请求,路由规则将把
”Categories”
作为操作方法名,
Categories()
方法将用于处理该请求等等。
提示:
ASP.net MVC
框架并不要求你一定遵循这个规范,如果你使用不同的映射规则,你只需要打开应用程序类并进行修改。
URL
的参数到控制类方法的映射
在控制类操作方法
中有多种访问
URL
参数的方式。
控制基类封装了
Request
和
Response
对象以供使用,这些对象与
ASP.net
中你所熟悉的
HttpRequest/HttpResponse
对象拥有相同的
API
接口,但他们之间一个重要的区别是这些对象现在是基于接口的而不是抽象基类(说明:
MVC
框架中同时包含了
System.Web.IhttpRequest
和
System.Web.IhttpResponse
接口)。使用接口的优点是可以方便对控制类进行单元测试,
在后面的文章里我将详细阐述这一点。
下面是这个例子介绍了我们如何使用
Request
获取查询字符串
(QueryString)
中的
ID
变量,并传递给
ProductController
控制类中的
Detail
操作方法:

ASP.net MVC
框架也支持将
URL
参数映射到操作方法的操作。如果你的操作方法中具有一个参数,
MVC
框架默认查找请求数据中是否存在具有相同名称的相关
HTTP
请求变量,如果存在,它将作为函数参数自动传递给操作方法。
例如,利用这种特性,我们可以按照下面更简洁的方式实现
Detail
方法:

除了从请求的查询字符串和
Form
变量中实现参数值映射,
ASP.net MVC
框架同样通过
URL
映射规则将参数值集成在
URL
中(例如:使用
/Products/Detail/3
代替
/Products/Detail?id=3
)
MVC
项目的默认
URL
映射规则是
"/[controller]/[action]/[id]"
,这表明在
URL
子路径中控制类名称
(Controller)
和动作方法名称
(action)
之后的部分将被自动作为方法参数传入控制类操作方法。
这表明我们可以从路径(例如
: /Products/Detail/3
)中获取
Detail
方法的
ID
参数。

利用同样的方式,我们可以通过
URL
路径向
List
方法传入产品目录名称参数(例如:
/Products/List/Beverages
)。为了增强代码的可读性,我修改了映射规则,使用“
Category
”作为这个方法的参数而不是“
id
”。
下面是具备了完整的
URL
映射和参数映射的
ProductController
类的实现:

注意上面的例子中
List
方法是如何从
URL
中的查询字符串
(querystring)
获取目录参数以及可选的页码参数(我们将利用这个参数在服务器端实现分页显示的逻辑代码)。
MVC
框架中的操作方法的可选参数使用
nullable
类型的参数,因为
List
方法的页码参数是可选参数(
int?
代表可以为空),所以
MVC
框架会根据传入的
URL
自动为参数赋值。关于
nullable
类型的使用请阅读
我的另一篇相关文章
。
创建数据模型对象
现在我们已经完成了
ProductContoller
类并添加了三个操作方法处理
Web
请求,我们的下一步是创建其他的类用于访问数据库并获取请求的数据。
在
MVC
中“模型
(model)
”是用于维护状态的应用程序组件。在
Web
应用中,状态通常在数据库中保持(例如我们可以使用
Product
对象代表产品
SQL
数据库中
Product
表的数据)。
ASP.net MVC
框架允许使用多种数据访问模式和框架创建和管理模型。你可以使用
ADO.net DataSet/DataReader(
或任何他们的抽象对象
)
,也可以使用像
Nhibernate,LLBLGen, WilsonORMapper, LINQ to SQL/LINQ to Entity
之类的数据库实体映射工具
(ORM).
在我们的电子商务示例程序中,我们将要使用
.NET3.5
和
VS2008
中内置的
LINQ to SQL ORM
映射工具,在
以后的文章
里我介绍更多关于
LINQ to SQL
的知识(包括
Part1, Part2, Part3
和
Part4
)。
在
VS
项目中的
”Model”
目录上右单击选择“添加新项目”,添加一个
LINQ to SQL
模型。在
LINQ to SQL ORM
设计器中我会定义
3
个数据对象类对应
SQL Server
的示例数据库
Northwind
中的类别
(Categories)
、产品
(Products)
和供应商
(Suppliers)
表(阅读我
LINQ to SQL系列文章的Part 2
了解如何完成该操作)。

完成
LINQ to SQL
数据模型类后,我将在模型文件夹
Model
中添加
NorthwindDataContext
分布类:

在这个类中我将定义一个封装了一些
LINQ
表达式的辅助方法,以用于从数据库中获取指定的产品目录类别、获取指定产品目录的所有产品和指定
ProductID
的产品信息。

These helper methods will make it easy for us to cleanly retrieve the data model objects needed from our ProductsController class (without having to write the LINQ expressions within the Controller class itself):
辅助方法让
ProductController
类中获取所需要的数据模型的代码更加整洁(不需要在控制类中编写
LINQ
表达式):

现在我们已经创建完成了在
ProductController
功能重所需要的所有数据代码和对象。
完成
ProductController
类的实现
MVC
应用程序中的控制类用于处理请求,与用户交互和执行应用逻辑(创建和更新数据库中的对象模型)。
控制类通常不生成
HTML
代码,生成
HTML
代码的工作由“视图
(View)
”组件完成,视图是与控制类相独立的类和模板。视图主要完成封装显示逻辑,不应该包含任何应用逻辑或数据库访问代码(所有的应用逻辑都应该由控制类进行处理)。
在
MVC Web
工作流程中,控制类操作方法将处理
Web
请求,接受传入参数并执行相应的逻辑代码,根据数据库创建或获取对象模型,并选择一个“视图”用于生成相应的
UI
发送到浏览器。控制类将向视图传入所有需要的数据和参数用于显示数据。

你或许想知道像这样将控制类和视图分离的有点是什么,为什么不把他们放在一个相同的类中?这样做主要的优点是有效的将应用程序和数据逻辑分离,使针对应用程序和数据逻辑的单元测试与
UI
呈现分离,同时可以使应用程序更容易维护,因为在视图模板中不允许添加应用程序和数据逻辑。
在实现
ProductController
类中的三个控制方法时,我们使用传入
URL
路径中的参数从数据库中获取对应的对象模型,然后选择一个“视图”组件用于生成相应的
HTML
响应。我们使用
Contoller
基类中的
RenderView()
方法指明我们希望使用的视图,同时传入视图显示时所需要的数据。
下面是
ProductsController
类的最终实现:

注意到上面的操作方法代码都很少(每个方法只有两行)。这得益于
MVC
框架啊为我们提供的
URL
参数解析逻辑(避免书写很多逻辑代码),同时也因为产品浏览的逻辑功能比较简单(操作方法只有只读的显示功能)
你通常会发现你的一些方法代码非常短小,这表明你对数据逻辑和控制逻辑进行了很好的封装。
对
ProductController
进行单元测试
或许你会对我们下一步将要进行程序测试而感到奇怪,你或许会问这怎么可能?我们还没有实现视图,我们的应用程序现在甚至没有产生一个
HTML
标记,
MVC
吸引人的特性之一就是可以在视图
/HTML
产生逻辑完成之前独立进行针对控制类和模型逻辑的单元测试。正像你将要在下面看到的,我们甚至可以在创建视图之前进行单元测试。
为了对
ProductController
类进行单元测试我们在项目默认添加的测试项目中新建了一个
ProductControllerTest
类:

接下来我们要哦啊定义一个简单的单元测试对
ProductController
类中的
Detail
函数进行测试:

The ASP.NET MVC framework has been designed specifically to enable easy unit testing. All core APIs and contracts within the framework are interfaces, and extensibility points are provided to enable easy injection and customization of objects (including the ability to use IOC containers like Windsor, StructureMap, Spring.NET, and ObjectBuilder). Developers will be able to use built-in mock classes, or use any .NET type-mocking framework to simulate their own test versions of MVC related objects.
ASP.net MVC
框架转为利于单元测试而设计。框架中所有的核心
API
和协议都是基于接口的
In the unit test above, you can see an example of how we are injecting a dummy "ViewFactory" implementation on our ProductsController class before calling the Detail() action method. By doing this we are overriding the default ViewFactory that would otherwise handle creating and rendering our View. We can use this test ViewFactory implementation to isolate the testing of just our ProductController's Detail action behavior (and not have to invoke the actual View to-do this). Notice how we can then use the three Assert statements after the Detail() action method is called to verify that the correct behavior occurred within it (specifically that the action retrieved the correct Product object and then passed it to the appropriate View).
在上面的单元测试中,你可以看到我们是如何在调用个
ProductsController
类的
Detail()
方法前对“视图工厂
(ViewFactory)
”的。通过这种方式我们重写了将要处理创建和产生视图的视图工厂。我们可以使用这个视图工厂的
因为在
MVC
框架中哦我们可以模拟各种对象(包括
IhttpRequest
和
IhttpResponse
对象),你不需要在
Web Server
的环境中进行单元测试,取而代之的是我们可以将
ProductController
类创建在一个普通的类库项目中并对他进行测试,这可以有效提高单元测试的执行效率,同时简化了其配置和运行过程。
如果我们使用
Visual Studio 2008
,我们可以轻松的跟踪测试运行的成功
/
失败状态(该功能已经被集成入
VS2008
专业版中)。

我想你会发现
ASP.net MVC
框架式的编写测试更加容易,同时更好地支持了
TDD
开发流程。
用视图产生
UI
我们已经完成并测试了该电子商务程序中产品浏览部分的应用和数据逻辑,现在我们需要实现他的
HTML UI
界面。

我们将实现当
RenderView()
方法时被调用是,视图会根据数据
ProductController
操作方法提供的数据产生相应的界面。

在上面的例子中,
RenderView
方法的
”Categories”
参数指明了我们希望用于显示的视图名称,第二个参数是一个目录类的集合,我们将在视图中根据该集合数据产生相应的
HTML
界面。
ASP.net MVC
框架支持多种模板引擎产生
UI
(包括像
Nvelocity, Brail
以及自定义的模板引擎),
ASP.net MVC
框架默认使用
ASP.net
已经支持的
ASPX, MASTER
和
ASCX
。
我们将使用
ASP.net
内置的视图引擎产生我们的电子商务程序界面。
定义
Site.Master
文件
因为我们要为站点创建很多页面,我们将要首先为所有的
UI
定义一个母板页,以便封装常用的
HTML
布局,我们在、
Views\Shared
文件夹中创建一个名为
”Site.Master”
的文件实现该功能。

我们引用一个包含了站点样式的外部
CSS
样式表文件,并使用母板页定义站点的布局和内容显示区域,在开发时我们可以选择使用所有
VS2008
设计器中提供的强大功能特性(包括
拆分设计视图(HTML split-view designer), CSS编辑 (CSS Authoring),
和
嵌入模板支持
(N
ested Master Pages support
)

理解
/Views
目录结构
当你在
Visual Studio
中创建
ASP.net MVC
项目时,它默认会在
View
根目录下创建一个
”Shared”
子目录,你可以在这里存放母板页,用户控件和在多个控件中共享的视图。
当创建针对某一个控制类的视图是,
ASP.net MVC
默认的规则是将它们创建在
/Views
根文件夹下,子文件夹名称默认与控制类的名称相同。例如,因为我们刚创建的控制类是
ProductsController,
那么我们默认在
\Views\Products
子文件夹中存放视图文件。

当我们调用某一控制类中的
RenderView(string viewName)
方法时,
MVC
框架在、
Views\ControllerName
文件夹中自动搜索对应的
.aspx
或
.ascx
视图模板文件,如果其中没有对应的视图模板,则将自动转到
\Views\Share
目录进行搜索。
创建目录视图
我们可以通过在
Products
目录中通过“添加新项目”菜单项选择
”MVC View Page”
选项创建
ProductsController
类的目录视图文件。这将创建一个新的
.aspx
页面,我们可以设置这个文件与
Site.Master
母板文件的关联使得他具备站点的一致外观:

在使用
MVC
模式创建应用程序时,你应当使你的视图代码尽可能简化并完全用于产生视图,而把应用和数据逻辑在控制类中实现。控制类在调用
RenderView
方法时应向视图中传入用于生成视图的必要数据。例如,下面的
ProductController
类的
Categories
方法中我们向视图传入一个
Category
集合对象:

MVC
视图页面默认集成自
System.Web.Mvc.ViewPage
基类,该积累定义了很多在我们构建
UI
过程中将要用到的辅助方法和属性,
ViewPage
的一个属性是
ViewData,
它提供对控制类从
RenderView()
方法中传来的数据的访问。
在你的视图中你可以通过迟绑定或强类型的方式访问视图数据
(ViewData)
。如果你的视图继承自
ViewPage
类,那么
ViewData
属性将被设定为迟绑定
(late-bound dictionary)
类型。如果你的视图继承自泛型
ViewPage<T>
类,那么
ViewData
属性将被设定为与控制类传入的参数相同的类型。
例如,我下面的目录视图后台代码继承自
ViewPage<T>
,同时我指明了
T
是一个目录对象的集合:

这表明我在访问
ProductsController.Categories()
方法提供的
List<Category>
类型的
ViewData
时具备了完全的类型安全,智能感知和编译时检查的特性:

产生目录视图
或许你还记得这篇文章开始部分的截图,我们希望在目录视图中显示所有的产品目录:

我有如下两种方式在目录视图的实现部分产生
HTML
代码:
1)
在
.aspx
文件中嵌入代码
2)
在
.aspx
页面使用服务器控件并在后台代码中实现绑定。
实现方式
1
:使用嵌入代码
ASP.net
页,用户控件和母板页都支持
<%%>
和
<%=%>
标记在
HTML
标签中嵌入代码,我们采用这种技术在目录视图中编写一个
”foreach”
循环生成
HTML
格式的目录列表:

VS2008
提供了对
VB
和
C#
两种语言代码编辑器的完全代码智能感知支持,这意味着我们在访问传入视图的目录对象是将获得智能感知的支持:

VS2008
同样提供了对迁入代码的调试支持(允许我们在代码中设置断点):

实现方式
2
:使用服务器控件

注意上面的代码中,
ListView
控件是如何封装产生列表值和空列表值
(<EmptyDataTemplate>
省去了我们编写
if/else
判断逻辑
)
两种情况的。我们可以在后台代码中将目录列表绑定到该控件。

重要:在
MVC
中我们只希望在视图的后台代码中放置显示逻辑(不包括任何其他的业务逻辑),注意上面的大妈中我们唯一的一个逻辑操作时将强类型的目录列表
ViewData
赋值给
ListView
控件。我们的
ProductController
控制类实际承担从数据库中获取目录列表工作而不是视图。
我们的视图模板中的
ListView
服务器控件将会产生向我们在嵌入代码中编写的一样的
HTML
标记,因为我们的页面上没有
<form runat=”server”>
控件,没有
ViewStaes
视图,
ID
和其他标记都将排除,只有
CSS
友好的
HTML
代码:

HTML.ActionLink
方法
或许你已经注意到了在两种方式的代码中都调用了
Html.ActionLink
方法:

Html
对象是
ViewPage
类及其子类的的辅助属性,
ActionLink
方法用于产生链接回控制类方法的
HTML
代码。如果你看到了前一部分的
HTML
输出图片,你可以看到这个方法输出的
HTML
代码:
<a href="http://weblogs.asp.net/Products/List/Beverages">Beverages</a>
Html.ActionLink
辅助方法的原型如下:
string ActionLink(string text, object values);
第一个参数代表超级链接中间的文字(例如
<a>text goes here</a>
)
.
第二个参数是一个匿名对象(
anonymous object
)代表一系列用于产生
URL
路径的参数(你可以认为他是
一种产生字典的有简洁方式
)。在后面介绍
URL
映射引擎的文章中我会进一步介绍它究竟是如何工作的。概括的将,你不但可以使用
URL
映射系统处理
URL
路径同时可以生成需要的
HTML
代码,如果我们有如下的映射规则:
/<controller>/<action>/<category>
我们在
ProductController
的目录视图中编写下面的代码:
<%= Html.ActionLink("Click Me to See Beverages", new { action="List", category="Beverages" } %>
ActionLink
方法将要使用应用程序的
URL
映射规则将处理你传入的参数并产生输出:
<a href="http://weblogs.asp.net/Products/List/Beverages">Click Me to See Beverages</a>
这使得生成到控制类的
URL
和
AJAX
回调变得更加容易,同时意味着你只要修改
URL
映射规则,就可以让应用程序中所有处理
URL
请求和产生
URL
路径的代码发生相应的变更。
重要提示
:为了增强可测试性,今天的
MVC
框架不支持视图中控件的直接回送事件,取而代之的,
ASP.net MVC
应用程序产生到控制类的超级链接和
AJAX
回调,然后使用视图(以及其中的其他服务器控件)产生输出。这是的你的视图逻辑更加简洁并专注于控制显示,是应用和数据逻辑与视图分离,你可以更方便的对控制类进行单元测试。后面我将会做详细的介绍。
总结
第一篇文章相当长,旨在对
ASP.net MVC
框架中各部分之间的关系有一个大致的描述,以及如何利用它创建一个更加普遍并与真实世界相吻合的应用场景,
ASP.net MVC
第一个预览版本将在几周后发布,你将可以使用他尝试我上面提到的操作。
MVC
中的很多概念(尤其是对应用程序各部分分离的思想)或许在很多人看来是很新的,希望这篇文章同时也可以展示我们一直在研究的
ASP.net MVC
是如何在已有的
ASP.net, .NET
和
Visual Studio
基础上分离的。你可以使用
.ASPX, . ASCX
和
.MASTER
文件和
ASP.net AJAX
创建
ASP.net MVC
视图。
ASP.net
的非
UI
特性例如窗体验证,
Windows
验证,用户权限,角色管理,
URL
权限设置,缓存,
Session, Profile,
运行监控,配置,编译,区域化设置和
HttpModules/HttpHanlders
仍然被
MVC
模型支持。
如果你并不喜欢
MVC
模型或发现他并不符合你的开发习惯,你可以选择不使用它,这完全是一个可选项,并不会取代已有的
Web
页面控制模型,
WebForms
和
MVC
都会被继续被支持和强化功能。你甚至可以创建一个同时兼有
WebPage
和
MVC
模型的应用程序。
如果你确实喜欢
MVC
并希望了解更多的知识,请继续关注后面的文章,我会介绍更多
MVC
的概念并使用他们完成创建我们的电子商务应用程序以展示
MVC
的诸多特性。
希望这对你有所帮助,
Scott