in

SharePoint Blogs

The Best Place for SharePoint-related Blogs

Sharepoint desde cero

Mi aprendizaje en Sharepoint
  • Cómo registrar eventos en SharePoint

    Como continuación del último post en el que vimos como crear un evento paso a paso, ahora veremos diferentes maneras que tenemos para registrar nuestro evento en SharePoint.

    Antes de continuar con este post, recomendamos revisar el anterior:

    Cómo crear un evento en SharePoint

    Tal y como comentamos, las diferentes formas que tenemos para registrar el evento, todas ellas igual de válidas, son:

    1. Creando una característica de SharePoint, que nos permitirá activarla y desactivarla desde el propio SharePoint.

    2. Con una aplicación de consola con el modelo de objetos de Sharepoint.

    3. De forma automática con una aplicación gratuita de administración de SharePoint llamada SharePoint Inspector.

    1.- CREANDO UNA CARACTERÍSTICA DE SHAREPOINT

    Probablemente esta manera de registrar el evento es la que más trabajo tiene inicialmente para crear la característica. Pero una vez creado la característica, nos permitirá activar y desactivarla desde la "Configuración del sitio" del Sharepoint.

    Siguiendo con el desarrollo que iniciamos en nuestro anterior post, añadiremos y preparemos otro proyecto de tipo "Biblioteca de clases" para la instalación de la característica:image16image17

    Eliminamos la clase "Class1.cs" que se crea automáticamente y agregamos un archivo XML que llamaremos "Feature.xml":image19 image20

    Insertar el siguiente código en el .xml:

    <Feature xmlns="http://schemas.microsoft.com/sharepoint/"
      Id="[guid]"
      Scope="Web"
      Title="Announcement Event Handler"
    >
        <ElementManifests>
            <ElementManifest Location="Elements.xml" />
        </ElementManifests>
    </Feature>

     

    En el código sustituiremos [guid] por uno nuevo. Para obtener un Guid podemos ejecutar desde la línea de comandos: C:\Archivos de programa\Microsoft Visual Studio 8\Common7\Tools\guidgen.exe o desde la opción "Crear Guid" en el menú Herramientas de Visual Studio:

    image21

    <Feature xmlns="http://schemas.microsoft.com/sharepoint/"
      Id="{1FA22BF6-79FC-45fb-8F33-E1CC3B37A7F2}"
      Scope="Web"
      Title="Cancelar añadir nuevos elementos"
    >
        <ElementManifests>
            <ElementManifest Location="Elements.xml" />
        </ElementManifests>
    </Feature>

     

    También necesitaremos obtener el Public Key Token del ensamblado con el comando C:\archivos de programa\Microsoft Visual Studio 8\SDK\v2.0\Bin\sn.exe:

    sn –Tp [pathToAssembly]\[assemblyFileName]

    o siguiendo los pasos que comenta Andrew Conell: http://www.andrewconnell.com/blog/archive/2006/09/15/4587.aspx

    Ahora creamos otro xml que llamaremos "elements.xml":

    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
        <Receivers ListTemplateId="100">
            <Receiver>
                <Name>listapersonalizada</Name>
                <Type>ItemAdding</Type>
                <SequenceNumber>10000</SequenceNumber>
                <Assembly>
                    EventoNuevaPromo,
                    Version=1.0.0.0,
                    Culture=neutral,
                    PublicKeyToken=eb28d2942d41f46a
                </Assembly>
                <Class>EventoNuevaPromo.AddingAction</Class>
                <Data></Data>
                <Filter></Filter>
            </Receiver>
        </Receivers>
    </Elements>

    En este xml tenemos varios parámetros que comentar. ListTempateId hace referencia al id de la plantilla que afectará esta característica, y en este caso, a que tipo de lista se agregará el evento. Type tiene que ser el evento que estamos agregando. Sequencenumber es el orden en que se ejecutará este evento si tenemos varios eventos asociados a una lista.

    Después de esto copiamos las 2 xmls creados a

    C:\Archivos de programa\Archivos comunes\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\[nombre caracteristica], en nuestra caso a C:\Archivos de programa\Archivos comunes\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\listapersonalizada.

    Se puede hacer con un comando xcopy en los post-built commands para automatizar.

    Luego con 2 comandos stsadm instalaremos la características y la activaremos:

    Stsadm.exe –o installfeature –name listapersonalizada
    Stsadm.exe –o activatefeature –name listapersonalizada –url http://localhost

    En lugar del 2º comando, podríamos activar la característica desde el navegador en la "Configuración del sitio". Finalmente sólo nos faltaría reciclar la Application Pool desde el administrador de IIS.

    Para desinstalar la característica:

    stsadm –o deactivatefeature –name [nombrecaracteristica] –url http://localhost

    stsadmn –o uninstallfeature –name [nombrecaracteristica]

    y a continuación reciclar el Application Pool.

     

    2.- CON EL MODELO DE OBJETOS DE SHAREPOINT

    En este caso también agregaremos un proyecto a nuestra solución del evento, pero esta vez una aplicación de consola:

    image23

    Agregamos la referencia de Microsoft.SharePoint como en el proyecto del Evento y agregamos el using Microsoft.SharePoint.

    Introducimos en la clase el siguiente código:

    try
                {
                    string listName = "Documentación";
                    string siteURL = "http://localhost";
                    string receiverName = "Evento Archivo Nuevo";
                    int sequenceNumber = 2001;
                    string assemblyFullName = "EventoArchivoNuevo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3c2296eb2e1f5b8e";
                    string assemblyClassName = "EventoArchivoNuevo.AddedAction";
                    string receiverData = "";
     
                    SPList list = new SPSite(siteURL).OpenWeb().Lists[listName];
                    SPEventReceiverDefinitionCollection eventReceivers = list.EventReceivers;
                    //eventReceivers[0].Delete();
                    SPEventReceiverDefinition eventReceiver = eventReceivers.Add();
                    eventReceiver.Name = receiverName;
                    eventReceiver.Type = SPEventReceiverType.ItemAdded;
                    eventReceiver.SequenceNumber = sequenceNumber;
                    eventReceiver.Assembly = assemblyFullName;
                    eventReceiver.Class = assemblyClassName;
                    eventReceiver.Data = receiverData;
                    eventReceiver.Update();
                    Console.WriteLine("Todo OK");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error: " + ex.Message);
                }
                Console.ReadLine();

    La información que introducimos en nuestro código es prácticamente equivalente a la que introducimos en el  elements.xml de la característica.

    Establecemos el proyecto creado como proyecto de inicio:

    image25

    Y ejecutamos.

    Si todo ha ido bien:

    image26

    Sólo nos faltaría reciclar el Application Pool (o un poco más a lo bruto, hacer un iisreset).

    Para desasociar el evento de la lista, podemos descomentar en el codigo la línea de eventReceivers[0].Delete(); y comentar el resto

    Otro código equivalente visto en el blog de Carlos Segura sería:

    using System;
    using Microsoft.SharePoint;
     
    namespace ConsoleTools
    {
        class Program
        {
            static void Main(string[] args)
            {
                SPSite site = new SPSite("http://spsbeta/SiteDirectory/test");
                SPWeb web = site.OpenWeb();
                SPList list = web.Lists["Demo"];
     
                string ensamblado = "MiWebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d196fc71b3d34a48";
                string clase = "MiWebPart.MiEventHandler";
     
                list.EventReceivers.Add(SPEventReceiverType.ItemAdded, ensamblado, clase);
                list.EventReceivers.Add(SPEventReceiverType.ItemUpdated, ensamblado, clase);
                list.EventReceivers.Add(SPEventReceiverType.ItemDeleting, ensamblado, clase);
     
            }
        }
    }

    Como mejora podríamos editar los códigos para que nos pida la URL de la web y el nombre de la biblioteca/lista en la que queremos registrar el evento.

    De esta forma, no tenemos que activar característica ni nada, pero no tenemos la versatilidad de desasociar el evento a través de la interfaz web ya que no tenemos la característica.

    3.- Usando una aplicación externa: Sharepoint Inspector

    Este programa es de mucha utilidad y lo podemos obtener desde Codeplex. Nos permite agregar/eliminar un evento a cualquier lista o biblioteca de SharePoint, y como veréis de la forma más fácil.

    Una vez creado nuestro evento, los pasos para registrar el evento con este programa sería los siguientes.

    Desplegar el menú de árbol hasta llegar a "Event Receivers" dentro de nuestra lista:

    image28

    y con el botón derecho, hacemos click sobre "Add event":

    image29

    image

    Seleccionamos la DLL en “Load DLL” y nos carga los eventos creados en esta dll.

    image

    Nos Rellena el assembly de forma automática. Sólo tenemos que seleccionar en clase y en la lista Event Type el evento que queremos asociar. Observad el detalle del checkbox que nos verifica que la dll está registrada en el GAC:

    image

    Y simplemente presionando "Add" ya tendremos registrado nuestro evento.

    Casi de la mismo forma, si queremos eliminar el evento de la lista, sólo tendríamos que desplegar el evento y con el botón derecho "Remove":image

    Otro herramienta parecida a Sharepoint Inspector pero sólo orientada al manejo de eventos es EventHandlerExplorer desarrollada por U2U.

    RESULTADO

    Con cualquiera de las 3 formas, conseguimos lo mismo.

    En nuestro ejemplo en el evento bloqueamos el adding (properties.Cancel = true;) de una lista y mostramos el siguiente mensaje de error (properties.ErrorMessage = "No se puede añadir nuevos elementos";).

    Este es el resultado al intentar insertar un elemento en nuestra lista:

    image22

  • Cómo crear eventos de SharePoint

    Los eventos de SharePoint nos permite controlar cuando se ejecutan en nuestro portal una serie de acciones a nivel de listas, bibliotecas o webs. Gracias a esto podemos asociar código propio a este serie de eventos para realizar otras acciones o actualizaciones, realizar validaciones o incluso cancelar la inserción de un documento o elemento a una lista.

    Tenemos dos tipos de eventos en función de cuando se ejecutan. Podemos asociar un evento cuando ya se ha realizado una acción, es decir, tras producirse una inserción, actualización o eliminación. El otro tipo se ejecuta a la vez que la acción y éste nos permite cancelar el proceso, por ejemplo si tras una validación queremos cancelar la inserción de un documento por no cumplir una condición.

    Los eventos a los que podemos asociar código son los siguientes:

    SPItemEventReceiver
    ItemAdded ItemAdding ItemAttachmentAdded ItemAttachmentAdding
    ItemAttachmentDeleted ItemAttachmentDeleting ItemCheckedIn ItemCheckedOut ItemCheckingIn ItemCheckingOut ItemDeleted ItemDeleting ItemFileConverted ItemFileMoving ItemUncheckedOut ItemUncheckingOut ItemUpdated ItemUpdating
    SPListEventReceiver
    FieldAdded FieldAdding FieldDeleted FieldDeleting FieldUpdated FieldUpdating
    SPWebEventReceiver
    SiteDeleted SiteDeleting WebDeleted WebDeleting WebMoved WebMoving

    En este post vamos a seguir paso a paso como crear un evento sencillo con Visual Studio 2005. En el ejemplo vamos cancelar la inserción de un elemento a una lista en cualquier caso. Aunque no es muy realista el ejemplo, nos sirve para ver la funcionalidad y las posibilidades de los eventos. Tras crear un evento y registrarlo en el GAC, debemos asociarlo a una lista o biblioteca o sitio. Este último paso lo dejaremos para un segundo post.

    COMO CREAR UN EVENTO EN SHAREPOINT CON VISUAL STUDIO

    Creamos proyecto Tipo Biblioteca de Clase:

    image1

    Agregamos una referencia a la .dll de SharePoint para poder trabajar con su modelo de objetos:

    image2

    La encontraremos en "En examinar", en la ruta C:\Archivos de programa\Archivos comunes\Microsoft Shared\web server extensions\12\ISAPI :

    image3

    Agregamos "using Microsoft.SharePoint ":

    image4

    Cambiamos el nombre de la clase por AddingAction, hacemos que herede de Microsoft.Sharepoint.SPITemEventReceiver y sobrescribimos el método ItemAdding:

    image

    Metemos el código para el evento. En este caso paramos la inserción y mostramos mensaje de error:

    image

    Con esto ya tenemos todo el código escrito. Ahora deberemos firmar el ensamblado para poder registrarlo en el GAC del servidor:

    image

    image

    Marcamos el checkbox "Firmar el ensamblado" y "Nuevo" en “Seleccione un archivo de clave de nombre seguros”

    image image

    El explorador de soluciones nos quedará algo parecido a:

    image

    Hecho esto, lo registraremos en el GAC mediante un comando. Si este comando lo introducimos en el "Post-Build Event" de Visual Studio, automatizaremos el actualizar nuestros cambios en el servidor cada vez que compilemos nuestro código en el Visual Studio.

    Para ello, volvemos a la ventana propiedades del proyecto, en el apartado "Eventos de Generación":

    image

    Y aquí en "Línea de comandos del evento posterior a la generación", introduciremos el siguiente comando (cada comando en una misma línea):

    "c:\Archivos de programa\Microsoft Visual Studio 8\SDK\v2.0\bin\gacutil.exe" /nologo /i "$(TargetPath)" /f

    c:\WINDOWS\system32\iisapp.vbs /a "Sharepoint - 80" /r

    donde “Sharepoint – 80” es el nombre del “grupo de aplicaciones” que ejecuta el MOSS. Podemos verlo en la Administración del IIS. Este segundo comando recicla el "Grupo de Aplicaciones".image

    En este momento, si generamos nuestro proyecto, lo estaremos agregando al GAC y reciclando el Grupo de Aplicaciones para que SharePoint tenga en cuenta esta nueva .dll.

    Tras esto, tendremos que asociar nuestro evento a la lista. Lo podremos hacer de hasta 3 maneras diferentes.

    1. Creando una característica de SharePoint, que nos permitirá activarla y desactivarla desde el propio SharePoint.
    2. Con una aplicación de consola con el modelo de objetos de Sharepoint.
    3. De forma automática con una aplicación gratuita de administración de SharePoint llamada SharePoint Inspector.

    Esto lo veremos en el próximo post.

  • Error: Item has already been added. Key in dictionary: '484' Key being added: '484'

    Inicio con este post una nueva sección dedicada los errores y problemas de SharePoint que me vaya encontrando por los clientes. El objetivo es recopilar los errores con sus soluciones para aprovechar en futuras situaciones en las que se repitan estos errores.

    El error que me he encontrado recientemente en un cliente se producía la intentar hacer cualquier cambio en la Administración Central. Podía navegar por las diferentes páginas de la Administración Central, pero en el momento que intentaba realizar algún cambio de configuración aparecía el siguiente error:

    Item has already been added. Key in dictionary: '484'  Key being added: '484'

    En el visor de sucesos se mostraba el siguiente registro:

    Event Type: Error
    Event Source: Windows SharePoint Services 3
    Event Category: Cronómetro
    Event ID: 6398
    Date:  01/07/2008
    Time:  11:54:16
    User:  N/A
    Computer: SERVER
    Description:
    El método Execute de la definición de trabajo Microsoft.SharePoint.Administration.SPConfigurationRefreshJobDefinition (ID 6c90c1b6-deb7-43d6-8cad-b4c1bb395077) lanzó una excepción. A continuación se incluye más información.

    Item has already been added. Key in dictionary: '484'  Key being added: '484'

    For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

    Tras googlear un poco encontré un ejecutable que supuestamente arregla el error pero no fue mi caso. Creo que fue por un problema de permisos con el que ejecuté el ejecutable.

    En cualquier caso, según parece el programa sigue los siguientes pasos y que realizándolos manualmente sí que me soluciono el problema:

    SOLUCIÓN

    • REALIZA UN BACKUP DE TODAS LAS BASES DE DATOS DE SHAREPOINT ANTES DE SEGUIR ESTOS PASOS

    • Abre tu base de datos de configuración de SharePoint con el SQL Management Studio

    • Esa base de datos contiene una tabla llamada dbo.Objects. Sobre la misma, botón derecho y "Abrir tabla" y a continuación haz un click sobre el icono "Mostrar panel SQL".

    • Ejecuta la siguiente consulta:

    SELECT Id, ClassId, ParentId, Name, Status, Version, Properties
    FROM Objects
    WHERE (Properties LIKE '%DiagnosticsService%')

    • Mostrará dos resultados. Mirando el campo propiedades verás algo parecido a:
      <object type="Microsoft.SharePoint.Administration.SPDiagnosticsService ... <object type="Microsoft.Office.Server.Administration.DiagnosticsService ...

    • En estos campos verás, entre otras cosas, el nº de la clave que te da error. En mi caso era con la clave 484.

    • Borra esos 2 registros. Ya sé que da un poco de miedo borrar 2 registros de la BD, pero así lo solucioné y por eso realizamos en el 1er paso el backup de la BD.

    • Ahora si vas a la Administración Central ya no te mostrará el error.

  • 2 próximos webcast interesantes

    Héctor Insua dará en los próximos días 2 webcast tal y como ha comentado hace unos días en un post. Estoy seguro que serán muy interesantes. Os dejo los enlaces para que podáis asistir a los mismos:

    1 – SharePoint en Windows 2008 – Ventajas y Beneficios

    (miércoles, 06 de agosto de 2008 20 h. hora española)

    Conozca como la nueva plataforma 2008 puede ayudarnos a mejorar la Gestión de SharePoint 2007, aprenda a instalarlo, configurarlo y administrarlo. Se verán las novedades de IIS 7, roles y features de Windows 2008.

    2 – Estrategias y Opciones de Disaster Recovery en SharePoint 2007

    (miércoles, 13 de agosto de 2008 21 h. hora española)

    El Servidor no responde? Las bases han desaparecido? Fallo un disco duro? Se perdieron archivos? Alguien borro un sitio accidentalmente?.  Aprenda a responder todas estas preguntas  y a hacer su plataforma mas segura, se verán las opciones de recuperación para SharePoint desde todo punto de vista. Con trucos y recomendaciones para que los tiempos de caída de sus servidores sean un tema del pasado.

  • Más vale tarde que nunca, Ajax a la palestra

    Aunque la tecnología Ajax ya lleva mucho tiempo activa en el mundo web, yo personalmente no me había pegado mucho con ella para sacarle algo de jugo. Hasta ahora me la habían presentado y poco más, mi relación con ella no había sido mucho más allá que alguna prueba práctica. Tampoco quiere decir que ahora ya esté en la pomada de Ajax, pero he hecho mis primeros pinitos de los que estoy orgulloso. Y es lo que tienes Ajax (y todas las librerías/frameworks creadas alrededor de la misma, véase Asp.net Ajax, Prototype, Scriptacolous), que con mi poco esfuerzo consigues cosas muy aparentes.

    No voy a parar a explicar lo que es AJAX (Asynchronous JavaScript And XML). Como ya he dicho, llego un poco tarde al tema y en el mundo web ya está más que explicado. En cualquier caso, para la teoría siempre podéis echar mano de la Wikipedia.

    Intentaré enseñar algún ejemplo muy sencillo en próximos posts usando el framework ASP.NET AJAX y su maravilloso Control Toolkit, que nos proporciona muchísimos controles preparados para arrastrar y funcionar. También voy a obviar el "Get Started" en Asp.net Ajax y su Control Toolkit más que nada porque en su web ya tenemos 2  vídeos muy aclaratorio en el que se muestra como instalar y agregar los controles a nuestro Visual Studio, además de mostrar 2 sencillos ejemplos:
    Get Started with the ASP.NET AJAX
    Get Started with the ASP.NET AJAX Control Toolkit

    Ah, por cierto, si aún usáis Visual Studio 2005, las descargas del ASP.NET AJAX 1.0 las han puesto un poco más escondidas, así que os dejo el enlace que me ha costado un poco encontrarlo. Los chicos de Microsoft ya empiezan a priorizar a los usuarios de VS 2008.

    En este post introductorio no voy a mostrar ningún ejemplo concreto, simplemente voy a comentar 2 problemillas que me he encontrado al empezar con Ajax por si corréis la misma suerte que yo. Como muchas veces en este mundo, ni vamos a crear algo que no se ha hecho antes ni vamos a ser los primeros que nos enfrentemos a un problema.

    Si veis los vídeos "Get Started" os daréis cuenta que es muy fácil y sencillo crear una web nueva desde cero que soporte ASP.NET Ajax y el Control Toolkit y que nos permita agregar los controles Ajax. Muy sencillo gracias a las plantillas que se nos agregan al VS2005; nos crea un proyecto web con un web.config con todos los objetos registrados y demás parámetros necesitados.

    El 1er problema viene cuando ya tenemos un proyecto web desarrollado que se creo sin usar las plantillas de Ajax y queremos agregarle algún detalle con Asp.net Ajax. Si somos demasiado optimista y a nuestro "antiguo" proyecto agregamos y configuramos cualquier control Asp.net Ajax directamente, veremos que no funciona y que además obtenemos un error de BLOCKED SCRIPT

    "'Sys' no está definido"

    El error se produce porque nos faltan varias instrucciones en el web.config que cuando creamos un proyecto nuevo usando la plantilla correspondiente (Ajax Enabled Web site) el Visual Studio ya nos añade automáticamente.

    Estas instrucciones son las siguientes:

    <?xml version="1.0"?>
    <configuration>
      <configSections>
        <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
          <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
            <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
            <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
              <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere"/>
              <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
              <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
            </sectionGroup>
          </sectionGroup>
        </sectionGroup>
      </configSections>
      <system.web>
        <pages>
          <controls>
            <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
          </controls>
        </pages>
        <compilation debug="true">
          <assemblies>
            <add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
          </assemblies>
        </compilation>
        <httpHandlers>
          <remove verb="*" path="*.asmx"/>
          <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
          <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
          <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
        </httpHandlers>
        <httpModules>
          <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        </httpModules>
      </system.web>
      <system.web.extensions>
        <scripting>
          <webServices>
          </webServices>
        </scripting>
      </system.web.extensions>
      <system.webServer>
        <validation validateIntegratedModeConfiguration="false"/>
        <modules>
          <add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        </modules>
        <handlers>
          <remove name