9

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

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

一件奇怪的事情是来自 Atif 的一篇较旧的帖子,上面写着他们已经被记录了:

http://markmail.org/message/ncmdgwm5rmzewbwu

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

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

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

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而不是切换到别的东西。

4

3 回答 3

6

Atif 在推特上回复说没有已知的补丁:

http://twitter.com/raboof/statuses/7229453423

所以我创建了一个这样做的补丁:

http://twitter.com/manningj/statuses/7231616905

http://blog.sublogic.com/2009/12/patch-to-enable-session-variable-logging-with-elmah/

于 2009-12-31T12:58:06.213 回答
3

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

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

于 2012-03-27T00:25:06.420 回答
0

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

在 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 文件)并从 bin 中获取所需的 ddl 文件。

  • AntiXssLibrary.dll
  • Elmah.AspNet.dll
  • 埃尔玛.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" />
于 2018-02-14T18:06:44.033 回答