不拖控件的asp.net之HttpHandler

 

    微软提供的一系列Web控件,固然用着很方便。但它的效率如何?它的原理是什么?为什么很多人都说ASP.NET开发的网站很慢?等等问题都是值得我们研究的。从一个牛人的文章中看到过这么一句话“一个合格的ASP.NET开发人员必须懂得如何不用控件(指Web控件)开发”。不错,学了这么长时间开发,一直没离开过那些用着很“舒适”控件。最近,从网上找资料学习(进行中)了HttpHandler、模板引擎、aspx和WebForm、ASP.NET MVC,以便能深入了解ASP.NET的原理,解开自己心中的那些疑惑。这里先介绍HttpHandler,其它东西之后会在之后的博客中介绍。


(1)HttpHandler的作用


    首先要明白浏览器与服务器请求-处理-响应的交互方式(看下图),当然HttpHandler(一般处理程序)扮演的即是服务器处理者的角色:

    



(2)下面简单介绍http协议及报文:


 协议

  ?  连接(Connection):浏览器和服务器之间传输数据的通道。一般请求完毕就关闭,不保持连接,或称为短连接。这样的优点是可以增强服务器处理的客户端并发请求数;缺点是会降低服务器处理速度,因为建立连接的速度很慢。

  ?  请求(Request):浏览器向服务器发送的请求信息,包含请求的类型、数据、浏览器(客户端)的信息(语言、浏览器版本、IP地址)等。

  ?  响应(Response):服务器处理浏览器请求后返回的数据,包含请求是否成功、错误码等。


 报文(以IE浏览器请求“百度首页”为例)

  请求(Request):

  如下图为百度首页的请求数据报(请求方式为Get时请求传递的数据(参数等)都会在下图的请求标头中(此时请求正文为空),为Post时数据会转到请求正文中。

  Get/HTTP/1.1表示向服务器用GET方式请求page,使用Http1.1协议。

  Accept-Language表示浏览器支持的语言种类。

  Referer:为(图片、js、css文件等)来源页面、所属页面。

  


  响应(Response):

  响应码:“200”OK 表示请求响应成功;

      “302”:Found表示重定向,Response.Redirect()使浏览器再请求一次重定向的地址,重定向请求方式为Get。

      “404”:Not Found表示未找到所请求页面。

      “500”:表示服务器内部出现错误

    Content-Type:text/html:表示返回数据的类型,服务器通过此属性告诉客户端响应的数据的类型,这样浏览器就根据返回数据的类型来进行不同的处理,如果是图片类型(image/gif)就显示,如果是文本类型(text/plain)就直接显示纯文本代码等等。这就是为什么要在一般处理程序中设置ContentType属性(例:context.Response.ContentType = "text/html";)

  


(3)HttpHandler代码演示


 Test1

  先看一个最简单的HttpHandler:

  

    public class TestHandler1 : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            //将ContentType = "text/plain";改为“text/html”
            context.Response.ContentType = "text/html";
            //接受两个参数name、age
            string name = context.Request["name"];
            int age = Convert.ToInt32(context.Request["age"]);
            //返回给浏览器一句话
            context.Response.Write("Hello" + name + " 您的年龄是:" + age);
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}


  运行这个一般处理程序,然后“手动”给浏览器地址栏的地址添加两个参数,例如:

  

  这样即可运行处结果:Hello zhipeng您的年龄是24

 Test2

  由于手动添加参数很麻烦,且容易出错,所以用Html表单(form)自动给服务器提交参数。于是将上例中的一般处理程序保持不变,然后添加一个html页,代码如下:

  

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form action="TestHandler1.ashx" method="post">
        姓名:<input type="text" name="name" /><br />
        年龄:<input type="text" name="age" /><br />
           <input type="submit" value="提交" name="haha" />
    </form>
</body>
</html>


 步骤:

  ?  首先添加<form></form>标签,因为只有它内部的东西才可能提交给服务器(一般处理程序),然后设置它的action和method属性。分别指明提交给哪个HttpHandler和提交方式

  ?  然后需要设定html页中表单元素的name属性,这里注意,id(不可重复)主要是给js操作dom用的,name(可以重复)才是提交给服务器用的。

  ?  然后服务器端(一般处理程序)就可用context.Request[“username”]来根据name属性来获得提交的属性。

 注意:

  ?  将用户填写的内容提交的服务器有如下条件:只有三类标签input、textare、select;只有value值会被提交;标签必须设定name属性;标签必须放到form标签内

  ?  get(默认值)通过url传递表单值,传递数量有限,不传输大量或敏感的数据;post传递的表单值隐藏到http报文中,url中看不到,传递数量无限制。下图为分别为get和post时的报文:

  get时,请求标头中含有请求时发送的数据;请求正文为空:


   


  post时,请求时发送的数据从标头字符串中,转移到请求正文中:


   


 Test3

  下面做一个简单的小例子,如下图,如果用户名和密码都为admin时,则页面提示"恭喜,登录成功!",否则提示"用户名或密码有错误!"。

   

  较特殊的地方是将所有的代码都放到HttpHandler中,代码如下:

  

    public class TestHandler2 : IHttpHandler
    {

        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/html";
            //取出请求中的参数username和password
            string userName = context.Request["username"];
            string passWord = context.Request.QueryString["password"];
            //定义画表单page的字符串
            string html = "<html><head></head><body><form action=‘TestHandler2.ashx‘>用户名:<input type=‘text‘ name=‘username‘ value=‘{username}‘/><br/>密 码:<input type=‘password‘ name=‘password‘ value=‘{password}‘ /> <input type=‘submit‘ value=‘登录‘/></form><p>{msg}</p></body></html>";
            //判断,如果username和password为空则将字符串html中的占位符{username}、{password}、{msg}分别替换为空,然后将字符串返回给浏览器进行解析
            if (string.IsNullOrEmpty(userName) && string.IsNullOrEmpty(passWord))
            {
                string code = html.Replace("{username}", "");
                code = code.Replace("{password}", "");
                code = code.Replace("{msg}", "");
                //将字符串返回给浏览器
                context.Response.Write(code);
            }
            else
            {
                //如果用户名、密码都正确则将字符串“恭喜,登录成功!”返回给浏览器
                if (userName == "admin" && passWord == "admin")
                {
                    context.Response.Write("恭喜,登录成功!");
                }
                //如果用户名或密码填写不正确,则将填写的信息填充标签的值,并将占位符{msg}替换为“用户名或密码有错误”进行提示
                else
                {
                    string code = html.Replace("{username}", userName);
                    code = code.Replace("{password}", passWord);
                    code = code.Replace("{msg}", "用户名或密码有错误!");
                    context.Response.Write(code);
                }
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}


  其实上例中的字符串html就是一个表单模板,可以真对不同的情况,对该模板进行不同的处理(上例采用的字符串替换方式),但是这种方式不利于美工的修改,且难实现复杂的业务逻辑。为此引出了“模板引擎”的概念,模板引擎的作用、优势以及强大功能会在下篇文章介绍。

(4)总结

  控件不是洪水猛兽,学懂了如何不脱控件进行.NET开发,了解它本质的东西,然后开发时就可以根据不同的需求多一种选择方向。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。