2009-12-29 35 views
9

注:我知道避免使用会话的各种原因,但这是我继承的项目,所以请跳过那部分的任何回复:)如何让ELMAH包含会话值?

由于这是一个解决的问题,我希望有人可以指向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比开关的东西其他。

回答

3

而不是修补Elmah,我用Exception数据做了这个。在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; 
     } 
    } 
} 

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

+0

这实际上是我所做的,除了我创建了一个附件到电子邮件,以保持会话变量有点分开。缺点是你可以利用ELMAH的邮件模块,所以如果有人不使用它,他们会敬酒+你不能在你的数据库上查询这些变量的统计数据。 – lstanczyk 2012-06-12 15:36:57

+0

HistoryStack.Dump()返回值的格式是什么?它只是CRLF明文吗? – NickG 2012-08-10 08:15:37

+0

这似乎不适用于我。虽然Application_Error()触发了,但额外的数据从来不会出现在数据库的XML中,因此无法查看它:(需要额外的步骤吗? – NickG 2012-08-10 08:30:08

0

现在可以挖出的旧补丁不幸已经过时了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> 
    } 
} 

进行更改ErrorDetailPage.cshtml在Visual Studio中,右键点击后在文件和“运行自定义工具”生成代码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" />