zoukankan      html  css  js  c++  java
  • 不用asp.net MVC,用WebForm照样可以实现MVC(请看最后一句话)

        在《避开WebForm天坑,拥抱ASP.Net MVC吧》这篇博客中我讲到了ASP.net WebForm由于一些先天的“诱导犯罪”的缺陷,现在用ASP.net MVC的公司越来越多。但是根据那篇文章末尾的"ASP.net MVC的免费网络公开课"调查表的统计,我们发现有一大半的人还没有使用过ASP.Net MVC,而没用过ASP.net MVC的人中竟然有很多人人是因为感觉ASP.Net 难、没时间学。调查表分析数据如下:

     

        初看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视图中必须有三个名字各为TextBox1、TextBox2、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最新课程

  • 相关阅读:
    Ubuntu配置sublime text 3的c编译环境
    ORA-01078错误举例:SID的大写和小写错误
    linux下多进程的文件拷贝与进程相关的一些基础知识
    ASM(四) 利用Method 组件动态注入方法逻辑
    基于Redis的三种分布式爬虫策略
    Go语言并发编程总结
    POJ2406 Power Strings 【KMP】
    nyoj 会场安排问题
    Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor.
    Java的String、StringBuffer和StringBuilder的区别
  • 原文地址:https://www.cnblogs.com/rupeng/p/5074793.html
Copyright © 2011-2022 走看看