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

将客户端 JavaScript 错误记录到服务器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.29/5 (9投票s)

2005年12月12日

4分钟阅读

viewsIcon

151110

downloadIcon

447

如何使用 AJAX、XML 和 C# 将客户端 JavaScript 错误记录到服务器。

引言

意识到如果你的 JavaScript 失败了,你唯一知道的方式就是某种用户让你知道,这有点可怕。我们都见过“对象 x 未定义”之类的错误等等,你向网站管理员报告过多少次错误?这些问题很容易长时间被忽视。

我最近一直在学习“AJAX”技术,并且在我意识到通过结合使用 AJAX 和 C#,我们可以摆脱对用户的依赖,并且自己自动记录错误时,有了一个神奇的灵感。

基本的攻击计划如下

Overview.

背景

整个概念的关键在于首先捕获错误,然后使用 XMLHttpRequest 将错误数据发送回服务器,该服务器通过一个 .NET HTTP 处理程序,最终调用某种方法,对错误信息进行一些有用的处理。

查看 MSDN 了解更多关于捕获客户端错误的信息。

如果你以前没有使用过 AJAX,我建议以下有用的资源

如果你是 .NET 中 HttpHandlers 的新手,请不要再看其他地方了

使用代码

示例 ASP.NET (C#) 项目非常简单易用(要使示例代码正常工作,只需共享 JavaScriptErrorLogger 文件夹,以便你可以向 Web 服务器发出 HTTP 请求)。让我们来看看要点。

好消息是,将错误捕获代码应用于现有的 JavaScript 非常容易。要处理错误,你所需要做的就是处理 Window.Onerror 事件

window.onerror = errorHandler;

errorHandler 当然会指向一个函数,该函数对事件进行一些有用的操作

function errorHandler(message, url, line)
{
    // message == text-based error description

    // url     == url which exhibited the script error

    // line    == the line number being executed when the error occurred


    // handle the error here

    alert( message + '\n' + url + '\n' + line );
    
    return true;
}

显然,你的错误处理需要非常可靠。提示错误数据并不是特别具有突破性,因此这是示例代码中用于实际执行 XmlHttpRequest 的 JavaScript

function errorHandler(message, url, line)
{
    // message == text-based error description

    // url     == url which exhibited the script error

    // line    == the line number being executed when the error occurred


    // handle the error here

    //alert( message + '\n' + url + '\n' + line );

    
    
    //-------------------------------------------------------------------

    // Log the Error

    //-------------------------------------------------------------------

    
    var xmlHttpRequest;
    // a variable to hold our instance of an XMLHTTP object.


    var bHookTheEventHandler = true;
    // used to switch on/off the handling

    // of any response from the server.


    // Checking if IE-specific document.all collection exists 

    // to see if we are running in IE 

    if (document.all)
    { 
        xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP"); 
    } else { 
        xmlHttpRequest = new XMLHttpRequest(); 
    }
    

    //----------------------------------------------------------------        

    // Roll the error information into an xml string:

    //----------------------------------------------------------------

    var xmlDoc = new ActiveXObject("Msxml2.DOMDocument.3.0");
    xmlDoc.async = false;
    xmlDoc.loadXML("<JavaScriptError line='" + line + "' url='" 
                   + url + "'>" + message + 
                   "</JavaScriptError>");


    //------------------------------------------------------------

    // If you want to see some sort of response to prove (on the 

    // client end) that something has happened,

    // set bHookTheEventHandler = true 

    // otherwise false is probably all we want.

    //------------------------------------------------------------

    if(bHookTheEventHandler)
    {
        xmlHttpRequest.onreadystatechange = 
                sendSomeXml_HandlerOnReadyStateChange;
    }

    //prepare the call, http method=GET, false=asynchronous call

    xmlHttpRequest.open("post", "https:///JavaScript" + 
            "ErrorLogger/logerror.ashx", bHookTheEventHandler);

    //finally send the call

    xmlHttpRequest.send( xmlDoc );  
    
    //------------------------------------------------------------

    // Finished Logging the Error

    //------------------------------------------------------------

                    
    return true;
}

请注意,如果你只想记录错误,则不需要处理 xmlHttpRequest.onreadystatechange 事件,但如果想让用户知道发生了错误并已被记录,你可以在这种情况下使用它。

在我们能够捕获任何传入请求之前,我们需要调整 web.config 文件(有关更多信息,请参阅上面的背景链接)。这种方法的优点是,在创建 XmlHttpRequest 时指定的 URL 不必实际存在。在此示例中,HTTP 处理程序将捕获对 .ashx URL 的请求。

<httpHandlers>
  <!-- Simple Handler -->
  <add verb="*" path="*.ashx" 
        type="JavaScriptErrorLogger.LogErrorHandler, JavaScriptErrorLogger" />
</httpHandlers>

在服务器端,我们将使用 HTTP 处理程序捕获传入的 XML

using System;
using System.Web;
using System.Xml;

namespace JavaScriptErrorLogger 
{

    public class LogErrorHandler : IHttpHandler 
    {

        public void ProcessRequest( HttpContext httpContext ) 
        {
            XmlDocument xmlDoc = null;
        
            // If XML document was submitted via POST method

            // then load it in the DOM document:

            if (httpContext.Request.InputStream.Length > 0 && 
                httpContext.Request.ContentType.ToLower().IndexOf("/xml") > 0) 
            {
                xmlDoc = new XmlDocument();
                xmlDoc.Load( httpContext.Request.InputStream );
        
                // at this point the XML message is available via xmlDoc.InnerXml: 

                Console.WriteLine( xmlDoc.InnerXml );
            }
        }
    }
}

我在网上找到的大多数示例都使用 GET 发出客户端 XmlRequest。如果要将数据发送到服务器,你需要使用 POST(如前面提供的错误处理代码中所示)。使用 POST 后,我们可以通过使用 httpContext.Request.InputStream(如上所示)获取发送到服务器的数据。在此示例中,我们只是将 XML 输出到控制台,而在示例代码中,我们使用一种方法将 XML 记录到文件中。

在我们的 HTTP 处理程序中捕获 XML 后,我们可以再次将其(或其他 XML)发回

public void ReturnXML( HttpContext httpContext, string rawXml )
{
    if(rawXml == "")
        throw new ApplicationException("The value of rawXml was not defined.");

    // Produce XML response:

    httpContext.Response.ContentType = "application/xml";
    XmlTextWriter xw = new XmlTextWriter( httpContext.Response.OutputStream, 
                                           new System.Text.UTF8Encoding() );
    xw.WriteRaw( rawXml );
    xw.Close();
}

关注点

你将在示例代码中看到,我使用一个简单的对象来传递有关错误的信息(在 C# 级别)。此对象只有一个属性(一个字符串),其中包含描述错误的 XML。但是,如果你很聪明,你会意识到这可以扩展为包含我们想要随错误发送的任何其他信息,例如客户端的浏览器等等。你可以更进一步,将 XML 直接反序列化为 C# 对象。

因为——在一个理想的世界里——你永远不会遇到任何错误,所以构建一个测试工具会很明智,这样你就可以定期调用一个错误并检查它是否按照你的预期处理错误。如果你的系统已经有一段时间没有向你发送任何错误日志,最好是因为没有任何错误——而不是因为错误处理已损坏。

© . All rights reserved.