從大神 Kevin 那邊知道 Arebis.Web.Mvc.ElmahDashboard 這個 Dash Board套件,它比 Elmah.axd 更加的友善,使用後讓 Log Viewer、Search 的友善度提升,二話不說立馬納入專案內;有在使用 Elmah + Sql Server 的夥伴,可以試著使用看看
http://getglimpse.com/
http://kevintsengtw.blogspot.tw/2016/05/aspnet-mvc-elmah-dashboard-elmah-sql.html
這裡將分享保護 Elmah Connect String 的使用經驗,不會提到安裝套件步驟
我的專案是 WebForm + EF + Elmah + NLog To Elmah + Arebis.Web.Mvc.ElmahDashboard,若動到了保護 Elmah 的連線字串,會影響到 Elmah、Arebis.Web.Mvc.ElmahDashboard 和 NLog To Elmah,你應該適實際調整修改影響範圍
開發環境
- Windows 10 Enterprise x64 CHT
- VS2015 Update3
- Entity Framework 6.1.3
- Elmah 1.22
- NLog 4.3.4
- Arebis.Web.Mvc.ElmahDashboard 1.0.0
- Glimpse 1.8.6
解密
這裡會用到我自行開發連線字串的解密、連線工廠,不影響主要思路,就不公布惹,實際做法可參考
連線字串的加解密方式可參考黑大的文章
http://blog.darkthread.net/post-2015-11-28-encrypt-ef-connstring.aspx
連線工廠可參考以下連結:
https://github.com/codetuner/Arebis.Web.Mvc.ElmahDashboard/blob/master/ElmahDashboardHostingApp/Areas/MvcElmahDashboard/Code/ElmahDashboardContext.cs
http://getglimpse.com/Docs/Manual-ADO-Integration
開始實作
@Web.Config
我加密後的連線字串如下圖:
原本在 Web.Config 裡面設定的設定已經用不到了 我把它挪到 Application_Start
@Global.asax.cs
Elmah.ServiceCenter.Current 的型別是 ServiceProviderQueryHandler 委派,這裡我用 Lambda 的寫法
我要在 Lambda 裡解密連線字串並重新裝載 SqlErrorLog
ConnectionFactory.GetConnectionString 是我自己的解密方法
private static volatile ServiceContainer s_elmahServiceContainer;
private static readonly object s_lockElmahServiceContainer = new object();
protected void Application_Start(object sender, EventArgs e)
{
var parent = ServiceCenter.Current;
ServiceCenter.Current = context =>
{
lock (s_lockElmahServiceContainer)
{
if (s_elmahServiceContainer != null)
{
return s_elmahServiceContainer;
}
s_elmahServiceContainer = new ServiceContainer(parent(context));
//decrypt connection string
var connectionString =
ConnectionFactory.GetConnectionString("Elmah");
var log = new SqlErrorLog(connectionString);
log.ApplicationName = AppSetting.APPLICATION_NAME;
s_elmahServiceContainer.AddService(typeof(ErrorLog), log);
return s_elmahServiceContainer;
}
};
}
@ElmahDashboardContext.cs
Arebis.Web.Mvc.ElmahDashboard 有自己的連線物件,也必須要解密連線字串
ConnectionString.Decrypt 是我自己的解密方法
private static DbConnection CreateConnection(DbProviderFactory dbProviderFactory, string connectionString)
{
var conn = dbProviderFactory.CreateConnection();
if (connectionString.Contains(Utility.PROTECT_TEXT))
{
connectionString = ConnectionString.Decrypt(connectionString);
}
conn.ConnectionString = connectionString;
conn.Open();
return conn;
}
@ElmahMsSqlTarget.cs
這個方法是實作 TargetWithLayout 抽象來的,具體作法請參考 Bibby 大神的文章:http://bibby.be/2012/08/nlog-elamh.html
我只是改用自己的解密連線工廠 (ConnectionFactory.CreateDbConnection) 和 Dapper
protected override void Write(LogEventInfo logEvent)
{
using (var connection = ConnectionFactory.CreateDbConnection(ConnectionStringName))
{
if (connection.State == ConnectionState.Closed)
{
connection.Open();
}
var time = logEvent.TimeStamp.ToUniversalTime();
var xdoc = GetXdoc(logEvent, time);
var userName = string.Empty;
if (CurrentHttpContext != null && CurrentHttpContext.User.Identity.IsAuthenticated)
{
userName = CurrentHttpContext.User.Identity.Name;
}
connection.Execute("ELMAH_LogError",
new
{
ErrorId = (Guid) SequentialGuid.NewGuid(),
Application = AppSetting.APPLICATION_NAME,
Host = Environment.MachineName,
Type = "NLog-" + logEvent.Level.Name,
Source = logEvent.LoggerName,
Message = logEvent.FormattedMessage,
User = userName,
AllXml = xdoc.ToString(),
StatusCode = 0,
TimeUtc = time
},
commandType: CommandType.StoredProcedure);
}
}
處理完後,就能使用加密後的連線字串了,基本上有用到 Elmah 連線字串的物件的人都要處理
參考資料:
https://dotblogs.com.tw/mrkt/2016/05/27/013356
http://kevintsengtw.blogspot.tw/2016/05/aspnet-mvc-elmah-dashboard-elmah-sql.html
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET