| 
 | 
 
       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。                                          
 
 
 
 |