代码之家  ›  专栏  ›  技术社区  ›  James Manning

如何让elmah包含会话值?

  •  9
  • James Manning  · 技术社区  · 15 年前

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

    由于这是一个已解决的问题,我希望有人可以指向一个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

    我知道另一种选择是换成除埃尔玛以外的东西(如例外者-见 http://exceptioneer.com/Public/ExceptioneerAndELMAH.aspx )但由于这是我目前唯一的问题,我宁愿有一个补丁埃尔玛,而不是切换到其他东西。

    3 回复  |  直到 7 年前
        2
  •  3
  •   Michael La Voie Frederik Gheysels    11 年前

    我没有修补elmah,而是用异常数据来做这个。在global.asax中,我将额外的数据插入到应用程序的异常中。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;
            }
        }
    }
    

    现在,这些数据被附加到电子邮件的底部。不需要补丁或扩展。

        3
  •  0
  •   abney317    7 年前

    不幸的是,现在的埃尔玛已经有点过时了。下面是我在版本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文件)并从需要的bin中获取DDL文件。

    • antixsslibrary.dll文件
    • elmah.aspnet.dll文件
    • ELMAHDLL

    现在您可能还需要修改项目中的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" />