`

由IsPostBack引发的思考

 
阅读更多

我看过无数篇讲解webform相关技术文章,其中不乏优秀的。但是据我看来,大多只是“知其然而不知其所以然”。主要是教你“如何做”,而很少有人会讲解其背后的原理。

这大概和微软的整个技术体系有关。呵呵。当然,这不是本章介绍的重点。本章中,我将借助一个常见的IsPostBack属性,从web本质去讲解,希望能引发读者的思考。

关于IsPostBack的解释,网上一搜,真实铺天盖地的。但我认为,总结的并不完善,而且初学者很容易被搞“晕”。


页面第一次加载:比如在浏览器地址栏中直接敲入“http://.../Index.aspx”并回车,默认是发送的是http get请求,IsPostBack为false

页面第二次加载:选中浏览器地址栏,再回车(或者直接刷新),默认发送的还是get请求,IsPostBack还是为false。反复操作,IsPostBack总是为false

所以,纠正一点。网上介乎所有的解释“IsPostBack”时候,都会提到了所谓的“第一次访问”或“第一次加载”,也有一定的道理。
但是,这样解释并不精确,有点牵强(是从MSDN直接机器翻译过来的)。尤其容易让初学者(或者从jsp、php转型过来的)弄晕。
有的初学者甚至会这样认为:我第一次打开index.aspx页面后,再刷新一下,这是第二次访问(页面加载)了,此时IsPostBack应该为true了吧。

我一直习惯从本质去看待技术,个人认为要想真正透彻的理解IsPostBack,必须要明白web应用的本质(例如基础的html、form、http协议等)
本章我就先不借助Reflector工具去反编译Page类和它的IsPostBack属性了,免得弄得有些读者一头雾水。


asp.net webform技术,很适合那些从传统C/S开发模式转型过来的开发人员,尤其是从事Windows桌面编程的,基于控件,事件驱动编程的。
为了提供这种方便,使BS/CS架构融合,其实webform技术幕后做了无数的工作,才使得很多开发人员感觉“asp.net和桌面应用差不多,都是拖控件,设属性,事件...”。
所以,那些不求甚解的“代码工人”,会感觉asp.net很简单,拖拖控件设属性事件绑定数据就好了。也就引发了业内对asp.net程序员的贬低。
相反,对于一开始从事过asp,jsp开发的人(我本人就是)来讲,更习惯从web开发的“请求/处理/响应”模型本质去探索、思考。

言归正传,回到主题,继续讲IsPostBack。先说说啥是“PostBack”吧。webform中所谓的PostBack(回发),其实是先Post然后再Back。啥意思呢?有朋友肯定会疑问了,难道我是用get请求就不行?当然不是了。还是先看图片:


点击之后呢:


看到了吧。我一点submite提交了表单后,页面刷的一下,文本框中中的值又变为空了,页面还原了,表单和按钮都还存在呢。这就是“Back”嘛(服务器端处理请求完成后,重新响应数据传给浏览器端,浏览器再呈现html)。如果你使用纯html,将表单提交给一个ashx程序去处理,ashx中只使用了一行Response.wrtite("Hello world")去响应用户的请求,并输出,你会发现:当你点击按钮之后,页面刷的一下,页面呈现给你的,只有一行"Hello world"了,页面上的表单元素,按钮等都不见了,这显然不是我们想要的效果。而在我们的aspx中,提交请求给后台去处理,后台同样只写了一行Response.wrtite("Hello world"),但结果会是这样:之前的表单、按钮等都存在,而且文本框的值也都空了,并且页面上多出一行“"Helloworld”来。所以,这说明在我们的webform模型中,服务器端在处理完请求之后,又会将之前页面的html数据重新响应给客户端,交给浏览器去渲染,再呈现给用户。这其实是个复杂的过程。明白了吗?webform的背后默默地做了无数的工作,以至于你习惯了觉得理所当然,都没有任何发觉,强大吧?包括webform的事件驱动、后台可以直接控件取值等等,其实都是模拟出来的。用性能消耗换换来方便。

那不用说了,我点击按钮提交表单,这个动作就是“Post”了。当然,这里所说的post,并不是只局限于post请求方式,像上面的例子中就是用的get方式提交表单的,实现了动态web应用的“请求/处理/响应”的流程。搞清楚了PostBack,再说Page类的这个IsPostBack属性,应该就好理解了。

其实IsPostBack表示的意思是“是否回发”。判断“是否回发”说通俗点就是:“你是只为了单纯的处理页面呈现,将动态网页变成html给客户端,还是处理客户端的请求,并做出相应”。说白了,就是是否发生了表单提交的submit动作。web中传统的表单提交动作,get方式请求,默认会将值放入url中,而post方式,默认将值放入form表单内一起提交。

一般情况,是表单提交的动作(且传过来了),不管是post还是get,浏览器客户端有传值过来,服务器端去处理并相应请求,IsPostBack属性则为True。

当用户使用get请求提交表单时,浏览器地址栏中可能会有如下的内容:

http://localhost:1749/WebForm1.aspx?__VIEWSTATE=%2FwEPDwULLTE2MTY2ODcyMjlkZHxr20KAwiI6Wo4w0Y%2FGZLgMrVuhJ87dK99bAggIeZZw&id=ff

这很正常,这是使用webform中使用的viewstate和隐藏域来存值(是base64位编码的)。把这段url拷贝到新的浏览器窗地址栏中,直接按回车,跟踪到后台代码中的Page_Load下面,IsPostBack属性还是true。

但是,如果你去掉或者修改了url中的“viewstate”(改一个字母都不行的), 再按回车,跳到后台去,IsPostBack属性将会变为false。

同样的,你直接在浏览器敲入localhost:1175/ISPostBackDemo.aspx?id=1,这样看起来也是在用URL传值,但这只是个普通的get请求,是不包含表单提交动作,而且没有隐藏域没有viewstate相关的数据。所以,IsPostBack还是false。

而我直接在浏览器中敲入的“.../Index.aspx”,没有表单提交动作,服务端只是负责呈现页面(转换成html),刷洗加载一万次,IsPostBack属性都还是false


网友总结如下结论:
结论① 对于使用Server.Transfer进行迁移时迁移到的页面其IsPostBack=false。

结论② Post方式如果Request中没有请求值,即Request.Form =null则IsPostBack=false;Get方式如果Request中没有请求值,即Request.QueryString =null则IsPostBack=false。

结论③ 如果QueryString或Form虽然有请求值,但是QueryString或Form中的Key没有“__VIEWSTATE”和“__EVENTTARGET”和“__VIEWSTATEFIELDCOUNT”,并且没有键为“null”,值以“__VIEWSTATE”开头并且也没有值为“__EVENTTARGET”的键值对,则IsPostBack=false。

结论④ 使用Response.Redirect方式向自画面迁移时,此时IsPostBack=false。

结论⑤ 发生跨页提交(CrossPagePostBack),当访问PreviousPage属性的时候,对于源Page,IsPostBack=true。

结论⑥ 发生跨页提交(CrossPagePostBack)时目标页面是IsPostBack=false

结论⑦ 使用Server.Execute迁移到的页面其IsPostBack=false。

结论⑧ 在Page运行期间其对应的DLL被更新了并且Page的树结构发生过变化,这种情况下请求时IsPostBack=false。

我个人再补充一点:当使用Ajax请求某个aspx页面时(也可以是请求本页面),无论是post还是get方式,默认情况下,IsPostBack总是为false

除非你使用:$(document.forms[0]).serialize() 作为参数传递,该方法能够自动序列化form表单的value,类似一次Post表单提交动作。其实因为提交了“_viewstate”相关的信息给服务器端,所以ispostback属性会变成true。

同理,你在后台使用服务端控件的取值时,如果禁用了viewstate,是无法取到值的。


小提示:Request.Form是指用form递交过来的数据。而Request.QueryString则是指用URL递交过来的。而Request中,包含了所有的请求信息。
还有点很多人都会误解的:当使用Request.Form["aaa"]或者Request["aaa"]去取值时,aaa其实是指的表单元素的name属性,而不是其id。
当使用服务端控件时,只有ID属性,例如 <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
默认情况下,解析成html后,将变成<input name="TextBox1" type="text" id="TextBox1" />。默认情况服务端控件的ID属性和隐藏的ClientID值一样。
但是,当aspx被父级包裹时(例如master模板页),解析成html后的id和name都会发生改变,这时候,ClientID就派上用场了。
分享到:
评论

相关推荐

    IsPostBack深入探讨 .txt

    IsPostBack深入探讨 .txtIsPostBack深入探讨 .txt

    IsPostBack的使用介绍

    主要讲解Asp.net中的IsPostBack的介绍,如何使用才有用。

    Ispostback在girdview绑定checkbox时的应用

    Ispostback在girdview绑定checkbox时的应用,明确写明了,gridview服务器回发是的刷新造成checkbox的checked总是FALSE得问题!

    ASP.NET中IsPostBack用法详解

    主要介绍了ASP.NET中IsPostBack用法,有助于读者进一步理解IsPostBack用法并加以灵活应用,需要的朋友可以参考下

    IsPostBack原理的介绍

    IsPostback的原理——————————————————————————– 一步一步让你看明白。。 先说说吧,然后在上代码。ispostback:就是判断页面是首次加载的,还是数据回发(有get或者post请求过的)后的...

    js基础js页面刷新问题

    js基础js页面刷新问题js基础js页面刷新问题js基础js页面刷新问题js基础js页面刷新问题

    Web Page的生命周期详解

    ASP.NET Web Page的生命... 在此阶段,每一个control的UniqueID属性被设置,页面的主题也被应用,如果此页面是回传页面,即Page的IsPostBack属性为true,那么页面里各个控件的新的值和ViewState还没有在此阶段被恢复。

    js刷新当前页面

    如果有这种应用: 我们需要重新加载该页面,也就是说我们期望页面能够在服务端重新被创建, 我们期望是 Not IsPostback 的。这里,location.replace() 就可以完成此任务。被replace的页面每次都在服务端重新生成。

    点击提交按钮后DropDownList的值变为默认值实现分析

    IsPostBack) { 你的绑定函数; } 否则,页面会重新加载,所有控件的值变为初始值。 IsPostBack是Page类有一个bool类型的属性,用来判断针对当前页是正在为响应客户端回发而加载还是正在被首次加载和访问。 当...

    asp.net2.0系列教程第2章_第1节

    页面生命周期 页面事件 Page_Load事件以及Page.IsPostBack 页面控件事件

    js刷新当前页面的几种方法(相当牛X)

    如果有这种应用: 需要重新加载该页面,也就是说期望页面能够在服务端重新被创建,期望是 Not IsPostback 的。 这里,location.replace() 就可以完成此任务。被replace的页面每次都在服务端重新生成。 代码: ...

    asp.net2.0系列教程第6章_第5节

    6章_第5节删除前添加确认提示 注意数据操作时Page.IsPostBack

    ASP.NET Page生命周期详解

    在此阶段,页还将确定请求是回发请求还是新请求,并设置IsPostBack属性。 (3)初始化页面:页面初始化期间,可以使用页中的控件,并将设置每个控件的UniqueID属性。如果当前请求是回发请求,则回发数据尚未加载,...

    web service 获取天气预报 源码 设计

    Page.IsPostBack) { BindPro(); BindCity(); BindWeather(); } } // 获得省份 protected void BindPro() { } protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e) { } ...

    Jquery 无刷新分页

    在网络里找来找去,找来找去...IsPostBack) //{ // pageCount = new PagerTestBLL.PersonManager().GetPersonCount().ToString(); //} } 使得可以用 html 显示,这个将会使找不代码的朋友,少受骗了. (带有数据库)

    UDropDownList

    拥有层级上下级关系的下拉列表且父级不能够选择服务器控件源码,绑定数据不要放到!IsPostBack里面

    asp.net 更换风格

    IsPostBack) { ltrStyleName.Text = userStyle; foreach (string styleName in styleConfig.StyleNames) { ListItem item = new ListItem(styleName); if (string.Compare(styleName, userStyle) == ...

    ASP.NET的网页代码模型及生命周期

    代码分离有一种好处,就是在.aspx页面中,开发人员可以将页面直接作为样式来设计,即美工人员也可以设计.aspx页面,而.cs文件由程序员来完成事务处理。同时,将ASP.NET中的页面样式代码和逻辑处理代码分离能够让维护...

Global site tag (gtag.js) - Google Analytics