I'm a bit confused at how to add a message to an error logged programatically with ELMAH.
eg:
public ActionResult DoSomething(int id)
{
try { ... }
catch (Exception e)
{
// I want to include the 'id' param value here, and maybe some
// other stuff, but how?
ErrorSignal.FromCurrentContext().Raise(e);
}
}
It seems all Elmah can do is log the raw exception, how can I also log my own debug info?
You can throw a new Exception setting the original as the inner exception and ELMAH will log the messages for both:
catch(Exception e)
{
Exception ex = new Exception("ID = 1", e);
ErrorSignal.FromCurrentContext().Raise(ex);
}
will show
System.Exception: ID = 1 ---> System.NullReferenceException: Object reference not set to an instance of an object.
I found that I can also do something like:
Elmah.ErrorSignal.FromCurrentContext().Raise(new NotImplementedException("class FbCallback.Page_Load() Request.Url= " + Request.Url));
To log my own messages. Then in when I browse to
http://localhost:5050/elmah.axd
I see my messages as type NotImplementedException.
Not very pretty but works.
Related
What I want to achieve is to show a custom exception Type and Error message in elmah.axd table but with the original stacktrace of a child throwed exception.
This is just an example of a nested try catch that match my needs:
// custom exception constructor
public MyCustomException(string customMsg, Exception expt):base(customMsg,expt)
// my test case
try{
try{
//_context.saveChanges(); --> this will generate an exception
// but for this example we'll throw the following
throw new IndexOutOfRangeException();
}
catch (Exception e){
// here elmah will print in the Type column "IndexOutOfrange" and in the Error column the message: "Index was outside the bounds of the array. Details..."
ErrorSignal.FromCurrentContext().Raise(e);
// now I throw a custom exception with the original stacktrace of "IndexOutOfrangeException"
throw new MyCustomException("Message to see in elmah 'Error' column", e)
}
}
catch(MyCustomException cex){
// here elmah will also print in the Type column "IndexOutOfrange" and in the Error column the message: "Index was outside the bounds of the array. Details..." with the original stacktrace
ErrorSignal.FromCurrentContext().Raise(cex)
// my expectation would be to print in the Type column "MyCustomException" and in the Error column the message: "Message to see in elmah 'Error' column Details..." with the original stacktrace
}
catch(Exception ex){
// some code here
}
Am I doing something wrong or it's just not possible what I want?
ELMAH always uses the base exception to generate the Type and Error fields. This is the best (IMO) way of doing it since the base exception will always be the original cause of the error. This explains why you get the type and message of the IndexOutOfRangeException logged in ELMAH.
There's a small "hack" to resolve this if you switch to using the Log method:
try{
try{
throw new IndexOutOfRangeException();
}
catch (Exception e){
throw new MyCustomException("Message to see in elmah 'Error' column", e)
}
}
catch(MyCustomException cex){
var error = new Elmah.Error(cex);
// Type and Error will now have the values of `IndexOutOfRangeException`
error.Type = cex.GetType().FullName;
error.Message = cex.Message;
// I manually updated the values from `MyCustomException`
ErrorLog.GetDefault(HttpContext.Current).Log(error);
}
catch(Exception ex){
// some code here
}
I tested this locally and both Type and Error get the value from the outer exception.
When the HttpClient throws an exception trying to get a page it returns a HttpRequestException. This exception doesn't really have anything to categorize the error apart from the message so the only way i can see to handle errors is like so:
try
{
HttpResponseMessage response = await client.GetAsync("http://www.example.com/");
// ...
}
catch (HttpRequestException e)
{
if(e.Message == "Name or service not known")
{
HandleNotKnown();
return;
}
if(e.Message == "Some other specific message")
{
HandleOtherError();
return;
}
// ... etc
}
I don't like doing this because I feel like at some point the error text could change in an update and break my code.
Is there a better way to handle specific errors with HttpClient?
The HttpRequestException inherits from Exception and so it has the InnerException property
Gets the Exception instance that caused the current exception.
So check this Exception for more details.
I have a method that provides an Exception object and I want to log an error if anything happens in the error handler itself. Here is some pseudocode:
public override void OnError(Exception originalException)
{
try
{
// Do work...
}
catch (Exception e)
{
// How do I create this exception without losing the stack
// trace of e and preserving any inner exceptions that were
// in e at the same time including the details of
// originalException?
Exception newException = new Exception(e.Message, originalException);
Logger.Error("An error occurred", newException);
}
}
Basically, I am trying to combine originalException and e above into one Exception message to pass to a logger object. I suppose one option would be to create 2 separate log messages but it's not ideal.
You could use an AggregateException to wrap multiple exceptions:
public override void OnError(Exception originalException)
{
try
{
// Do work...
}
catch (Exception e)
{
var exs = new AggregateException(originalException, e);
Logger.Error("An error occurred", exs);
}
}
EDIT: If Logger doesn't record contents of the InnerException property (or InnerExceptions in this case) then seems the only option is multiple calls to Logger.Error.
I have created few custom exception class
public class CreateNewUserWebException : Exception
{
public CreateNewUserWebException(string email): base(
string.Format("[{0}] - User could not be added.", email))
{
}
}
public class CreateNewUserEntityFrameworkException : System.Data.DataException
{
public CreateNewUserEntityFrameworkException(string email)
: base(
string.Format("[{0}] - User could not be added.", email))
{
}
}
and here is my controller code
try
{
var user = _createUserModule.CreateUser(model);
CookieManager.SetAuthenticationCookie(user, model.Email, rememberMe: false);
return RedirectToAction("Index", "Bugs");
}
catch (CreateNewUserEntityFrameworkException exception)
{
this.ModelState.AddModelError("", "Some error occured while registering you on our sytem. Please try again later.");
Elmah.ErrorSignal.FromCurrentContext().Raise(exception);
}
catch (CreateNewUserWebException exception)
{
this.ModelState.AddModelError("", "Some error occured while registering you on our sytem. Please try again later.");
Elmah.ErrorSignal.FromCurrentContext().Raise(exception);
}
catch(Exception exception)
{
this.ModelState.AddModelError("", "Some error occured while registering you on our sytem. Please try again later.");
Elmah.ErrorSignal.FromCurrentContext().Raise(exception);
}
I have purposely fully induced an primary key violation exception which is
but exception is not catched by my custom exception class. It is not caught by the last exception catch block.
I cannot understand why so. Can some one help me out on this please.
The part you've highlighted in the debugger is the inner exception. That isn't used by the CLR to determine which catch block to enter. The outer exception is just a DbUpdateException - which you haven't specified a particular catch block for.
Even the inner exception is just a DataException - it's not an instance of your custom exception.
You haven't shown any code which actually throws your exception - are you sure it's being used at all? What code have you written to tell EF to throw your exception rather than the exception it would otherwise throw?
(Given your comments, I'm not sure you quite understand exception handling. Creating a custom exception doesn't somehow let you catch an instance of that without it being thrown - something still has to throw an instance of that exception before it's any use.)
I have a member of a library being declared on the main page of my app:
private OpticalReaderLib.OpticalReaderTask _task = new OpticalReaderLib.OpticalReaderTask();
It works fine until I want to navigate back to this page at a different time. It brings up the error "An exception of type 'System.Exception' occurred in OpticalReaderLib.DLL but was not handled in user code".
Does anyone know why this is happening?
Thanks.
System.Exception is the base class for all Exceptions, so this is a very generic error message.
You could try logging more detail (e.g. exception.Message or exception.InnerException) about the exception that is thrown as part of your investigation. (via a try-catch statement).
It looks like you're initialising a field, where is this code being executed?
Update due to comment
As a temporary solution to discover the exception error.
private OpticalReaderLib.OpticalReaderTask _tempTask;
private OpticalReaderLib.OpticalReaderTask _task
{
get
{
//code to debug the error that is occuring
try
{
if (_tempTask == null)
_tempTask = new OpticalReaderLib.OpticalReaderTask();
else
return _tempTask;
}
catch (Exception exception)
{
//Log the exception detail here
}
}
}
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
if (_task != null)
{
_task.Completed -= OpticalReaderTask_Completed;
_task.Dispose();
_task = null;
}
base.OnBackKeyPress(e);
}