[ASP.NET]从ASP.NET Postback机制,到POST/GET方法

写这篇博客的起源来自于本身最近在学习ASP.NET时对于 PostBack机制的困惑。由于本身在解决困惑地同时,会不断产生新的疑问,所以博客最后深刻到了http 包的格式和Internet所使用的TCP/IP模型,算是来了一堂基础复习课。但我相信这些基础的牢固性,会影响到web方向的深刻学习,所以整理成文,便于复习,便于探讨。javascript

写博的时候并无将http协议包格式等底层的东西调整到最前面写,由于我以为既然我是这样思考的,何不这样呈现?为了便于描述,我用下图这棵树表示写这篇博文的思路,IsPostBack是表面的引发疑问的叶子,顺着这片叶子,能够逐渐追溯到http协议这个树干。“Post与Get方法”那一块被安排在树干上,是由于从这里开始,触及了Web开发的主体;枝叶上的ASP.NET部分,只是基于这个主体又加入本身的技术的延伸。别的技术好比JSP,Struts等Java方向的技术,也是基于这个主体的另外一种技术方向的延伸,所以它们都会像树枝同样,从主干上发散开。html

博文中有任何以为不对的地方,欢迎在留言中和我探讨。毕竟我也只是刚接触Web不久的Fresh Man,行文之时,心下惴惴,所以欢迎指出错误和讨论。前端

PostBack机制

什么是Postback?IsPostBack的做用是什么?java

PostBack机制是ASP.NET特有的机制,为何说特有,咱们从web请求和响应提及。web

web的基本原理就是请求和响应。以asp为例,Browser端的HTML文本,以及javascript代码,运行后向server端发送request,server端的.asp脚本,接受request,处理后发出respond。这种server端script和client端script交互,完成一次次对于用户操做(提交表单,载入新的URL)的响应。ajax

以一个html文件和asp文件为例:后端

html代码:浏览器

<!DOCtype html PUBLIC "-//W3C//DTD XhTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>order</title></head>
<body>
<h2>Form Example</h2>
<p>
Please input and submit
<form method="POST" ACTION="Response.asp">
<p>
姓: <input NAME="fname" SIZE="48"/>
<p>
名: <input NAME="lname" SIZE="48"/>
<p>
称呼: <input NAME="title" type=RADIO VALUE="先生"/>先生
<input NAME="title" type=RADIO VALUE="女士"/>女士
<p><input type=SUBMIT VALUE="提交"/><input type=RESET VALUE="清除"/>
</form>
</body>
</html>
Response.asp脚本代码(VB语言)
<HTML>
<HEAD></HEAD>
<BODY>
<%
Title = Request.Form("title")
LastName = Request.Form("lname")
If Title = "先生" Then
Response.Write LastName & "先生"
ElseIf Title = "女士" Then
Response.Write LastName & "女士"
Else
Response.Write Request.Form("fname") & " " & LastName
End If %>
</BODY>
</HTML>

能够看到HTML文件的form控件中,"action"属性指定了form提交后处理它的Server端脚本。安全

而在ASP.NET系统中,咱们没有Client端和Server端脚本,咱们只有aspx文件,而aspx也会被Render为HTML,在Client端经过浏览器显示,由于浏览器只能识别HTML标签。服务器

下面的例子引自Artech的浅谈ASP.NET的Postback,这篇文章讲解了Postback的实现方式,简单说来:Render以后的HTML会自动加入一个form,其中用hidden的input来存储id和事件参数。在__Postback这个函数中,form中的内容会被提交。Artech所给的aspx代码在Browser端的呈现出来的源码以下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>
            Test Page
        </title>
    </head>
    <body>
        <form name="form1" method="post" action="Default.aspx" id="form1">
            <div>
                <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
                <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
                <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTA0NDQ2OTE5OWRk281L4eAk7iZT10hzg+BeOyoUWBQ=" />
            </div>

<script type="text/javascript">
                <!--
var theForm = document.forms['form1'];
if (!theForm) {
    theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument) {
    if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value = eventTarget;
        theForm.__EVENTARGUMENT.value = eventArgument;
        theForm.submit();
    }
}

</script>

<div>
<span id="LabelMessage" style="color:Red;"></span>
</div>
<div>
    <input type="submit" name="Button1" value="Button1" id="Button1" />
    <input type="button" name="Button2" value="Button2" onclick="javascript:__doPostBack('Button2','')" id="Button2" />
    <input type="button" name="Button3" value="Button3" onclick="javascript:__doPostBack('Button3','')" id="Button3" />
</div>
</form>
</body>
</html>

以上代码在Artech博文中也能够找到,我把它贴过来,以方便引述。这段代码是Default.aspx被render到browser端的html源码,Postback的实现机制就是定义了一个form,这个Form中包含隐藏的input,从而保存须要post的值,那么,向哪里post?Form中"action"属性指定了post的目标,那这里呢?咱们能够看到其值为"Default.aspx",也就是它本身。这和上面那个ASP的例子中是不一样的。

个人理解是:所谓Postback,是指在ASP.NET机制中,不是Client端发post请求到server端脚本,在这个机制中,aspx被render到browser后,其Form的post目标依然是这个aspx。Postback由此得名,由于post回来了。。

所以当咱们触发网页的按钮时,若此按钮涉及到后台操做(在后端有C#响应代码,而非仅仅调用前端javascript函数),aspx页面便会从新加载,由于Postback触发了它。(这句话待商榷,我对Postback与page life cycle了解再深入些后,会再编辑这句话)。

这个机制所须要解决的第一个问题是:当开发人员编写代码时,aspx的加载有两种缘由:点击按钮触发post来让aspx加载;用户输入url来加载aspx。对于不一样的缘由,可能开发人员但愿代码进入不一样的处理逻辑。IsPostback这个ASP.NET所给的变量,就是用来给developer肯定是否这个网页是由于postback而加载,而是经过输入url或者刷新页面的方式来加载。

最简单的例子,Page_Load()方法里常常会 if(!IsPostBack) BindForm();//给表单全部控件赋值的方法。意思是提交后我就不绑定表单了,而是走Click的具体事件方法。

而IsPostBack是什么时候被赋值的,ASP.NET代码中是根据什么条件来判断是不是postback的网页,这一个树枝暂时尚未研究下去,若是能有前辈能在留言中给我一些线索的话,感激涕零 :)

有关于Page_Load()方法,它是ASP.NET中的网页载入过程当中page load事件的默认响应函数,具体请参见:

ASP.NET 页生命周期概述  以及 [ASP.NET]Page Life Cycle整理

所以Postback的机制本质实现实际上是form的post,那么post和get,这些具体是什么?

POST与GET方法

正如以前所说,web实际就是request与respond的交互,那么,这些request与respond,其实就是http包。

对于一个Request,它可能不只仅是一个要求载入页面的request,也多是要求发送一些数据的request,或者要求删除服务端一些数据的request,如何区分这些request?http给request定义了四个谓词:POST,GET,PUT,DELETE。从名字就能够看出来他们的功用,分别对应着改,查,增,删。

而最常使用的是GET与POST。

他们的共同点和区别在哪里?

共同点是:GET POST其实均可以实现向服务器传送数据。在HTML中,自己表单form的提交就有两种方式,一种是get的方法,一种是post 的方法。而这两种方法保存参数的方式是不一样的,若是使用Fiddler或其余的http包查看工具,能够发现post方法提交的Form,其参数存在body中,而get方法提交的form,其参数则直接加入到url的后面。

经过包来看二者之间本质的差异的例子,能够参见淺談 HTTP Method:表單中的 GET 與 POST 有什麼差別?

经过输入url来访问页面,其request都是get。

二者特性上的差异:form方式由于是将内容放在body中发过去,而get仅仅是发一个get请求过去,内容在url中,所以速度比post快,而安全性则低于post。

GET的response会被cache,而POST的response不会。由于GET的初衷就是获取内容,所以能够经过cache来存储不变的内容,而POST则是用来提交内容,其响应基于所提交的内容可能不断变化。

二者之间其余差异参见下图,图来自[HTTP]Http GET、POST Method

有一篇文章提到了在使用Ajax时,POST会比GET慢数倍,各位有兴趣能够看一下:打破沙鍋-AJAX POST比GET效率差?

以前提到既然request和response实际就是HTTP包,那POST与GET这些谓词又是如何在包中呈现的?

POST与GET报文格式

 以Artech的那个例子为例,那个例子若是运行起来,会看到三个按钮,点击其中一个,会显示哪一个按钮的click被fire了:

点击Button3后,request与response在fiddler中的内容如图:

在fiddle中,能够看到POST就出如今Request的第一行中。

Response的Header的内容是:HTTP/1.1 200 OK

 

 一个http请求报文的格式以下图 (图片来自计算机网络应用层之HTTP协议)

 分为请求行(Request line),首部行(Header line),空行(Brank line)和实体(body),谓词方法的位置就在请求行的开头。

HTTP响应respond的报文格式以下:

其中200为状态码,表示请求成功。返回内容在实体中呈现,好比以前fiddler的截图,响应包中的内容就是原先那个HTML的内容,也就是说,浏览器收到这个response后,用户会看到整个页面被刷新了一下。

咱们知道了http的报文格式,那什么是HTTP协议?

HTTP协议

HTTP是HyperText Transfer Protocol即超文本传输协议的缩写,是Web应用层协议之一。

在说这个以前,先提几个HTTP的特性,这部分引用了Tank的 HTTP协议详解 中部份内容

HTTP协议是无状态的:同一个客户端的此次请求和上次请求是没有对应关系,对http服务器来讲,它并不知道这两个请求来自同一个客户端。 为了解决这个问题, Web程序引入了Cookie机制来维护状态。引入了ViewState来存储控件内容或者用户自定义信息。

关于Cookie的介绍,读写方式,以及它在ASP.NET form authentication中所起的做用,参见:Fish Li的细说Cookie

关于ViewState:个人理解是一种在用户端存储控件内容和一些开发人员自定义内容的机制。其实现方式是在用户端的HTML代码中插入名字为"__ViewState"的hidden input,那些须要存储的内容,都通过Base64编码后以字符串的形式存储在这个hidden input中。由于是以字符串的形式存储在客户端的HTML文件中,所以属于长期储存,不会自动过时或消失,用户甚至能够拷贝下来保存。更多内容,参见 [.NET] ASP.NET 狀態管理(State Management):ViewState

打开一个网页须要浏览器发送不少次Request:

1. 当你在浏览器输入URL http://www.cnblogs.com 的时候,浏览器发送一个Request去获取 http://www.cnblogs.com 的html.  服务器把Response发送回给浏览器.

2. 浏览器分析Response中的 HTML,发现其中引用了不少其余文件,好比图片,CSS文件,JS文件。

3. 浏览器会自动再次发送Request去获取图片,CSS文件,或者JS文件。

4. 等全部的文件都下载成功后。 网页就被显示出来了。

 

因为HTTP是使用TCP做为其运输协议的,所以http协议也须要链接,也须要三次握手的过程。

TCP链接分为持久链接和非持久链接:

在非持久链接的状况下,服务器在发送响应后,关闭TCP链接。咱们定义往返时间RTT为一个小分组从客户机到服务器再回到客户所花费的时间。因此RTT包括分组传播时延、排列时延以及分组处理时延。

若http采用非持久链接时,咱们能够估算出完成一次传输所消耗的时间:完成了三次握手的前两部分后,客户机将三次握手的第三部分(确认)与一个HTTP请求报文结合起来发送到该TCP链接。一旦请求报文到达服务器,服务器向该TCP链接发送HTML文件。从上面的描述,咱们能够知道,对于一个非持久链接,请求一个HTTP请求/响应须要的总时间为两个RTT+服务器传输HTML文件的时间,也就是两个来回所耗的时间加上传输时间。

在持久链接状况下,服务器在发出响应后让TCP链接继续打开着。同一对客户/服务器之间的后续请求和响应能够经过这个链接发送。整个Web页面(上例中为包含一个基本HTMLL文件和10个图像的页面)自不用说能够经过单个持久TCP链接发送:甚至存放在同一个服务器中的多个Web页面也能够经过单个持久TCP链接发送。一般,HTTP服务器在某个链接闲置一段特定时间后关闭它,而这段时间一般是能够配置的。
持久链接分为不带流水线(without pipelining)和带流水线(with pipelining)两个版本。若是是不带流水线的版本,那么客户只在收到前一个请求的response后才发出新的request。带流水线则是不等到response就发下一个request。这样,在密集请求的状况下,不带流水线的每个请求响应过程都比带流水线的慢一个RTT,由于后一个基本没必要等,前一个至少每次等一个RTT。
 
HTTP/1.1的默认模式使用带流水线的持久链接。这种状况下,HTTP客户每碰到一个引用就当即发出一个请求,于是HTTP客户能够一个接一个紧挨着发出各个引用对象的请求。
 
HTTP是Web应用层协议之一,那么它在整个网络之中如何传递呢?

网络分层结构

咱们知道互联网的框架主要是两种:OSI的七层框架,和TCP/IP体系结构。而Internet网络体系结构以TCP/IP为核心。基于TCP/IP的参考模型将协议分红四个层次。

这两种模型的对应关系如图,图片来自网络互联参考模型(详解)

而咱们以前应用层的http报文,从最高层往下经历层层封装,最后到达最底层转换为01流。发往目的地,中间会通过交换机和路由器的中转,解包,确认下一个转发地址后再次封包转发。以下图 (图片来自网络互联参考模型(详解))

 

相关文章
相关标签/搜索