3

I have a custom exception, where I have overriden the Data property using reflection like the following...

public class MyCustomException : Exception
{
    private readonly SomeModel _log;
    public MyCustomException(SomeModel log)
        : base(string.Format("Could not insert to some table"))
    {
        _log = log;
    }

    public override System.Collections.IDictionary Data
    {
        get
        {
            var data = new Dictionary<string, object>();
            foreach (PropertyInfo pinfo in _log.GetType().GetProperties())
            {
                data.Add(pinfo.Name, pinfo.GetType().GetProperty(pinfo.Name));
            }
            return data;
        }
    }
}

When the above exception is thrown, it gets logged to elmah but the Data is not logged.

What changes do I have to make so that the Data is also logged to elmah ? Please advice.

Yasser Shaikh
  • 46,934
  • 46
  • 204
  • 281

3 Answers3

1

The Detail property of the Elmah.Error object - which is then processed by an ErrorLog class - is built from the ToString() method of the exception.

// Elmah.Error
public Error(Exception e, HttpContext context)
{
    // snip
    this._detail = e.ToString(); // here
    // snip

Add your data to an override of the ToString method in the MyCustomException to see it in Elmah.

samy
  • 14,832
  • 2
  • 54
  • 82
  • If you want to have a custom process for this data, you will have to create a custom `ErrorLog` class – samy Oct 07 '14 at 14:34
1

Your question is currently the issue with most stars on the ELMAH issue tracker:

https://code.google.com/p/elmah/issues/detail?id=162

ThomasArdal
  • 4,999
  • 4
  • 33
  • 73
1

@samy may be more correct, but I have also found another possible option that works for my situation. I am using elmah in a webapi2 project where users are anonymous and in one particular controller I want to record some context of the request from the viewmodel (in my case, an email address but I could potentially record more data) and I want to be able to associate errors to email so I can determine, after an error, if the same user was able to submit an order successfully.

In my controller, I perform a number of database calls in a transaction and then submit an order to paypal, all within a try/catch block. In the catch, I create a new exception instance with a message containing the email and set the innerException property to the thrown exception and throw the new exception.

I know it is possible to lose some stack trace information, I tested this in my context and the stack trace seems to be maintained but exceptions occur inside the controller because there are not many layers to this particular controller and application. If anyone has a similar situation, this method might be the quickest and easiest.

catch (Exception ex)
{
    Exception newException = new Exception(viewModel.ContactEmail, ex);
    throw newException;
}

This assumes you have a exception filter, such as below (for webapi), and the filter is registered as global in global.asax.

public class LogExceptionAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext actionExecutedContext)
    {
        if (HttpContext.Current != null)
        {
            ErrorSignal.FromCurrentContext().Raise(actionExecutedContext.Exception);
        }
    }
}
Luke Rice
  • 236
  • 2
  • 13