内容
介绍
做ASP.NET MVC开发需要什么?
ASP.NET与MVC和Web Form之间的有什么区别?
ASP.NET Web Form的为什么成功?
ASP.NET Web Form有什么不好?
解决方案是什么?
微软的ASP.NET MVC 怎么处理Web Form中的问题?
了解 Controller 在ASP.NET MVC中是如何工作的?
了解 View 在 ASP.NET MVC中是如何工作的?
试验 1 - 用一个简单的MVC来演示Controller
实验1中的问题和解答
实验2 - 演示View的工作原理
实验2中的问题和解答
第二天探讨什么?
完整系列
第1天
第2天
第3天
第4天
第5天
第6天
第7天
正如标题所保证的“7天内学会MVC“,所以这个系列的文章会有7个标题,每天一个标题。从周一开始看这个系列的文章到这周结束就会成为一个MVC高手.
第一天类似于热身, 在这第一天我们会搞明白为什么ASP.NET MVC 比 WebForm 优秀? 我们会做两个实验来说明WebForm的问题: 一个是Controller,另外一个是View.
每个实验结束都会有一个简小的问题和回答的环节, 在那时我们会讨论实验中的概念。所以上边的图就是这样的一个结构。
万一你有任何问题,在实验中没有得到解答,请放在下面相同问题的评论里,我们一定会回答的,如果哪些反复的出现,那么我们也会把该问题包含在文章中,这样会让大家都获得到同样利益。
所以我们需要你的7天时间,熬过着7天可以保证你真正成为一个ASP.NET MVC的开发者。
我们只需要Visual Studio,并且一个好消息是 VS 是完全免费的。你可以从http://www.visualstudio.com/下载Visual Studio通用版,没有日期和许可的问题而且不需要你掏腰包。
ASP.NET与 MVC 和 Web Form 之间的有什么区别?
”你正在读这篇文章,表示你知道ASP.NET 并且想要学习并掌握MVC.“
如您不介意,请再读一次前面的一句话,如果你认为是对的那么这篇文章你必须读.
很多的ASP.NET开发者第一次开始用MVC认为是全新完全不同的技术。但实际上ASP.NET是一个框架用于创建Web应用程序的,而MVC是一个更好的架构去开发组织组织整理我们的代码, 所以你说ASP.NET MVC比MVC更合适.
假如这个叫ASP.NET MVC, 那么旧的我们叫“ASP.NET WebForms”?
让我来纠正你的用语 - ”你正在读这篇文章,表示你知道ASP.NET WebForm 并且想要学习并掌握ASP.NET MVC.“
所以现在你的用语正确了,欢迎加入ASP.NET MVC的阵营,立即开始这个教程。
在过去的12年ASP.NET WebForm 很成功的被应用,让我们来了解下是什么让WebForm这么流行和成功。
正如你看到的微软编程语言的成功是要从Vb处理RAD(Rapid application development)和可视化的编程说起。可视化编程受到了得了巨大吹捧,微软就直接把IDE命名为"Visual studio".
使用Visual Studio, 开发者能够在设计区拖拽UI元素,也可以在后端控制元素,Visual Studio为这些元素生成C#或VB.NET Code,这些Code被称为“后置代码”或“代码后置”,在这些Code里,开发者可以操纵UI元素。
所以微软的可视化RAD架构有两件事,一个是UI ,另外一个是后置的Code。所以ASP.NET WebForm 你会有ASPX和ASPX.CS 两个文件。对于WPF你有XAML/XAML.CS等等..
为什么微软在ASP.NET WebForm这么a成功的时侯会想创建ASP.NET MVC?
主要问题是ASP.NET Webfrom存在严重的性能问题.
在Web应用程序中性能从两方面来看:
响应时间。- 服务端相应一个请求有多快?
带宽消费。- 发送多少数据?
我们来看看为什么ASP.NET Webfrom的响应时间这么慢。我们分别用Webform和ASP.NET MVC来做一个小的加载实验,明显可以看出ASP.NET MVC有能快两倍.
查看看更多的测试结果
让我们从下面简单的UI code和后置Code来看看为什么ASP.NET MVC 的性能要好呢?
假如ASPX Code有个简单的Text Box:
<asp:TextBox ID="TextBox1" runat="server">
后置Code你写了一些操作这个TextBox的逻辑进去:
protected void Page_Load(object sender, EventArgs e){ TextBox1.Text = "Make it simple"; TextBox1.BackColor = Color.Aqua;}
运行起来后可以看到浏览器输出了下面的Html:
这时右键View Source Code,你能看到下面的Code:
<input name="TextBox1" type="text" value="Make it simple" id="TextBox1" style="background-color:Aqua;" />
那现在停下来闭上眼睛想一想下面的问题,试着得到一个答案:
这是个高效生成HTML的方式?浏览器真的需要花费这么长的时间到服务端去拿这么简单的HTML?
开发人员不能直接写,这个很难吗?
如果你看到每个请求都有个请求的逻辑到服务端去生成HTML,那么在我们去拿grid, tree 等控件或生成更复杂的HTML表格,整个会话过程会很糟糕很耗带宽,处理这种不必要的请求而受到影响.
解决方案:“摆脱后置代码”,卷起袖子使用纯净的HTML。
Viewstate 在过去的10年里已经发展的非常的亲近,几乎是朋友了.
因为它可以自动保存状态减少开发时间,但是随之而来的是巨大的代价,ViewState让页面增长了相当地大. 在这个Load test中,我们看到与ASP.NET MVC相比,ViewState让页面大小增加了两倍.
下面 是Webfrom和ASP.NET MVC页面内容长度情况:
这个大小的增长是由于ViewState生成的额外字节.下面的是ViewState的截图,很多人可能会说可以禁用ViewState,如果有这样的选项,我们一定会尝试一下.
解决方案:“摆脱服务端的控件”
注意:下面的三个测试我们已经去掉了后置代码和服务端控件,对主要的问题总是性能问题.
现在由于我们省去了后置代码和服务端代码,我们“完全不知道”会得到什么样的HTML 和受到什么样的影响.例如下面的Code你能想象到会生成什么样的HTML?
<asp:Label ID="Label1" runat="server" Text="I am label"><asp:Literal ID="Literal1" runat="server" Text="I am a literal"><asp:Panel ID="Panel1" runat="server">I am a panel
那些Label会生成DIV 还是SPAN 标签?从下面的可以看到最后的结果,Label会生成一个SPAN,Literal生成简单的文字, Panel 生成DIV 标签等等…
<span id="Label1">I am label</span>I am a literal
I am a panel
所以直接写HTML比用服务端生成控件更好并且完全可以得到控制。
解决方案:“用直接写HTM来替代服务端控件”
直接写HTML来工作的其它的好处是网页设计人员很容易设计出很接近的网页,也可以用自己喜好的设计工具像:Dream weaver, front page等 没有依赖的设计,如果用服务端控件那些设计工具就很不容易去识别了.
如果你看任何专业的ASP.NET WEbform项目,你会注意到后置代码类非常的大而且相当的复杂, 后置Class继承自”System.Web.UI.Page”, 这个类不是可以被重用和在其它地方实例化的类, 换句话说 你不可以像下面这样用Webfrom类:
WebForm1 obj = new WebForm1();obj.Button1_Click();
因为“Webform” 类在没有”Request”和 “Response”对象时是不能被实例化的, 如果你在“Webform”中看到过“ButtonClick”事件,他们会像下面的code一下,从Code里就可以知道想要是同一个实例该有多麻烦了.
protected void Button1_Click(object sender, EventArgs e){ // The logic which you want to reuse and invoke}
解决方案:“从服务端控件和后置代码中解脱出来”
像前面刚讲到的不能直接实例化后置代码,这样就做单元测试或者自动化测试就非常困难。就必须要手动的运行程序做测试.
如果我们看前面用ASP.NET Webform所提到的4个问题,那么主要的罪犯就是两个人“后置代码”和“服务器控件”。下面是根本原因的图解,在这里我带着问题开始,什么造成了这样的原因,同样的解决方案又是什么?
解决方案是我们需要移动后置代码到被分离的简单类库中并且用简单的HTML来替代服务端控件. 类似下图:
就像说过的后置代码和服务端控件是根本原因,如果你看下当前开发者在用的Webform架构,基本是3层架构。这三层架构包括了ASPX和后置的CS代码.
这个UI跟.NET class 交互的class可以做为中间层,业务逻辑和中间层跟数据层交互.
所以ASP.NET MVC包括3部分:模型,视图,控制器. 后置代码逻辑放在了Controller中,View是你的ASPX,就像你干净的HTML,模型就是你的中间层. 你可以从前面的图形中看它们是如果适合的关联的.
所以你可以看到两个主要的改变:View �> HTML, code behind �> .Net class ( controller ).
在ASP.NET MVC中一般请求变成了:
步骤一: 先发送到Controller.
步骤二:根据Controller的Action创建模型的对象,模型调用数据访问层来获取数据。
步骤三:数据被填充到Model中,转交给View来达到显示的目的。
现在我们已经明白了ASP.NET MVC的不同组件,让我们来深入的了解每个组件。我们来做些试验,首先以Controller开始,因为它是MVC架构最重要的核心部分。
为了明白Controller,我们需要先明白这个用户相互作用术语逻辑。
场景 1:
你有想过当用户点击浏览器中的URL时发生了什么吗?
浏览器发送请求到服务器,服务器发送回来了个响应。
像这样的请求,客户端尝试去跟服务器交互。而服务端写了一些逻辑来响应这一请求。
一些逻辑?那么到底是什么逻辑?
一些可以处理用户请求和与服务器交互的逻辑。简单的来说是跟用户交互的逻辑。
场景 2:
它可能是服务器发送一个HTML的响应。HTML响应可以包含几个输入控件和一个提交按钮。
当点击”SaveCustomer”按扭的时侯会发生什么?
如果你的答案是“一些事件处理器将会处理这个按扭的点击事件”, 那么很抱歉。
实际上,在网络编程中没有事件的概念。在ASP.NET Webform的一些案例中,微软写了一些code来为我们带来了好处并且�我们带来了事件驱动编程的感觉。这只是个抽象或者正确的说是幻想。
当按扭被点击,一个简单的HTTP请求会被发送到服务器。这次的不同是,”Customer Name”,“Addres” 和“Age” 的值会随请求被发送到服器。(技术术语“值被发送到服务器”). 最终,如果它是个请求那么服务器上必须有个逻辑,这样服务器就可以将响应发送回来。总之,必须有一些用户交互逻辑写在服务服务器上。
在ASP.NET MVC中,最后一个字母C是Controller,将会处理用户交互的逻辑。
步骤 1 - 创建 ASP.NET MVC 5项目
步骤 1.1 打开VS 2013(或者更高版本的),点击 File>>New>>Project.
步骤 1.2 选择Web应用程序, 填写名称和位置然后ok.
步骤 1.3 选择MVC模板
步骤 1.4 改变认证
点击两次Ok,就好了。
步骤 2 - 创建 Controller
步骤 2.1 在解决方案浏览器的Controller文件夹右击Add>>Controller
修改Controller为TestController
最后要记得不能删除最后的”Controller“
步骤 3: 创建Action方法
打开新建的TestController类你会找到一个“Index”方法,用下面的公共方法“GetString”来替换“Index”。
public class TestController : Controller { public string GetString() { return "Hello World is old now. It’s time for wassup bro ;)"; } }
步骤 4。 执行和测试
在地址栏按F5,像下面这样放上"ControllerName/ActionName"。记得不要加最后的“Controller”
实验 1 的提问回答环节
TestController 和 Test 的关系是什么?
TestController 是一个类,但Test是controller的名字,注意当你在URL中输入controller名字的时侯应该去掉最后的"controller".
ASP。NET MVC遵循公约为基础的方法。它严格地看我们使用的约定。
在ASP.NET MVC有两件非常重要的事:
1. 怎么命名?
2. 怎么放置?
Action方法是?
Action是controller内接收用户请求并返回响应的简单公共方法。在上面的例子中,Action方法名“GetString”是返回一个string类型的响应。
注意:在ASP.NET Webform中默认返回一个简单的html响应。万一我们想要返回除了Html外的其它对象(在ASP.NET中). 我们创建一个HTTP处理器, 重写content type,返回响应等. 这不是个容易的任务。 在
ASP.NET MVC中非常容易。如果想要返回string类型你可以直接返回string,你不需要去发送完整的HTML。
如果我们从一个Action方法中返回一个对象将会发生什么?
我们来看看下面的代码块:
public class Customer { public string CustomerName { get; set; } public string Address { get; set; } } public class TestController : Controller { public Customer GetCustomer() { Customer c = new Customer(); c.CustomerName = "Customer 1"; c.Address = "Address1"; return c; } }
上面的Action方法会输出下面内容:
当返回对象是像“customer”一样的对象时, 会返回这个对象所实现的“ToString()”方法,返回这个类的完整名字“NameSpace.ClassName”
想在上面例子中得到什么值?
在下面的类中简单的重写ToString()方法:
public override string ToString() { return this.CustomerName + "|" + this.Address; }
是否必须使用公共访问修改器来装饰动作方法?
是的,每一个公共方法都会自动变成行动的方法。
有关非公开方法?
他们只是一个类的简单方法,对外不可见的方法,简单的来说这些方法不能被Web调用。
如果想要一个公共而不是Action的方法怎么做?
只是用“NonAction”修饰属性:
[NonAction] public string SimpleMethod() { return "Hi, I am not action method"; }
尝试访问这个方法会得到:
理解ASP.NET MVC 中的View
正如我们之前讨论的,Controller会处理用户的请求并且发送响应。最常见的响应是HTML, 它是浏览器理解的格式,含有一些图片,文字输入控件等的html。通常地在技术层面定义一个接口做为UI层而在ASP.NET MVC中称为VIew.
试验 2 - 演示Views
在第一个实验的MVC应用程序中只有个Controller和返回一个简单的String类型,让我们添加个View.
步骤 1 - 创建新的action 方法替代Test.
步骤 2 - 创建View
修改View内容:
运行得到:
为什么View被放在Test文件夹中?
在ASP.NET MVC中View被关联到与Controller指定的文件夹中,这个指定的文件夹将会被命名为controller的名字,那些view将会是对每个controller自己同名的文件夹可见。
例如:所有遇TestController相关的view将会被放在“~/Views/Test”并且Test Controller只可以访问那些放在Test文件夹的view。
View可以被多个Controller重用?
可以,对于这样的view,我们把它放在名叫“Shared”的文件夹中。
Shared中的view对所有的controller都可见。
一个action可以被多个view引用吗?
请查看下面的code:
public ActionResult GetView() { if (Some_Condition_Is_Matching) { return View("MyView"); } else { return View("YourView"); } }
注:在ASP. NET MVC视图和控制器不紧耦合。一个动作方法可以参考多个视图,一个视图可以被称为一个以上的动作方法(将它们放在共享文件夹中)。它提供了更好的可重用性。
视图功能的目的是什么?
创建ViewResult对象使视图响应。
ViewResult 是PageActivatorinternally内部创建的对象
ViewResult 选择正确的view引擎并且传递viewPageActivator 对象做为参数到引擎的构造函数
ViewEngine 创建View类的对象
ViewResult 调用 View的RenderView 方法
注: 我们在一系列讨论ASP.NET MVC生命周期细节中有单独的主题.
ActionResult和ViewResult之间的关系是什么?
ActionResult是抽象类而ViewResult是ActionResult多层次的Child。多层级是因为,ViewResult是viewresultbase的child,viewresultbase是ActionResult的Child。
如果要返回ViewResult为什么把ActionResult做为ViewResult?
实现多态,看下面的例子:
public ActionResult GetView() { if(Some_Condition_Is_Matching) { return View("MyView"); } else { return Content("Hi Welcome"); } }
在上面例子中,当匹配到有些条件时我们会引用View方法,会返回ViewResult,而其它条件我们会引用Content方法从而返回ContentResult.
什么是ContentResult?
ViewResult表是一个完整的HTML响应,而ConetntResult 代表一定数量文字的响应。就像返回纯粹的string,不同之处在于ContentResult是个ActionResult包装的string结果,ContentResult同样是ActionResult的子类。
在调用View方法时可以不用参数?
可以,那么它会找到 跟当前Action名字一样的View。
第二天学什么?
在第二天我们会讨论Models,Validation,Jquery 和Json.