我正在尝试使用SQL Server 2008 R2在ASP.NET 4应用程序中配置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>
答案 0 :(得分:12)
你不能告诉ELMAH对你的连接字符串做些什么。但是,您可以做的是告诉ELMAH在需要ErrorLog
时给您回电,让您在运行时获得更多控制权。然后,您可以读取加密的连接字符串,使用内部函数对其进行解密,并返回使用它初始化的SqlErrorLog。
为此,您需要提供与之兼容的方法
ServiceProviderQueryHandler
代表。System.ComponentModel.Design.ServiceContainer
代表。这是定义:
public delegate IServiceProvider ServiceProviderQueryHandler(object context);
该方法的实现必须返回实现IServiceProvider
的对象的实例。如果您不想自己编写一个,可以从.NET Framework免费获得一个。见addition in 1.2。服务提供者的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 / delegate创建时将服务请求传递给捕获的服务点
直接满足它,从而创造一个链。您可以通过在应用程序初始化期间的某处设置ServiceCenter.Current
来告诉ELMAH您的实现,以便上述代码需要放置。
请记住,这是一个非常简单的实现,但它应该足以让您在需要时启动并优化。
在此{{3}}之前,做类似事情的唯一方法需要进行子类化和其他体操,但仍然会产生部分结果。现在,您只需要实现一个方法并将其交给ELMAH,它只需根据服务类型响应来自ELMAH的查询对象。
答案 1 :(得分:3)
作为Atif Aziz帖子的补充,这里是VB.NET版本(.NET 2.0版本的InitializeElmah_VB9 [没有lamdda],VB.NET for .NET 4.0的InitializeElmah)
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