In my last post I talked about ELMAH and how you can override connection string. But Atif Aziz (ELMAH author) pointed out that there is a better way to do that:
@trailmax There’s a another & better way to get #ELMAH to use a custom connection string. See http://t.co/1u1hZLWwt7 thread for ideas.
— Atif Aziz (@raboof)
Fair enough, I thought. I did see that solution when originally needed to fix this problem. But I did not manage to quickly reproduce the code, so I went with a hacky way. This time I’ve spent a couple hours for that and did get what I wanted without dirty hacks.
Here is my implementation:
using System.ComponentModel.Design;
using Elmah;
using MyApplication.Domain.Services.Configuration;
namespace MyApplication.Web.App_Start
{
public class ElmahConfig
{
public static void Configure()
{
ServiceCenter.Current = EnclosedServiceProviderQueryHandler.Create(ServiceCenter.Current);
}
}
public class EnclosedServiceProviderQueryHandler
{
private readonly ServiceProviderQueryHandler parent;
public EnclosedServiceProviderQueryHandler(ServiceProviderQueryHandler parent)
{
this.parent = parent;
}
private ServiceProviderQueryHandler Query(object context)
{
return result =>
{
var container = new ServiceContainer(parent(context));
// provides the connection string here
var log = new SqlErrorLog(ConfigurationContext.Current.GetDatabaseConnectionString())
{
ApplicationName = "MyApplication",
};
container.AddService(typeof(ErrorLog), log);
return container;
};
}
public static ServiceProviderQueryHandler Create(ServiceProviderQueryHandler parent)
{
var queryHandler = new EnclosedServiceProviderQueryHandler(parent);
return queryHandler.Query(parent);
}
}
}
This creates a delegate that in its turn provide a SqlErrorLog that takes a connection string from your Ambient Context. And to hook in this, in your Global.asax.cs
, into Application_Start()
you need to add the following:
protected void Application_Start()
{
// other configurations here...
ElmahConfig.Configure();
}
And in web.config you don’t need to provide any type of class in <elmah>
section:
<elmah>
<security allowRemoteAccess="true" />
</elmah>
And usual
<errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="DefaultConnection" />
must be removed, as we already do the same in Application_Start()