Ajax UrlTester


Todo webmaster que se precie debe seguir una regla de oro básica: cuando realizas un cambio en la Web, debes visitar las páginas donde se han hecho los cambios para comprobar que todo va correcto.

Esto, aparentemente tan lógico y trivial, no es tan sencillo como parece. Si estamos hablando de una o dos páginas no hay problema, pero hay ocasiones en que los cambios realizados son complejos y pueden implicar 20, 30 o 40 páginas.

Con esta idea en mente, y sin buscar antes en Google por si había ya algo parecido (de hecho aún no lo he mirado y no sé si lo haré), se me ocurrió hacer un script que visitara las páginas y me diera, al menos, una mínima información sobre el estado de las páginas que yo quiera.

Hay muchas opciones posibles. Por ejemplo podríamos usar un spider. Pero como ya escribí un artículo muy similar y me apetecía usar Ajax y Javascript, decidí utilizar el XMLHttpRequest.

Básicamente, la funcionalidad del script consiste en visitar las páginas que yo le configuro usando el XMLHttpRequest, y éste me dará el Status y el StatusCode de cada una de esas páginas.

Como ya sabréis, si la página funciona correctamente, devolverá un StatusCode "200" y un Status "OK". Si no existe la página devolverá un "404 - Page Not Found" y si hay un error devolverá "500 - Internal Server Error". Es poca información, pero nos viene perfecto para dar un repaso rápido a una gran cantidad de páginas.

Además de esta funcionalidad básica, el script "maquilla" los resultados devueltos, indicando, por ejemplo, cuando comienza y termina un test, o coloreando en rojo todo aquello que no sea un "200 - OK".

Lo he metido todo en un .ASCX en lugar de un .dll, porque a mí me suele ser más cómodo, sobretodo en cosas de administración tan pequeñitas.


Ahora vayamos al grano, mostrando un poquito del código básico:

El .ascx.cs tiene dos métodos centrales el "AddJavascriptCore" y el "AddJavascriptTest". Veamos el primero de ellos:


    private void AddJavascriptCore()
    {
        string js = string.Format(
            @"
    
        // Simplemente devuelve una variable "XMLHttpRequest" válida para IE y FF
        // It simply returns an XMLHttpRequest variable, valid for IE and FF
        function CreateXmlHttp()
        {{
            try
            {{
                xmlHttp = new ActiveXObject('Msxml2.XMLHTTP');
            }}
            catch(e)
            {{
                try
                {{
                    xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
                }}
                catch(oc)
                {{  
                    xmlHttp = null;
                }}
            }}
            if(!xmlHttp && typeof XMLHttpRequest != 'undefined')
            {{
                xmlHttp = new XMLHttpRequest();
            }}
            return xmlHttp;
        }}


        // Se llama al empezar el test, y muestra el mensaje de inicio
        // It's called at the beginning of the test and returns a start message
        function BeginTest()
        {{
            var panel = document.getElementById('{0}');
            panel.appendChild(document.createTextNode('BEGIN TEST'));
            panel.appendChild(document.createElement('br'));
        }}


        // Controlamos cuándo se ha llamado a todas las páginas
        // We control when are tested all the pages
        function SubstractCount()
        {{
            i--;
            if (i==0)
            {{
                var panel = document.getElementById('{0}');
                panel.appendChild(document.createTextNode('END TEST'));

            }}
        }}


        // Recoge la variable XMLHttpRequest y maneja la función que se ejecutará cuando la llamada termine.
        // Get the XMLHttpRequestVariable and hands the function that is going to execute when the call ends.
        function SendTest(ajaxRequest)
        {{
            var xmlHttp = CreateXmlHttp();
            xmlHttp.onreadystatechange = function() {{Test(ajaxRequest, xmlHttp)}};
            xmlHttp.open('GET', ajaxRequest, true);
            xmlHttp.send('');
        }}

        
        // Cuando termine la llamada, se crean los elementos DOM y se muestra el resultado
        // When the call ends, the DOM elements are created and the results are shown
        function Test(ajaxRequest, xmlHttp)
        {{
            if(xmlHttp.readyState == 4)
            {{
                var panel = document.getElementById('{0}');

                var item = document.createElement('div');

                var ajaxUrlRequest =document.createElement('a');
                ajaxUrlRequest.href= ajaxRequest;
                ajaxUrlRequest.target= '_blank';
                ajaxUrlRequest.appendChild(document.createTextNode(ajaxRequest));

                item.appendChild(ajaxUrlRequest);
                item.appendChild(document.createTextNode(': ' + xmlHttp.status + ' - ' + xmlHttp.statusText));

                var color = 'blue';

                if (xmlHttp.status != '200') color = 'red';
                    item.setAttribute('style', 'color:' + color);

                panel.appendChild(item);

                SubstractCount();
            }}
        }}
", pnlTesterResults.ClientID);

        // Registra el script. Se usa ASP.NET AJAX, pero en lugar de ésta puedes usar el ClientManager.
        // Registers the script. Here is used ASP.NET AJAX, but you can use the ClientManager instead
        ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "Subgurim_AjaxPageTester_AddJavascriptCore", js, true);
    }

    

En cuanto al método "AddJavascriptTest", es mucho más sencillo, pues sólo se encarga de inicializar variables y llamar al método para cada una de las páginas.

    private System.Collections.Specialized.StringCollection urlList = new System.Collections.Specialized.StringCollection();
    public System.Collections.Specialized.StringCollection UrlList
    {
        get { return urlList; }
        set { urlList = value; }
    }

    private void AddJavascriptTest()
    {
        StringBuilder sb = new StringBuilder();

        if (null != UrlList)
        {
            sb.AppendFormat("var i = {0};", UrlList.Count);
            sb.Append("BeginTest();");
            foreach (string url in UrlList)
            {
                sb.AppendFormat("SendTest('{0}');", url);
            }
        }

        ScriptManager.RegisterStartupScript(this, this.GetType(), "Subgurim_AjaxPageTester_AddJavascriptTest", sb.ToString(), true);
    }




Así pues, tras registrar el control en cualquier página .aspx, lo utilizaremos del siguiente modo:

        // Añade las url que quieras comprobar. Deben estar en el mismo dominio que esta página.
        // Add the URL that you want to test. They should be in the same domain that this page.
        AjaxPageTester1.UrlList.Add("/default.aspx");
        AjaxPageTester1.UrlList.Add("/login.aspx");