2011-05-12 11 views
5

Estoy intentando configurar el registro de errores de ELMAH en una aplicación ASP.NET 4 utilizando SQL Server 2008 R2. ¿Hay alguna manera de decirle a ELMAH que llame a nuestra función de desencriptación interna en la cadena de conexión que le proporcionamos? ¿Debo modificar la fuente ELMAH y reconstruir?Configuración de ELMAH con el registro de SQL Server con cadena de conexión cifrada

<configSections> 
    <sectionGroup name="elmah"> 
    <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" /> 
    <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" /> 
    <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" /> 
    <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" /> 
    </sectionGroup> 
</configSections> 

<elmah> 
    <security allowRemoteAccess="1" /> 
    <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="ELMAH" /> 
</elmah> 

<connectionStrings> 
    <add name="ELMAH" connectionString="EncryptedConnectionString" providerName="System.Data.SqlClient" /> 
</connectionStrings> 

<system.webServer> 
    <handlers> 
    <add name="Elmah" verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" preCondition="integratedMode" /> 
    </handlers> 
    <modules> 
    <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" /> 
    </modules> 
</system.webServer> 

Respuesta

12

No puede simplemente decirle a ELMAH que haga algo con su cadena de conexión. Sin embargo, lo que puede hacer es decirle a ELMAH que le devuelva la llamada cuando necesite un ErrorLog, lo que le brinda más control en el tiempo de ejecución. Luego puede leer la cadena de conexión cifrada, descifrarla con su función interna y devolver una SqlErrorLog inicializada con ella.

Para hacer esto, debe proporcionar un método que sea compatible con el delegado ServiceProviderQueryHandler. Aquí está la definición:

public delegate IServiceProvider ServiceProviderQueryHandler(object context); 

La aplicación del método debe devolver una instancia de un objeto que implementa IServiceProvider. Si no tiene ganas de escribir una para comenzar, puede obtener una gratis de .NET Framework. Ver System.ComponentModel.Design.ServiceContainer. El proveedor del servicio GetService debe responder a las solicitudes para el tipo ErrorLog y puede, por ejemplo, devolver un objeto SqlErrorLog que se ha inicializado con una cadena de conexión manipulada en tiempo de ejecución. Aquí hay una posible implementación:

var parent = ServiceCenter.Current; 
ServiceCenter.Current = context => { 
    var container = new ServiceContainer(parent(context)); 
    var connectionSettings = ConfigurationManager.ConnectionStrings["FOOBAR"]; 
    var connectionString = Decrypt(connectionSettings.ConnectionString); 
    var log = new SqlErrorLog(connectionString); 
    container.AddService(typeof(ErrorLog), log); 
    return container; 
    } ; 

Esto captura el punto de servicio actual e instala el suyo en su lugar. El lambda/delegado creado pasa peticiones de servicio al punto de servicio capturado cuando no puede satisfacerlo directamente, creando así una cadena de . Usted le informa a ELMAH sobre su implementación configurando ServiceCenter.Current en algún lugar durante la inicialización de su aplicación, de modo que es allí donde tendrá que sentarse el código anterior.

Tenga en cuenta que esta es una implementación muy simple, pero debería ser lo suficientemente buena como para comenzar y optimizarla más adelante si fuera necesario.

Antes de esto, addition in 1.2, la única manera de hacer algo similar requería la creación de subclases y otras gimnasias y aún así obtenía resultados parciales. Ahora solo necesita implementar un método y entregárselo a ELMAH y que simplemente responde a las consultas de ELMAH para los objetos en función de su tipo de servicio.

+0

¿Qué es 'parent (context)' en este ejemplo de código? – Doug

3

Como una adición al puesto de Atif Aziz, aquí la versión VB.NET (InitializeElmah_VB9 para la versión .NET 2.0 [sin lamdda], InitializeElmah para VB.NET para .NET 4,0)

Imports System.Web.SessionState 

Public Class Global_asax 
    Inherits System.Web.HttpApplication 


    Public Overrides Sub Init() 
     MyBase.Init() 

     InitializeElmah_VB9() 
     'InitializeElmah()' 
    End Sub 

    Public parent As Elmah.ServiceProviderQueryHandler = Nothing 

    Sub InitializeElmah_VB9() 
     ' TODO: Create Table + Functions ' 
     parent = Elmah.ServiceCenter.Current 
     Elmah.ServiceCenter.Current = AddressOf ElmahCallback 
    End Sub 

    Function ElmahCallback(objContext As Object) As System.IServiceProvider 
     Dim container As New System.ComponentModel.Design.ServiceContainer(parent(objContext)) 
     Dim connectionSettings As System.Configuration.ConnectionStringSettings = ConfigurationManager.ConnectionStrings("FOOBAR") 

     Dim strConnectionString As String = connectionSettings.ConnectionString 

     Dim x As New System.Data.SqlClient.SqlConnectionStringBuilder(strConnectionString) 
     x.Password = CryptStrings.DeCrypt(x.Password) 

     strConnectionString = x.ConnectionString 

     Dim log As Elmah.SqlErrorLog = New Elmah.SqlErrorLog(strConnectionString) 
     container.AddService(GetType(Elmah.ErrorLog), log) 
     Return container 
    End Function 

    Sub InitializeElmah() 
     ' TODO: Create Table + Functions ' 
     Dim parent As Elmah.ServiceProviderQueryHandler = Elmah.ServiceCenter.Current 
     Elmah.ServiceCenter.Current = Function(context) 
       Dim container As New System.ComponentModel.Design.ServiceContainer(parent(context)) 
       Dim connectionSettings As System.Configuration.ConnectionStringSettings = ConfigurationManager.ConnectionStrings("Foobar") 
       Dim connectionString As String = connectionSettings.ConnectionString 

       Dim x As New System.Data.SqlClient.SqlConnectionStringBuilder(connectionString) 

       x.Password = CryptStrings.DeCrypt(x.Password) 

       connectionString = x.ConnectionString 

       Dim log As Elmah.SqlErrorLog = New Elmah.SqlErrorLog(connectionString) 
       container.AddService(GetType(Elmah.ErrorLog), log) 

       Return container 
      End Function 

    End Sub 


    Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs) 
     ' Wird beim Starten der Anwendung ausgelöst 
    End Sub 


    Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs) 
     ' Wird beim Starten der Sitzung ausgelöst 
    End Sub 


    Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs) 
     ' Wird zu Beginn jeder Anforderung ausgelöst 
    End Sub 


    Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs) 
     ' Wird beim Versuch der Benutzerauthentifizierung ausgelöst 
    End Sub 


    Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs) 
     ' Wird bei einem Fehler ausgelöst 
    End Sub 


    Sub Session_End(ByVal sender As Object, ByVal e As EventArgs) 
     ' Wird beim Beenden der Sitzung ausgelöst 
    End Sub 


    Sub Application_End(ByVal sender As Object, ByVal e As EventArgs) 
     ' Wird beim Beenden der Anwendung ausgelöst 
    End Sub 


End Class 
Cuestiones relacionadas