ELMAH にセッション値を含めるにはどうすればよいですか?
-
21-09-2019 - |
質問
注記:セッションの使用を避けるさまざまな理由は承知していますが、これは私が継承したプロジェクトなので、返信のその部分はスキップしてください:)
これは解決された問題なので、誰かが車輪の再発明ではなく、セッション データのログ記録を含む ELMAH パッチ/ブランチ/フォークを指摘してくれることを願っています。
奇妙な点の 1 つは、Atif からの古い投稿で、すでにログに記録されていると述べていることです。
http://markmail.org/message/ncmdgwm5rmzewbwu
コメント者の henningst は、ここでセッション変数を追加することについて言及しました。
http://www.hanselman.com/blog/ELMAHErrorLoggingModulesAndHandlersForASPNETAndMVCToo.aspx
もう 1 つのアプローチ (私が避けたいのは) は、値を Cookie にコピーすることです。
代替手段の 1 つは、ELMAH 以外のもの (Exceptioneer など) に切り替えることだと思います。 http://Exceptioneer.com/Public/ExceptioneerAndELMAH.aspx)しかし、これが現時点での ELMAH に関する唯一の問題であるため、他のものに切り替えるよりも、パッチを適用した ELMAH を使用したいと思っています。
解決
ATIFには、既知のパッチはありませんと言ってTwitter上で答えます:
http://twitter.com/raboof/statuses/7229453423する
だから私はそうするパッチを作成します:
http://twitter.com/manningj/statuses/7231616905する
ます。http://ブログ.sublogic.com / 2009/12 /パッチ・ツー・イネーブルセッション変数-ロギングと-ELMAH / の
他のヒント
むしろELMAHにパッチを適用するよりも、私は例外のデータでこれをやりました。 Global.asaxの中で、私はのApplication_Errorに例外に余分なデータを挿入します()。 「HistoryStackは、」ボタンとタブクリックするなど、ユーザーの履歴を記録するための私自身のクラスです。
void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError().GetBaseException();
var stack = HistoryStack.Dump(); // essentially grabs data from the session
ex.Data.Add("historyStack", stack);
}
次に、ErrorMail_Mailingで()私は、データの背中をつかんで、電子メールでそれを付加します:
void ErrorMail_Mailing(object sender, Elmah.ErrorMailEventArgs e)
{
var stack = e.Error.Exception.Data["historyStack"] as Stack<string>;
if (stack == null && e.Error.Exception.InnerException != null)
{
// could probably skip the first try and go straight to this assignment:
stack = e.Error.Exception.InnerException.Data["historyStack"] as Stack<string>;
}
if (stack != null && stack.Count > 0)
{
e.Mail.Body = e.Mail.Body + "<h1>Browsing History</h1>" + System.Environment.NewLine;
while (stack.Count > 0)
{
e.Mail.Body = e.Mail.Body + stack.Pop() + "<br />" + System.Environment.NewLine;
}
}
}
さて、このデータは、電子メールの一番下に追加されます。必要なパッチや拡張はありません。
掘り出すことができる古いパッチは、残念ながら今の Elmah では少し時代遅れです。バージョン2.0.15523.27でセッション変数をログに記録するために行ったことは次のとおりです ここにある古いパッチに基づいています。 https://storage.googleapis.com/google-code-attachments/elmah/issue-12/comment-5/elmah-sessionVariables.patch
Error.cs 内
System.Web.SessionState をインポートする
using System.Web.SessionState;
探す:
private NameValueCollection _serverVariables;
private NameValueCollection _queryString;
private NameValueCollection _form;
private NameValueCollection _cookies;
以下を追加します。
private NameValueCollection _sessionVariables;
探す:
_serverVariables = CopyCollection(request.ServerVariables);
_queryString = CopyCollection(qsfc.QueryString);
_form = CopyCollection(qsfc.Form);
_cookies = CopyCollection(qsfc.Cookies);
以下を追加します。
_sessionVariables = CopyCollection(context.Session);
探す:
public NameValueCollection Cookies
{
get { return FaultIn(ref _cookies); }
}
以下を追加します。
/// <summary>
/// Gets a collection representing the session variables captured as part of the diagnostic data
/// </summary>
public NameValueCollection SessionVariables
{
get { return FaultIn(ref _sessionVariables); }
}
探す:
copy._serverVariables = CopyCollection(_serverVariables);
copy._queryString = CopyCollection(_queryString);
copy._form = CopyCollection(_form);
copy._cookies = CopyCollection(_cookies);
以下を追加します。
copy._sessionVariables = CopyCollection(_sessionVariables);
探す:
private static NameValueCollection CopyCollection(NameValueCollection collection)
上に追加:
private static NameValueCollection CopyCollection(HttpSessionStateBase sessionVariables)
{
if (sessionVariables == null || sessionVariables.Count == 0)
return null;
var copy = new NameValueCollection(sessionVariables.Count);
for (int i = 0; i < sessionVariables.Count; i++)
copy.Add(sessionVariables.Keys[i], sessionVariables[i].ToString());
return copy;
}
ErrorJson.cs 内
探す:
Member(writer, "queryString", error.QueryString);
Member(writer, "form", error.Form);
Member(writer, "cookies", error.Cookies);
以下を追加します。
Member(writer, "sessionVariables", error.SessionVariables);
ErrorXml.cs 内
探す:
case "form" : collection = error.Form; break;
case "cookies" : collection = error.Cookies; break;
以下を追加します。
case "sessionVariables": collection = error.SessionVariables; break;
探す:
WriteCollection(writer, "form", error.Form);
WriteCollection(writer, "cookies", error.Cookies);
以下を追加します。
WriteCollection(writer, "sessionVariables", error.SessionVariables);
ErrorMailHtmlPage.cshtml 内
探す:
<p>@(RenderPartial<PoweredBy>())</p>
上に追加:
@foreach (var collection in
from collection in new[]
{
new
{
Id = "SessionVariables",
Title = "Session Variables",
Items = error.SessionVariables,
}
}
let data = collection.Items
where data != null && data.Count > 0
let items = from i in Enumerable.Range(0, data.Count)
select KeyValuePair.Create(data.GetKey(i), data[i])
select new
{
collection.Id,
collection.Title,
Items = items.OrderBy(e => e.Key, StringComparer.OrdinalIgnoreCase)
}
)
{
<div id="@collection.Id">
<h1>@collection.Title</h1>
<table class="collection">
<tr><th>Name</th>
<th>Value</th></tr>
@foreach (var item in collection.Items)
{
<tr><td>@item.Key</td>
<td>@item.Value</td></tr>
}
</table>
</div>
}
Visual Studio で ErrorMailHtmlPage.cshtml に変更を加えた後、ファイルを右クリックして [カスタム ツールの実行] を選択し、ErrorMailHtmlPage.generated.cs のコードを生成します。
ErrorDetailPage.cshtml 内
(ファイルの最後で) を見つけます。
@*
}
*@
上に追加:
@{
var sessioncollection = new
{
Data = error.SessionVariables,
Id = "SessionVariables",
Title = "Session Variables",
};
//
// If the collection isn't there or it's empty, then bail out.
//
if (sessioncollection.Data != null && sessioncollection.Data.Count > 0)
{
var items =
from i in Enumerable.Range(0, sessioncollection.Data.Count)
select new
{
Index = i,
Key = sessioncollection.Data.GetKey(i),
Value = sessioncollection.Data[i],
};
items = items.OrderBy(e => e.Key, StringComparer.OrdinalIgnoreCase);
<div id="@sessioncollection.Id">
<h2>@sessioncollection.Title</h2>
@*
// Some values can be large and add scroll bars to the page
// as well as ruin some formatting. So we encapsulate the
// table into a scrollable view that is controlled via the
// style sheet.
*@
<div class="scroll-view">
<table cellspacing="0" style="border-collapse:collapse;" class="table table-condensed table-striped">
<tr>
<th class="name-col" style="white-space:nowrap;">Name</th>
<th class="value-col" style="white-space:nowrap;">Value</th>
</tr>
@foreach (var item in items)
{
<tr class="@(item.Index % 2 == 0 ? "even" : "odd")">
<td class="key-col">@item.Key</td>
<td class="value-col">@item.Value</td>
</tr>
}
</table>
</div>
</div>
}
}
Visual Studio で ErrorDetailPage.cshtml に変更を加えた後、ファイルを右クリックして [カスタム ツールの実行] を実行し、ErrorDetailPage.generated.cs のコードを生成します。
これで、ビルド (プロジェクトに含まれている build.cmd ファイルを使用しました) し、必要な ddl ファイルを bin から取得できます。
- AntiXssLibrary.dll
- Elmah.AspNet.dll
- エルマ.dll
また、Elmah への参照にバージョンを含めるために、プロジェクトの web.config を変更する必要がある場合もあります。Resharper を使用している場合は、これらのそれぞれをクリックして修正できます。(おそらくこれを回避するには別の方法があるはずですが、よくわかりませんし、それを理解することについてはあまり心配していませんでした)
そのうちの 1 つの例は次のとおりです。
<section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
に
<section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah.AspNet, Version=2.0.15523.27, Culture=neutral, PublicKeyToken=null" />