开发者工具:页面状态恢复与错误重现

作为开发者,经常面临一个难题:当客户报告一个bug时,他们往往无法提供足够的信息来描述异常发生前的情况(例如他们输入的字段值、异常发生前打开的页面等)。如果应用程序能够在异常发生前生成(恢复)打开的网页源代码,并将其存储起来(例如存储在数据库中),那么开发者就可以从数据库中获取页面源代码,将其放入HTML文件并在浏览器中打开。这样,开发者就可以得到异常发生前页面的副本。

为了实现这一功能,开发了一个非可视控件。在项目开始时,考虑使用IHttpModule实现来拦截HTML源代码,但AJAX应用程序只会将页面变化的部分发送给客户端。在这种情况下,需要合并完整渲染和部分渲染以获取页面的实际状态,这很不方便。此外,这种方法不允许将更改的字段和其他更改(例如由JavaScript引起的更改)包含在源代码中。还需要解析HTML代码并设置更改的值。在看来,这是一个复杂的解决方案。

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

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

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

设计器非常简单。在设计时,开发者可以访问Enabled属性。默认情况下它是true,但开发者可以将其切换为false以关闭控件的功能(这在生产环境中非常有用,当所有bug都已修复时,可以减少HTTP请求的大小)。

如果开发者的应用程序中有母版页,他可以将控件添加到母版页。如果开发者有页面或母版页的层次结构,他可以在运行时将控件添加到层次结构的开始。

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

<%@ 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(); } }

步骤2:控件注册将在客户端OnSubmit事件上执行的JavaScript处理程序,并注册将包含传输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:开发者可以根据自己的喜好使用传入的信息。

以下将找到控件使用的示例:

图1. 第一个示例网页的截图 图2. 使用HtmlSourceTransmitter获取的第一个示例页面的视图 图3. 第二个示例网页的截图 图4. 使用HtmlSourceTransmitter获取的第二个示例页面的视图 可以比较截图和视图 - 它们几乎相同!

谁可以使用它? 在看来,几乎所有用户都是一样的 - 他们都是健忘的。在这种情况下,拥有异常发生前页面的“截图”非常有用。这个控件对于需要捕获服务器bug的开发者非常有用,当用户无法详细描述bug发生前的情况时。 几乎都经历过描述的情况,这个控件可以帮助解决问题!

已知问题: HtmlSourceTransmitter与Microsoft IE WebControls库中的TabStrip控件配合使用效果不佳。 这个控件只存储显示页面的HTML代码,不存储外部资源 - 图像、脚本、级联样式等。因此,开发者应该在应用程序文件夹中创建一个HTML文件,以获得最佳结果。 使用HtmlSourceTransmitter获取的页面布局可能与原始布局不同。 相信还有其他需要修改的地方,或者需要添加的其他功能。所以,请告诉。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485