Yasser Shaikh
Yasser Shaikh

Reputation: 47784

How to log custom exception with additional Data property to Elmah?

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.

Upvotes: 3

Views: 2701

Answers (3)

Luke Rice
Luke Rice

Reputation: 236

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

Upvotes: 1

ThomasArdal
ThomasArdal

Reputation: 5239

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

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

Upvotes: 1

samy
samy

Reputation: 14962

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.

Upvotes: 1

Related Questions