在《避开WebForm天坑,拥抱ASP.Net MVC吧》这篇博客中我讲到了ASP.net WebForm因为一些先天的“诱导犯罪”的缺陷,如今用ASP.net MVC的公司愈来愈多。可是根据那篇文章末尾的"ASP.net MVC的免费网络公开课"调查表的统计,咱们发现有一大半的人尚未使用过ASP.Net MVC,而没用过ASP.net MVC的人中居然有不少人人是由于感受ASP.Net 难、没时间学。调查表分析数据以下:html
初看ASP.net确实难:复杂的路由机制、 ViewData/ViewBag/TempData、过滤器、Razor、Layout、XXXHelper、验证、WebAPI、依赖注入、单元测试……光看这一堆概念头就晕了,“仍是拖控件简单”。前端
其实学习一个新的框架,只要搞清他的原理就会“豁然开朗”,再看其余的东西就不会感受恐惧了。程序员
这篇文章我将会带着你们搞明白什么叫MVC模式,而且带着你们用你们熟悉的Asp.Net WebForm实现MVC!数据库
对!你没听错!缓存
用Asp.Net WebForm实现MVC!安全
再次感觉一下ASP.net WebForm吧。服务器
假设有一个Person对象的集合,咱们要在网页中以html渲染,那么要以下编写网络
<table> <asp:Repeater ID="Repeater1" runat="server"> <ItemTemplate><tr><td><%#Eval("Name") %></td><td><%#Eval("Age") %></td></tr></ItemTemplate> </asp:Repeater> </table>
C#代码:架构
if(!IsPostBack) { List<Person> list = new List<Person>(); list.Add(new Person { Name = "rupeng", Age = 8 }); list.Add(new Person { Name = "qq", Age = 18 }); Repeater1.DataSource = list; Repeater1.DataBind(); }
这样作的缺点是C#代码中访问了apsx中的控件Repeater1,也就是在aspx中必需要有一个Repeater类型、Id为Repeater1的控件,这样aspx就和C#代码耦合在了一块儿。麻烦在哪儿呢?并发
1)若是aspx有两个地方都要用list了,那么就要写两组DataSource=list;DataBind();
2)若是aspx中忽然不想要Repeater了,把Repeater1删掉C#代码就会报错
3)Aspx中突然不想用Repeater进行数据的显示了,想换别的控件,那么C#代码也要改
再好比,在ASP.Net WebForm中,实现加法计算器会以下实现:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> +<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox> <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="=" /> <asp:TextBox ID="TextBox3" runat="server"></asp:TextBox>
protected void Button1_Click(object sender, EventArgs e) { int i1 = Convert.ToInt32(TextBox1.Text); int i2 = Convert.ToInt32(TextBox2.Text); int i3 = i1 + i2; TextBox3.Text = i3.ToString(); }
后台的C#代码和aspx的耦合要求aspx视图中必须有三个名字各为TextBox一、TextBox二、TextBox3的TextBox类型的服务器控件。若是我想把计算的结果从TextBox改为span就不行。前端设计人员看到TextBox绝对没有input亲切,前端人员对input 的把控能力会被TextBox更好。另外没必要再说WebForm引入的ViewState、页面生命周期、ClientID等使人做呕的问题。
有同窗会说了:你有病吗,开发时候aspx怎么可能老是变来变去,即便aspx变了,你C#代码也就变呗,有什么大不了的?
若是说系统小的话可能无所谓,对于比较复杂的系统,若是aspx和C#这样紧密的耦合,维护还会特别麻烦。并且若是实现像一些CMS系统那样能够动态修改模板文件的话就是存在着“C#没法预测、没法强制要求aspx到底怎么写”的问题。
这还仅仅是展现一个集合的问题,若是要展现复杂的扁平化数据或者须要从用户输入中获取数据,用这种方式更灾难。
那么MVC思想怎么解决呢?逻辑代码(Controller)不直接和页面视图(View)进行交互,他们之间用Model(数据模型)做为沟通的通道。当须要展现数据的时候由Controller收集到数据(Model),而后把数据交给View去展现;当Controller须要读取View中用户输入内容的时候,框架会把View中的数据映射到Model中,而后Controller读取Model中的数据进行后续的逻辑处理。这样就把逻辑代码(俗称C#代码)和视图(俗称页面)进行解耦了。
光说概念没用,仍是先看代码把。下面使用MVC模式改造的“显示Person集合”:
View视图PersonsView.aspx
<%@ Page Language="C#"%> <%@ Import Namespace="System.Collections.Generic" %> <%@ Import Namespace="WebApplication1" %> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> </head> <body> <table> <% var persons = (List<Person>)Context.Items["persons"]; foreach(var person in persons) { %> <tr><td><%=person.Name %></td><td><%=person.Age %></td></tr> <% } %> </table> </body> </html>
注意,我把aspx相关的两个自动生成的.cs文件删掉了,而且把<%@Page%>标签的AutoEventWireup、CodeBehind、Inherits等几个属性也都干掉了,这样aspx就变成了一个纯粹的“模板引擎”
做为Controller的Index.ashx的代码以下:
public void ProcessRequest(HttpContext context) { List<Person> list = new List<Person>(); list.Add(new Person { Name="rupeng",Age=8}); list.Add(new Person { Name = "qq", Age = 18 }); context.Items["persons"] = list; context.Server.Transfer("PersonsView.aspx"); }
这里借鉴了JSP中“request.getRequestDispatcher("index.jsp").forward(request,response)”同样的思路。
context.Server.Transfer是在服务器内部把请求处理权转交给"PersonsView.aspx"处理。HttpContext中的Items的生命周期是整个请求响应,这样咱们在通常处理程序中把数据放到context.Items中,而后在"PersonsView.aspx"中就能够能够经过Context.Items["persons"]拿到这个数据从而进行数据的展现。
为何把数据放到HttpContext.Items中呢。因为Transfer仅仅是服务器内部处理权的转接,可是仍然是在一个请求中的,因此放到Context.items是最好的。若是放到Session、Application等中会有并发的问题。
这样Controller(通常处理程序)和View(aspx)之间只要维持一个“要传递一个名字为persons类型的List<Person>”这样一个弱耦合关系便可,至于aspx用不用这个persons、用几回persons、怎么用persons,你Controller都不用管。
按照一样方法改造加法计算器
下面是视图AddView.aspx的代码
<%@ Page Language="C#"%> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <%dynamic viewBag = Context.Items["ViewBag"]; %> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>加法计算器</title> </head> <body> <form id="form1"> <input type="hidden" name="action" value="addSubmit" /> <input type="text" name="i1" value="<%=viewBag.i1 %>" />+<input type="text" name="i2" value="<%=viewBag.i2%>" /> <input type="submit" value="=" /><input type="text" value="<%=viewBag.i3 %>" /> </form> </body> </html>
而AddHandler.ashx的主体代码以下:
public void ProcessRequest(HttpContext context) { string action = context.Request["action"]; dynamic viewBag = new System.Dynamic.ExpandoObject(); if(string.IsNullOrEmpty(action)) { viewBag.i1 = ""; viewBag.i2 = ""; viewBag.i3 = ""; } else if(action=="addSubmit") { int i1 = Convert.ToInt32(context.Request["i1"]); int i2 = Convert.ToInt32(context.Request["i2"]); int i3 = i1 + i2; viewBag.i1 = i1; viewBag.i2 = i2; viewBag.i3 = i3; } context.Items["ViewBag"] = viewBag; context.Server.Transfer("AddView.aspx"); }
因为View和Controller之间传递的数据比较复杂、比较多,为了简化开发,这样用了dynamic 动态类型。熟悉ASP.Net MVC的同窗是否是感受这个和ASP.net MVC中的ViewBag殊途同归呢。
在这个加法计算器中若是我想把结算结果用span显示,那么只要把<input type="text" name="i3" value="<%=viewBag.i3%>" />改为<span><%=viewBag.i3%></span>就能够了。美工也容易介入页面美化。
若是我想把页面的Title从“加法计算器”改为“3和5相加的结果”,那么只要这样改就能够:<title><%=viewBag.i1 %>和<%=viewBag.i2 %>相加的结果</title> 这样model里的数据我aspx想用几回用几回,想怎么用就怎么用。有没有感受到和WebForm不同的地方呢?
因此只要思想一想通了,其实实现MVC模式不必定要用ASP.net MVC,我见过不少项目都是本身搞的MVC机制。
固然既然ASP.net MVC已经这么优秀了,通常状况不必像我这样从新本身发明一个轮子用。
这里给你们讲ASPX实现MVC只是用你们熟悉的东西让你们明白原理,工程项目应用仍是直接用ASP.Net MVC吧。
如鹏网.Net培训班正在报名,有网络的地方就能够参加如鹏网的学习,学完就能高薪就业,点击此处了解
三年前只要懂“三层架构”就能够说“精通分层架构”;如今则须要懂IOC(AutoFac等)、CodeFirst、lambda、DTO等才值钱;
三年前只要会SQLServer就能够说本身“精通数据库开发”;如今则需还须要掌握MySQL等开源数据库才能说是“.Net开源”时代的程序员;
三年前只要会进行用户上传内容的安全性处理便可;如今则须要熟悉云存储、CDN等才能在云计算时代游刃有余;
三年前只要掌握Lucene.Net就会说本身“熟悉站内搜索引擎开发”;如今你们都用ElasticSearch了,你还用Lucene.Net就太老土了;
三年前发邮件仍是用SmtpClient;如今作大型网站发邮件必须用云邮件引擎;
三年前缓存就是Context.Cache;如今则是Redis、Memcached的天下;
如鹏网再次引领.Net社区技术潮流!点击此处了解如鹏网.Net最新课程