Go homepage(回首页)
Upload pictures (上传图片)
Write articles (发文字帖)

The author:(作者)归海一刀
published in(发表于) 2014/1/30 1:28:53
IsPostBack深入分析_[Asp.Net教程]

IsPostBack深入分析_[Asp.Net教程]
1、IsPostBack 介绍
IsPostBack是 Page类有一个 bool类型的属性,用来判断针对当前 Form的请求是第一次还是非第一次请求。当 IsPostBack= true时表示非第一次请求,我们称为 PostBack,当 IsPostBack= false时表示第一次请求。在 asp.net框架内部有很多的场景需要判断 IsPostBack,比如 LoadAllState等操作就需要在 PostBack的时候进行。对于我们自己使用 WebForm进行开发时,经常会在 Page_Load中对 IsPostBack进行判断,因为第一次请求的时候会执行 Page_Load,在非第一次请求的时候也会执行 Page_Load。为什么对同一个 Form有多次请求呢? asp.net中引入了服务器端事件,支持服务器端事件的控件,会发出对当前 Form的请求,这样在很多情形下我们就需要区别是否是对这个 Form的第一次请求。

2、IsPostBack 结论
本人对 .Net的源代码中相关的处理进行的分析得到如下的结论:
结论① 对于使用 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。
可以这样来理解这些结论:一般情况判断 Request中如果没有请求值则 IsPostBack= false。如果有请求值但是不包括 “__VIEWSTATE”等一些特殊的键或值,则 IsPostBack= false(每次请求后 .Net框架会将一些特殊的隐藏域“ __VIEWSTATE ”等返回给客户端)。还有一些特殊的情形是上面的规则不能正确判断的需要特殊处理的,这些情形包括 Server.Transfer, Response.Redirect, CrossPagePostBack, Server.Execute,发生了页面元素变化及重新编译。
一般来说记住上面的结论就可以,如果您有兴趣,或者怀疑请继续看下面的 IsPostBack推论过程。
3、IsPostBack 推论过程
下面是根据 .Net框架中的源代码,来分析 IsPostBack是如何判断出来的。对于这些结论的推断本人做了相关的试验来证明推论的正确性,由于篇幅的原因没有将这些试验代码体现出来。另外不可能将全部的 .Net框架的代码都体现出来,只是将相关的代码片段列出,说明推断的依据。另外由于本人水平有限对 .Net框架的代码理解还存在的不足的地方,请发现后进行指正,谢谢。

public bool IsPostBack
{
get
{
if (this._requestValueCollection == null )
{
return false ;
}
if (this ._ isCrossPagePostBack )
{
return true ;
}

if (this _pageFlags [8])

{

return false ;

}

return (

(

(this.Context .ServerExecuteDepth <= 0 ) ||

((this.Context .Handler != null ) &&

(base.GetType () == this .Context .Handler .GetType ()))

) && !this._ fPageLayoutChanged

);

}

}

我们将每一个 if判断作为一个小节,作如下的分析。

3.1 this._requestValueCollection == null

if (this._requestValueCollection == null )

{

return false ;

}

可以看出 _requestValueCollection等于 null时 IsPostBack就等于 false。

在 Page.ProcessRequestMain(bool , bool ) 中有如下的代码:

if (this .PageAdapter != null )

{

this ._requestValueCollection = this .PageAdapter.DeterminePostBackMode();

}

else

{

this ._requestValueCollection = this .DeterminePostBackMode();

}

PageAdapter.DeterminePostBackMode 最终还是调用了 Page.DeterminePostBackMode ,下面我们看 Page.DeterminePostBackMode 如何实现。

protected internal virtual NameValueCollection DeterminePostBackMode()

{

if (this .Context.Request == null )

{

return null ;

}

if (this .Context.PreventPostback)

{

return null ;

}

NameValueCollection collectionBasedOnMethod = this .GetCollectionBasedOnMethod(false );

if (collectionBasedOnMethod == null )

{

return null ;

}

bool flag = false ;

string [] values = collectionBasedOnMethod.GetValues((string ) null );

if (values != null )

{

int length = values.Length;

for (int i = 0; i < length; i++)

{

if (values[i].StartsWith("__VIEWSTATE" , StringComparison .Ordinal) ||

(values[i] == "__EVENTTARGET" ))

{

flag = true ;

break ;

}

}

}

if (((collectionBasedOnMethod["__VIEWSTATE" ] == null ) && (collectionBasedOnMethod["__VIEWSTATEFIELDCOUNT" ] == null )) && ((collectionBasedOnMethod["__EVENTTARGET" ] == null ) && !flag))

{

return null ;

}

if (this .Request.QueryStringText.IndexOf(

HttpResponse .RedirectQueryStringAssignment, StringComparison .Ordinal) != -1)

{

collectionBasedOnMethod = null ;

}

return collectionBasedOnMethod;

}

这个函数中返回 null就意味者 IsPostBack= false,将上面函数中每个返回为 null的地方作如下的分析。

3.1.1 this.Context.Request == null

if (this
.
Context.Request
== null)
{ return null
;
}this.Context.Request == null 应该只有在异常的情况下会发生,正常情况下会在 HttpRuntime.ProcessRequestInternal 中创建 HttpContext及 HttpRequest对象。

3.1.2 this.Context.PreventPostback

if (this
.
Context
.PreventPostback) { return null
;
}在 HttpServerUtility.Transfer 中会使用 PreventPostback ,其代码如下:

public void Transfer(string path)

{

bool preventPostback = this ._context.PreventPostback;

this ._context.PreventPostback = true ;

this .Transfer(path, true );

this ._context.PreventPostback = preventPostback;

}

在调用 Server.Transfer进行画面迁移时设置 Context.PreventPostback = ture。此处得出结论①:对于使用 Server.Transfer进行迁移时迁移到的页面其 IsPostBack= false。



If you have any requirements, please contact webmaster。(如果有什么要求,请联系站长)





QQ:154298438
QQ:417480759