65.9K
CodeProject 正在变化。 阅读更多。
Home

网页源代码传输器:获取客户看到的页面

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (22投票s)

2007 年 9 月 3 日

CPOL

5分钟阅读

viewsIcon

91707

downloadIcon

299

本文介绍了一个控件,它允许以用户所见的方式获取网页。例如,开发人员可以保存异常发生前的页面副本,并在需要时恢复该页面。

引言

没有 bug 的 Web 应用程序——这是一种神话。

当需要重现客户的 bug 时,每个开发人员都会遇到很多问题。通常,客户无法提供足够的关于异常发生前条件的信息(他们输入的字段值;异常发生前打开的页面等)。

如果应用程序能够生成(恢复)打开的网页的源代码,包括输入的数据,就像异常发生前那样,并将其保存(例如,保存到数据库中),那将非常有帮助。在这种情况下,开发人员可以从(例如,从数据库中)获取页面的源代码,将其放入 HTML 文件并在浏览器中打开。开发人员将获得异常发生前页面的副本。

我将此功能实现为一个非可视控件。

背景

当我开始这个项目时,我以为我可以利用 IHttpModule 的实现来截获应用程序将发送给客户端的 HTML 源,这样就足够了。但是,支持 AJAX 的应用程序只向客户端发送页面的部分更改。在这种情况下,我需要合并完整的渲染和部分渲染才能获得页面的实际状态——这很不方便。

不幸的是,此解决方案不允许将更改的字段和其他更改(例如,由 JavaScript 引起)包含在源代码中。此外,我还需要解析 HTML 代码并设置更改后的值。在我看来,这是一个复杂的解决方案。

然后,我决定采取另一种方法来解决这个问题。我可以在客户端收集 HTML 源、更改的字段等,然后将其发送到服务器!

使用控件

将控件添加到网页非常简单。在 VS.NET 中,您应该使用“添加/删除工具箱项”来选择控件的 DLL 文件(PauSoft.Web.dll)。控件将出现在工具箱中,您可以将其添加到页面。

注意:每个页面或母版页只能添加一个控件实例。

设计器

Design-time view of the 'HtmlSourceTransmitter' control

控件的设计器非常简单。

在设计时,开发人员可以访问 Enabled 属性。默认情况下,它是 true,但开发人员可以将其切换到 false 来关闭控件的功能(当所有 bug 都已修复时,这对于减小生产环境中的 HTTP 请求大小可能很有用)。

如果应用程序中有母版页,可以将控件添加到母版页中。

如果开发人员有页面或母版页的层次结构,他可以在运行时将控件添加到层次结构的开头。

代码

以下代码描述了如何使用该控件

ASP.NET 母版页声明

<%@ Register Assembly="PauSoft.Web" Namespace="PauSoft.Web.UI.Controls" 
                        TagPrefix="psControls" %>

<psControls:HtmlSourceTransmitter ID="HtmlSourceTransmitter1" runat="server">
</psControls:HtmlSourceTransmitter>

ASP.NET 母版页代码隐藏类

public partial class Site1 : System.Web.UI.MasterPage
{
  protected void Page_Load(object sender, EventArgs e)
  {
    if (!Page.IsPostBack)
    {
      string htmlSource = HtmlSourceTransmitter1.HtmlSource;
      //store htmlSource to DB, file etc

      //...

    }
  }
}

运行时创建控件

运行时创建控件没有任何问题。

以下代码将在页面上添加一个 HtmlSourceTransmitter,并提供一种方便的方式来访问 HTML 源。

public partial class _Default : MyCustomPage
{
  private HtmlSourceTransmitter _htmlTransmitter = 
                    new HtmlSourceTransmitter();

  protected override void OnInit(EventArgs e)
  {
    base.OnInit(e);
    Controls.Add(_htmlTransmitter);
  }

  /// <summary />

  /// Returns HTML source of the page before submit.

  /// </summary />

  public string HtmlSource
  {
    get
    {
      return _htmlTransmitter.HtmlSource;
    }
  }
}

它是如何工作的?

HTML 源从客户端传输到服务器有一些步骤。

步骤 1

OnPrerender 事件上,控件会检查 Enabled 属性,如果属性值为 true,则注册脚本。

public class HtmlSourceTransmitter : Control
{
  protected override void OnPreRender(EventArgs e)
  {
    base.OnPreRender(e);

    if (Enabled)
      RegisterScripts();
  }
}

第二步

控件注册一个 JavaScript 处理程序,该处理程序将在客户端的 OnSubmit 事件上执行,以及一个将包含传输 HTML 代码的隐藏字段。

public class HtmlSourceTransmitter : Control
{
  private void RegisterScripts()
  {
    //Register script from .js file depends on current compile mode 

    //(debug/release) of web application

    Page.ClientScript.RegisterClientScriptResource(GetType(), 
        Utils.GetJSResourceCompilationMode
        ("PauSoft.Web.Resources.Scripts.HtmlSourceTransmitter.js"));

    //Register action, that will be executed on Form OnSubmit event

    string scriptName = string.Format(CultureInfo.InvariantCulture, 
                        "{0}_OnSubmit", ClientID);
    string scriptText = "FillTransmitterField()";
    if (!Page.ClientScript.IsOnSubmitStatementRegistered
                        (GetType(), scriptName))
      Page.ClientScript.RegisterOnSubmitStatement(GetType(), 
                        scriptName, scriptText);

    //Register hidden field, that will keep HTML source of the page

    Page.ClientScript.RegisterHiddenField(transmitterFieldName, string.Empty);
  }
}

步骤 3

OnSubmit 事件上,将执行 FillTransmitterField() 函数,该函数将生成一个用于更改元素的更新脚本,将此脚本添加到 Body 元素的 OnLoad 中,并将页面的 HTML 源存储到隐藏字段中,最后将数据发送到服务器(请参阅“HtmlSourceTransmitter.debug.js”文件)。

步骤 4

开发人员可以根据需要使用传入的信息。

结果

下面是一些控件用法的示例

Screenshot of first web page

图 1. 第一个示例网页的屏幕截图

Result of HtmlSourceTransmitter work for first web page.

图 2. 使用 HtmlSourceTransmitter 获取的第一个示例页面的视图

Screenshot of second web page

图 3. 第二个示例网页的屏幕截图

Result of HtmlSourceTransmitter work for second web page.

图 4. 使用 HtmlSourceTransmitter 获取的第二个示例页面的视图

您可以比较屏幕截图和视图——它们几乎一样!

谁可以使用它?

在我看来,几乎所有的用户都一样——他们健忘。在这种情况下,在异常发生前拥有页面的“屏幕截图”非常有用。该控件对于应该捕获服务器 bug 但无法详细描述 bug 前情况的用户很有用。

我们几乎所有人都经历过描述的情况,这个控件可以帮助我们解决问题!

已知问题

  1. HtmlSourceTransmitterMicrosoft IE WebControls 库中的 TabStrip 控件配合使用效果不佳。
  2. 此控件仅存储显示页面的 HTML 代码,不存储外部资源——图像、脚本、级联样式等。因此,为了获得最佳结果,开发人员应该在应用程序文件夹中创建一个具有接收到的源代码的 HTML 文件。
  3. 使用 HtmlSourceTransmitter 获取的页面布局可能与原始页面布局不同。

我相信还有一些其他需要修改的事情,或者需要添加的其他功能。所以,请告诉我。

致谢

感谢以下帮助过我的人

  • Vladimir Kuznetsov
  • Yan Oreshchenkov
  • Sergey Zyrianov

历史

  • 版本 1.0 (2007-08-30) - 初始发布
© . All rights reserved.