【问题标题】:How Postback is detected on serverside of a webform如何在 Web 表单的服务器端检测回发
【发布时间】:2017-05-31 19:23:34
【问题描述】:

我想知道如何在服务器端检测回发? 通常,页面上控件的状态存储在 Viewstate 中,并且它们在每次回发到服务器时来回遍历。 由于 http 是无状态的,服务器将如何区分 postbacked 页面和初始页面加载。

我们可以使用 Page.IsPostback 属性,该属性分别自动设置为 true 或 false 用于回发和初始加载。但我的问题是什么控制了对 Page.Ispostback 属性的真假分配以及服务器如何找出表单回发? 服务器是否使用任何隐藏字段来检测页面的回发?

【问题讨论】:

  • 第一个页面加载是 HTTP GET 请求,之后是 POST 请求。
  • 那么,如果它是一个表单的 POST 请求,那么假设它是一个回发是否安全?
  • 我会这么说,是的(大多数时候)。我会发布一个答案。

标签: c# asp.net


【解决方案1】:

在 ASP.NET 上下文中,第一个页面加载是 HTTP GET 请求,之后它们是 POST 请求。

Similar question here.

从技术上讲,第一页可以作为 POST,但这并不典型。

【讨论】:

  • 所以,服务器记录了它在 GET 之后收到 POST 并将它们标记为回发的页面。这些信息存储在哪里?
  • 是的,显然设置了一个标志。
  • 是标志 Page.Ispostback 还是分配给 Page.Ispostback 属性的服务器内存标志?
  • 不确定是否诚实。如果这是一个关键应用程序,我会花时间彻底研究 MS 文档。我认为它在服务器内存中......
  • @IrishChieftaun:我发现了一些有助于我们理解的东西。 http://www.evagoras.com/2011/02/10/how-postback-works-in-asp-net/http://aspalliance.com/articleViewer.aspx?aId=895&pId=-1 。正如我们预期的那样,客户端向服务器发送一些隐藏字段以检测回发,并基于此将 IsPostback 设置为 true。
【解决方案2】:

这有点复杂。 System.Web.UI.Page 大约有 6500 行,包含许多公共/内部依赖项。

http://referencesource.microsoft.com/#System.Web/UI/Page.cs

来自您之前的评论:

正如我们预期的那样,客户端向服务器发送一些隐藏字段 检测回发并基于此将 IsPostback 设置为 true。

您是正确的,使用了隐藏字段。 IrishChieftain 也正确地指出在确定中使用了 HTTP 动词。

整个过程是无状态的。

Page 通过多个步骤进行确定。

Starting with ProcessRequestMain():

  • 检查页面是否使用PageAdapter
  • 调用PageAdapter'sDeterminePostBackMode()方法,或在页面本身调用DeterminePostBackMode()
  • ...调用GetCollectionBasedOnMethod()
  • 请求是 POST 吗?尝试返回 Request.Form 集合。
  • 我们是否从GetCollectionBasedOnMethod() 获得收藏?如果是,请检查某些隐藏字段。
  • 检查跨页回发,并相应地设置_pageFlags[isCrossPagePostRequest]

这些似乎是调用IsPostBack 所必需的先决条件。

public bool IsPostBack {
    get {
        if (_requestValueCollection == null)
            return false;

        // Treat it as postback if the page is created thru cross page postback.
        if (_isCrossPagePostBack)
            return true;

        // Don't treat it as a postback if the page is posted from cross page
        if (_pageFlags[isCrossPagePostRequest])
            return false;

        // Don't treat it as a postback if a view state MAC check failed and we
        // simply ate the exception.
        if (ViewStateMacValidationErrorWasSuppressed)
            return false;

        // If we're in a Transfer/Execute, never treat as postback (ASURT 121000)
        // Unless we are being transfered back to the original page, in which case
        // it is ok to treat it as a postback (VSWhidbey 117747)
        // Note that Context.Handler could be null (VSWhidbey 159775)
        if (Context.ServerExecuteDepth > 0 &&
            (Context.Handler == null || GetType() != Context.Handler.GetType())) {
            return false;
        }

        // If the page control layout has changed, pretend that we are in
        // a non-postback situation.
        return !_fPageLayoutChanged;
    }
}

【讨论】:

    【解决方案3】:

    System.Web.UI.Page 类使用各种方法来检查当前请求是否为回发(设置 IsPostBack 属性)。其中一些(不是全部)是:

    1. 检查当前请求是否为跨页面回传,即是否是从另一个页面到当前页面的post请求。如果是这样,该请求将被视为回发。
    2. .Net 呈现的每个 HTML 页面中都有一个 __VIEWSTATEGENERATOR 隐藏字段。如果在页面接收到的请求中,该隐藏字段不存在,或者在验证字段内容时出现错误,则该请求不会被视为回发。
    3. 如果对页面的请求是通过 Server.Transfer 进行的,则不会将其视为回发。这种情况有一个例外,如果 Server.Transfer 是从该页面本身启动的,则该请求将被视为回发。
    4. 如果当前页面的布局自上次响应后发生了变化,Page 类将假装该请求是非回发请求。使用从请求中接收到的视图状态信息来识别布局更改。每个响应中有 2 个与视图状态相关的 .NET 隐藏字段,有助于确定布局更改。
      • __VIEWSTATEGENERATOR
      • __VIEWSTATE

    更多信息可以从source code for System.Web.UI.Page.IsPostBack属性中获得

    此源代码的 Visual Studio 解决方案也可用于download

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多