Getting the error identifier in Elmah after calling .Raise ()

I am working on an MVC3 application and I am using Elmah to handle the error log. What I want in my application is to transfer Elmah Id to the user error page, as I have provided a link that allows the user to specifically report this in case it is a repeat error (in their opinion).

Now I read similar questions 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 am currently using, with a SessionID, which gives me more flexibility in creating a unique Session object. However, this can still cause problems if more than one error occurs simultaneously (practically).

Instead, I decided to work on my own HandleErrorAttribute, which 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 that has only public properties that are set here as strings. This data can then be quickly displayed in the model for the administrator, and errorId can be used to create the "Report an error" link.

So my question is: does anyone know how to get the id after the string

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

without using a logged event in the global.asax.cs file?

Any thoughts are greatly appreciated.

+8
asp.net-mvc elmah
source share
4 answers

After reading the comments, Dupin seems logical that this is not entirely possible. I tried digging into the Elmah source code and came up with a couple of alternatives that might be worth sharing.

An obvious alternative is to use my original option to use a registered event:

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

For a more direct solution, you can manually register an error with the following:

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

However, using this approach will not result in blows to your filters or mail module, etc.

After a little thought and a bit more searching, I came up with a new compromise. Still using the registered event, but I 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); 

That way, I can pass an exception in my view model, which has this key value in the data collection. The registered event will be changed to the following:

 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 to the model, then to derive the identifier from the collection of sessions.

+7
source share

This may not be very useful, but I suspect that you cannot get the error identifier at this point, and you will need to use the logged event.

When you call

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

You are just making a mistake. Depending on how you configured ELMAH, you can log an error or simply send an email or tweet.

There is no direct connection between the raised error and the identifier. This will happen only during registration, which, if you feel funny, you can do in several places and create several identifiers.

+2
source share

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

+1
source share

The solution above only works if there is a Session object (website script). We needed to work in Azure WorkerRole or configure the type of console / desktop application. This solution will also work on the Internet and save session memory. There is no perfect solution, but it helps us to log the error and retrieve the stored identifier and disable email:

  • Save the error using ErrorLog.Log (error) (see Using ELMAH in a console application )
  • Raise an error by skipping registration (SQL or otherwise)

For the second part, we used the ElmahExtension implementation given here: https://stackoverflow.com/a/312960/

and DELETE the following lines adding an entry:

 (ErrorLog as IHttpModule).Init(httpApplication); errorFilter.HookFiltering(ErrorLog); //removed! 

The entire call from our client code is as follows:

 ErrorLog errorLog = ErrorLog.GetDefault(null); errorLog.ApplicationName = "YourAppName"; Error error = new Error(ex); string errorResult = errorLog.Log(error); Guid errorId = new Guid(errorResult); ex.LogToElmah(); //this is just going to send the email 

You might want to call this extension method something else, like RaiseToElmahNoStorage (), or something to indicate that it is skipping the storage component.

0
source share

All Articles