在调用.Raise()后获取Elmah中的错误ID

Ada*_*oss 8 asp.net-mvc elmah

我正在研究MVC3应用程序,我正在使用Elmah来处理我的错误记录.我在我的应用程序中想要的是将Elmah Id带到自定义错误页面,因为我将提供一个链接,允许用户在重复错误(他们认为)的情况下专门报告它.

现在,我在这里阅读了类似的问题,他们建议在Global.asax.cs文件中添加以下代码(或类似代码):

void ErrorLog_Logged(object sender, ErrorLoggedEventArgs args)
{
    string sessionId = Session.SessionID;
    Session["ElmahId_" + sessionId] = args.Entry.Id;
}
Run Code Online (Sandbox Code Playgroud)

这就是我目前正在使用的,SessionID允许增加使Session会话存储对象唯一的灵活性.但是,如果在(几乎)同时发生多个错误,这仍可能导致问题.

相反,我决定使用我自己的HandleErrorAttribute,它看起来像这样:

public class ElmahHandleErrorAttribute : FilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        if (filterContext == null)
            throw new ArgumentNullException("filterContext");

        if (filterContext.IsChildAction && (!filterContext.ExceptionHandled
            && filterContext.HttpContext.IsCustomErrorEnabled))
        {
            Elmah.ErrorSignal.FromCurrentContext().Raise(filterContext.Exception);

            // get error id here
            string errorId = null;

            string areaName = (String)filterContext.RouteData.Values["area"];
            string controllerName = (String)filterContext.RouteData.Values["controller"];
            string actionName = (String)filterContext.RouteData.Values["action"];

            var model = new ErrorDetail
            {
                Area = areaName,
                Controller = controllerName,
                Action = actionName,
                ErrorId = errorId,
                Exception = filterContext.Exception
            };

            ViewResult result = new ViewResult
            {
                ViewName = "Error",,
                ViewData = new ViewDataDictionary<ErrorDetail>(model),
                TempData = filterContext.Controller.TempData
            };

            filterContext.Result = result;
            filterContext.ExceptionHandled = true;
            filterContext.HttpContext.Response.Clear();
            filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

其中ErrorDetail是一个自定义模型,它只具有在此处设置为字符串的公共属性.然后,可以在管理员的模型中快速显示此数据,并且errorId可用于创建"报告错误"链接.

所以我的问题是有没有人知道在线后获得Id的方法

Elmah.ErrorSignal.FromCurrentContext().Raise(filterContext.Exception)
Run Code Online (Sandbox Code Playgroud)

不使用global.asax.cs中的Logged事件?

任何想法都非常感激.

Ada*_*oss 7

在阅读了杜宾的评论之后,这似乎是不合逻辑的.我尝试挖掘Elmah源代码并提出了一些可能值得分享的替代方案.

显而易见的替代方案是坚持使用Logged事件的原始选项:

void ErrorLog_Logged(object sender, ErrorLoggedEventArgs args)
{
    string sessionId = Session.SessionID;
    Session["ElmahId_" + sessionId] = args.Entry.Id;
}
Run Code Online (Sandbox Code Playgroud)

要获得更直接的解决方案,可以使用以下方法手动记录错误:

string errorId = Elmah.ErrorLog.GetDefault(HttpContext.Current)
    .Log(new Elmah.Error(filterContext.Exception));
Run Code Online (Sandbox Code Playgroud)

但是,使用此方法不会命中您的过滤器或邮件模块等.

在做了一些思考和更多的搜索后,我想出了一个新的妥协.仍然使用已记录的事件,但我找到了一种方法来创建一个可以传递给视图的新唯一键,方法是将我自己的数据添加到异常中.

string loggingKey = "ElmahId_" + Guid.NewGuid().ToString();
filterContext.Exception.Data.Add("LoggingKey", loggingKey);
Run Code Online (Sandbox Code Playgroud)

这样我就可以在我的视图模型中传递异常,该模型在Data集合中具有此键值.记录的事件将更改为以下内容:

void ErrorLog_Logged(object sender, ErrorLoggedEventArgs args)
{
    string key = args.Entry.Error.Exception.Data["LoggingKey"].ToString();
    Session[key] = args.Entry.Id;
}
Run Code Online (Sandbox Code Playgroud)

然后在视图中,我从模型中获取密钥,然后从Session集合中提取Id.