2011-05-12 45 views
5

我試圖配置ELMAH錯誤日誌中使用SQL Server 2008 R2的ASP.NET 4應用SQL Server日誌記錄。有什麼方法可以告訴ELMAH在我們提供的連接字符串上調用我們的內部解密函數?我需要修改ELMAH源並重建嗎?配置ELMAH與加密的連接字符串

<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> 

回答

12

您不能只告訴ELMAH對連接字符串做些什麼。但是,您可以做的事情是告訴ELMAH在需要ErrorLog時給您回電,讓您在運行時獲得更多控制權。然後,您可以讀取加密的連接字符串,使用內部函數對其解密,並返回一個用它初始化的SqlErrorLog。

爲此,您需要提供一種與 代表ServiceProviderQueryHandler兼容的方法。這裏的定義是:

public delegate IServiceProvider ServiceProviderQueryHandler(object context); 

方法的實現必須返回一個實現IServiceProvider對象的實例。如果您不想自己寫一本書,可以從.NET Framework免費獲得一本。見System.ComponentModel.Design.ServiceContainer。服務提供商的GetService必須爲ErrorLog類型的請求作出迴應,你就可以,例如,返回已初始化在運行時操縱的連接字符串SqlErrorLog對象。這裏有一個可能的實現:

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; 
    } ; 

這會捕獲當前服務點並安裝您自己的服務點。創建的lambda /委託傳遞服務請求時,它不能直接滿足它,因此創建一個鏈。在初始化應用程序的過程中,您可以通過在某處設置ServiceCenter.Current來告訴ELMAH您的實現方式,以便上述代碼需要放置在該位置。

請記住,這是一個非常簡單的實現,但它應該是足夠好,讓你開始,如果需要以後進行優化。

在此之前addition in 1.2,做類似的要求子類和其他體操,仍然取得了部分結果的時候,唯一的方式。現在你只需要實現一個方法並把它交給ELMAH,它只是根據ELMAH的服務類型來響應對象的查詢。

+0

什麼是這個代碼示例中的「父(上下文)」嗎? – Doug 2013-04-17 00:28:16

3

作爲除了與Atif阿齊茲後,這裏的VB.NET版本(InitializeElmah_VB9爲.NET 2.0版本[未經lamdda],InitializeElmah對於VB.NET的.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