如何让 ELMAH 包含会话值?

发布于 2024-08-16 10:04:42 字数 1117 浏览 6 评论 0原文

注意:我知道避免使用会话的各种原因,但这是我继承的一个项目,所以请跳过任何回复的这一部分:)

因为这是一个已解决的问题,我希望有人可以指出 ELMAH 补丁/branch/fork 包括记录会话数据而不是重新发明轮子。

一件奇怪的事情是 Atif 的一篇旧帖子说他们已经记录了:

http://markmail.org/message/ ncmdgwm5rmzewbwu

评论者 henningst 提到在此处添加会话变量:

http://www.hanselman。 com/blog/ELMAHErrorLoggingModulesAndHandlersForASPNETAndMVCToo.aspx

另一种方法(我宁愿避免)是将值复制到 cookies

http://www.sharpdeveloper.net/content/archive/2008/11/10/how -to-get-session-or-other-custom-values-into-elmah.aspx

我知道一种替代方法是切换到 ELMAH 之外的其他东西(例如 Exceptioneer - 请参阅 http://exceptioneer.com/Public/ExceptioneerAndELMAH.aspx) 但由于这是我目前对 ELMAH 的唯一问题,我宁愿只要有一个打补丁的 ELMAH 就可以了,而不是切换到其他东西。

NOTE: I know the various reasons to avoid using the session, but this is a project I've inherited, so please skip that part of any replies :)

Since it's a solved problem, I'm hoping someone can point to an ELMAH patch/branch/fork that includes logging session data rather than reinventing the wheel.

One weird thing is an older post from Atif that says they're already logged:

http://markmail.org/message/ncmdgwm5rmzewbwu

commenter henningst mentioned adding in the session variables here:

http://www.hanselman.com/blog/ELMAHErrorLoggingModulesAndHandlersForASPNETAndMVCToo.aspx

Another approach (I'd rather avoid) is copying the values into cookies

http://www.sharpdeveloper.net/content/archive/2008/11/10/how-to-get-session-or-other-custom-values-into-elmah.aspx

I know one alternative is to switch to something besides ELMAH (like Exceptioneer - see http://exceptioneer.com/Public/ExceptioneerAndELMAH.aspx) but since this is my only problem with ELMAH at the moment, I'd rather just have a patched ELMAH than switch to something else.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

活雷疯 2024-08-23 10:04:42

我没有修补 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;
        }
    }
}

现在此数据附加到电子邮件的底部。无需补丁或扩展。

Rather than patching Elmah, I did this with Exception data. In Global.asax I inserted the extra data into the exception on Application_Error(). "HistoryStack" is my own class for recording user history, including button and tab clicks:

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

Then, in ErrorMail_Mailing() I grabbed the data back and appended it in the email:

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

Now this data is appended to the bottom of the email. No patches or extensions necessary.

゛时过境迁 2024-08-23 10:04:42

不幸的是,现在可以挖出的旧补丁对于 Elmah 来说有点过时了。这是我在版本 2.0.15523.27 中记录会话变量的方法
基于此处找到的旧补丁:https://storage.googleapis.com/google-code-attachments/elmah/issue-12/comment-5/elmah-sessionVariables.patch

In Error.cs

导入系统.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 文件)并从 bin 中获取所需的 ddl 文件。

  • AntiXssLibrary.dll
  • Elmah.AspNet.dll
  • Elmah.dll

您现在可能还需要修改项目中的 web.config,以包含对 Elmah 的任何引用的版本。如果您使用 Resharper,您只需单击其中的每一个即可修复它们。 (可能应该采取不同的方式来避免这种情况,但我不确定,而且我不太担心弄清楚)

其中一个示例将更

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

The old patch that can be dug up is unfortunately a little outdated with Elmah now. Here's what I did to log session variables in version 2.0.15523.27
Based on an older patch found here: https://storage.googleapis.com/google-code-attachments/elmah/issue-12/comment-5/elmah-sessionVariables.patch

In Error.cs

Import System.Web.SessionState

using System.Web.SessionState;

Find:

private NameValueCollection _serverVariables;
private NameValueCollection _queryString;
private NameValueCollection _form;
private NameValueCollection _cookies;

Add below:

private NameValueCollection _sessionVariables;

Find:

_serverVariables = CopyCollection(request.ServerVariables);
_queryString = CopyCollection(qsfc.QueryString);
_form = CopyCollection(qsfc.Form);
_cookies = CopyCollection(qsfc.Cookies);

Add below:

_sessionVariables = CopyCollection(context.Session);

Find:

public NameValueCollection Cookies 
{
    get { return FaultIn(ref _cookies); }
}

Add below:

/// <summary>
/// Gets a collection representing the session variables captured as part of the diagnostic data
/// </summary>

public NameValueCollection SessionVariables
{
    get { return FaultIn(ref _sessionVariables); }
}

Find:

copy._serverVariables = CopyCollection(_serverVariables);
copy._queryString = CopyCollection(_queryString);
copy._form = CopyCollection(_form);
copy._cookies = CopyCollection(_cookies);

Add below:

copy._sessionVariables = CopyCollection(_sessionVariables);

Find:

private static NameValueCollection CopyCollection(NameValueCollection collection)

Add above:

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

In ErrorJson.cs

Find:

Member(writer, "queryString", error.QueryString);
Member(writer, "form", error.Form);
Member(writer, "cookies", error.Cookies);

Add below:

Member(writer, "sessionVariables", error.SessionVariables);

In ErrorXml.cs

Find:

case "form"            : collection = error.Form; break;
case "cookies"         : collection = error.Cookies; break;

Add below:

case "sessionVariables": collection = error.SessionVariables; break;

Find:

WriteCollection(writer, "form", error.Form);
WriteCollection(writer, "cookies", error.Cookies);

Add below:

WriteCollection(writer, "sessionVariables", error.SessionVariables);

In ErrorMailHtmlPage.cshtml

Find:

<p>@(RenderPartial<PoweredBy>())</p>

Add above:

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

After making changes to ErrorMailHtmlPage.cshtml in Visual Studio, right click on the file and "Run Custom Tool" to generate the code for ErrorMailHtmlPage.generated.cs


In ErrorDetailPage.cshtml

Find (at the end of the file):

@*
}
*@

Add above:

@{
    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>
    }
}

After making changes to ErrorDetailPage.cshtml in Visual Studio, right click on the file and "Run Custom Tool" to generate the code for ErrorDetailPage.generated.cs


Now you can build (I just used the build.cmd file that was included with the project) and grab the ddl files from bin that are needed.

  • AntiXssLibrary.dll
  • Elmah.AspNet.dll
  • Elmah.dll

You may also have to modify the web.config in your project now to include the version on any references to Elmah. If you're using Resharper you can just click on each of these and fix them. (There's probably a different way this is supposed to be done to avoid this but I'm not sure and I wasn't too worried about figuring it out)

An example of one of them though would be changing

<section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />

to

<section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah.AspNet, Version=2.0.15523.27, Culture=neutral, PublicKeyToken=null" />
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文