Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting the Id of an error in Elmah after calling .Raise()

I'm working on an MVC3 application and I'm using Elmah to handle my error logging. What I want in my application is to carry the Elmah Id onto the custom error page as I will provide a link which allows a user to specifically report it in the event that it is a repeat error (in their opinion).

Now, I've read similar questions on here and they suggest adding the following code (or similar) to the Global.asax.cs file:

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

This is what I'm using at the moment, with the SessionID allowing for added flexibility in making the Session stored object unique. However, this may still cause issues if more than one error occurs at (virtually) the same time.

Instead, I decided to work on my own HandleErrorAttribute that looks something like this:

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

where ErrorDetail is a custom model which just has the public properties that are being set here as strings. This data can then be shown in the model for admin's at a quick glance and the errorId can be used to create the 'Report Error' link.

So my question is does anyone know of a way of getting the Id after the line

Elmah.ErrorSignal.FromCurrentContext().Raise(filterContext.Exception)

without using the Logged event in the global.asax.cs?

Any thoughts are much appreciated.

like image 332
Adam Goss Avatar asked Oct 25 '11 20:10

Adam Goss


People also ask

How do you check ELMAH error?

Build the application, run it in the browser, and navigate to http://www.yoursite.com/elmah.axd. You are prompted to log in before you see the content. After a successful authentication, you see a web page to remotely view the entire log of recorded exceptions.

What is ELMAH error?

ELMAH (Error Logging Modules and Handlers) is an application-wide error logging facility that is completely pluggable. It can be dynamically added to a running ASP.NET web application, or even all ASP.NET web applications on a machine, without any need for re-compilation or re-deployment.

What is Elmah io?

elmah.io is the easy error logging and uptime monitoring service for . NET. Take back control of your errors with support for all . NET web and logging frameworks.


3 Answers

After reading Dupin's comments it seems logical that it isn't quite possible. I tried digging around the Elmah source code and came up with a couple of alternatives that might be worth sharing.

The obvious alternative is stick with my original option of using the Logged event:

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

For a more direct solution it is possible to manually log the error with the following:

string errorId = Elmah.ErrorLog.GetDefault(HttpContext.Current)
    .Log(new Elmah.Error(filterContext.Exception));

However, using this approach won't hit your filters or mail module and so on.

After doing a bit of thinking and a little more searching, I came up with a new compromise. Still using the logged event but I've found a way to create a new unique key that can be passed to the view, by adding my own data to the exception.

string loggingKey = "ElmahId_" + Guid.NewGuid().ToString();
filterContext.Exception.Data.Add("LoggingKey", loggingKey);

This way I can pass the exception in my view model, which has this key value in the Data collection. The logged event would be changed to something like this:

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

Then in the view I get the key from the model to then pull the Id from the Session collection.

like image 130
Adam Goss Avatar answered Oct 01 '22 21:10

Adam Goss


Maybe not very helpful but I suspect you can't get the error id at that point and you will need to use the logged event.

When you call

Elmah.ErrorSignal.FromCurrentContext().Raise(filterContext.Exception)

You're just raising the error. Depending on how you've configured ELMAH you might be logging the error or you might just send an email or a tweet.

There's no direct link between a raised error and an Id. That will only come with logging which, if you're feeling funny, you could be doing in multiple places and so creating multiple ids.

like image 31
Dupin Avatar answered Oct 01 '22 21:10

Dupin


http://code.google.com/p/elmah/issues/detail?id=148#c3 is an identical request and a proposed patch on the Elmah project site

like image 44
robrich Avatar answered Oct 01 '22 23:10

robrich