Exception Handling in ASP.NET (C#) from a separate class file - c#

I am writing an ASP.NET application in C# and I am working on handling possible exceptions that may be thrown from another file. I have a C# class file that I wrote containing methods that execute SQL commands, and I want to protect against possible exceptions being thrown once my application goes into production.
This is the SQL method I wrote that I am intentionally throwing an error in (From SqlData.cs):
public SqlConnection openConnection()
{
//Create an SQL connection
SqlConnection myConnection = new SqlConnection("My intentionally incorrect connection string");
//Open the connection
try
{
myConnection.Open();
}
catch (SqlException myAppEx)
{
throw new ApplicationException("There was an error opening the SQL database connection", myAppEx);
}
return myConnection;
}
I call this method from my Default.aspx.cs file with the following lines of code:
try
{
//The ReadDT method calls openConnection() in itself
dt = sqlData.ReadDT(query);
}
catch (ApplicationException exc)
{
throw exc;
}
I am trying to implement Page level exception handling, where if an exception is raised on the current page the Page_Error method is supposed to be called, as cited here. This is why I catch the exception that was thrown from my SqlData.cs class file, and re-throw the exception, so that this exception is seen by the server. Hence, Server.GetLastError() will not return null.
As implemented here, I have a separate error page that displays all of the information on the exception. My Page_Error method is as follows:
private void Page_Error(object sender, EventArgs e)
{
Server.Transfer("ErrorPage.aspx?handler=Page_Error%20-%20Default.aspx", true);
}
From here the user is redirected to my ErrorPage.aspx and the SqlException that was originally thrown is displayed perfectly.
The problem - When I catch the exception from the SqlData.cs, and re-throw the exception, an UnhandledException is raised. if I do not put a try catch block around the ReadDT method call, the same UnhandledException is raised from my SqlData.cs file.
Code trace:
throw new ApplicationException("There was an error opening the SQL database connection", myAppEx); (This works correctly)
The exception is then caught and re-thrown (UnhandledException occurs)
The Page_Error method is called as it should be and everything executes properly!
I hope I have been clear in answering myself, I have done a lot of research on exceptions and my particular problem and I have not had any success in finding an answer.
Thanks,
Eric

In ASP.NET, unhandled exceptions thrown by your application will be wrapped in an HttpUnhandledException before calling the Page or Global error handler. You need to look at its InnerException property to get at the original exception.
In general, you shouldn't bother wrapping and rethrowing exceptions like you're doing unless you're adding value (for example, additional data regarding the context of the exception). Just let them propagage to wherever they're eventually handled (Page_Error in your case, though you might consider using Application_Error in global.asax.cs, to avoid repeating this error handling code on every page).

So I came up with a combination of error handling through Code Level exception handling, and redirecting the user to an error page, then logging the error with ELMAH, to solve my problem.
I now handle all exception's directly in my SqlData class file, for the least yet most efficient code. I have a global variable HttpResponse response in my SqlData class file, that I populate each time I create a new instance of the class from within my ASP.NET application. So from my Main.aspx.cs file I have something like:
private SQLData data;
protected void Page_Load(object sender, EventArgs e)
{
data = new SQLData(Response);
...
}
If I do this I am able to call a response.Redirect() from my class file to send the user to my error page, I pass the exception error message and type of exception in a query string, to which I then print out to the user in my error page. This allows me to display only non-sensitive information to the user. Therefore the exception has been handled and ELMAH has logged all of the specifics!
//Create an SQL connection
SqlConnection myConnection = new SqlConnection("MyConnString");
//Open the connection
try
{
myConnection.Open();
}
catch (Exception ex)
{
//Manually log the exception in ELMAH
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
//Redirect the user to the error page
response.Redirect("ErrorPage.aspx?ErrorMessage=" + ex.Message + "&ErrorType=SQLException", true);
}
return myConnection;
I then have a link display at the bottom of my error page directing to the elamh.axd page only if you are an administrator. From this page you may view the stack trace and other sensitive information.
You can find information on ELMAH at the bottom of this page as well as setting up ELMAH in an ASP.NET application. It is very easy to do, and a very powerful tool.
Cheers,
Eric

Related

Should we put try catch with function if we just want to log the exception?

In asp.net application, all the exception that occurs and are not inside try catch can be handled by application_error.
If we just need to log the exception along with its stack trace, and we need not make any other decision/logic inside catch, why should we put try catch at application/bl or dal layer functions? Is there any reason to put try/catch with every database call function?
For example we have hundreds of function in DAL layer that executes following code:
try
{
//open db connection, execute stored procedure
}
catch
{
//log error
}
In case we get any exception from stored procedure OR in opening database connection, we get an exception but we are not doing anything except for logging these errors. We don't have very critical data-storage/retrieval requirement. We are logging error just to be alerted and fix it later. Is this correct to put catch in every such function?
Using try and catch is not for logging purposes only, especially when dealing with database connections.
An exception means that something wasn't completed. If something wasn't completed, your business process failed. If your business process failed, you need to know about it and handle it within the scope of that code, not application_error. Each error should be handled within the scope it was generated from. application_error should be your last fallback, and theoretically should never be reached.
Sure, you can use it for logging, but also for closing your DB connection (which was probably opened before the exception occurred and be left forever open), informing your users that an exception occured, and for data recovery, alternating your process to deal with the exception or preparing it for a retry.
So, taking your posted template, good code handling should look like this:
try
{
//open db connection, execute stored procedure
}
catch
{
// Inform the user
// Alternate your process or preparing for retry
// log error
}
finally
{
// Close the DB connection
}
One should use try/catch blocks only in places where you can meaningfully handle an exception. However, "meaningful handling " includes providing good error messages.
If your catch block simply logs the exception with no additional context, then such block could be replaced with a top-level handler (like application_error) that does the same thing.
If, however, you log additional information available only at the point of invocation, then having a catch block is entirely justified: it enhances the experience by providing better diagnostics, which is a perfectly legitimate goal.

handling errors outside of exceptions

I setup an exception handling class to log errors to the database which works really well but I was wondering if I can also somehow setup the application so any error outside of a try catch will call the same procedure somehow?
It works well most of the time and shows a screen with an error code to the user but I want to be able to use this friendly error screen each time but on the odd occasion an error outside of the try catch is thrown and it shows the normal asp.net error.
The catch I use:
catch (SqlException ex)
{
ExceptionHandling.SQLException(ex, constPageID, constIsSiteSpecific);
}
It is possible to use the Global.asax's Application_Error method.
protected void Application_Error()
{
Exception exception = Server.GetLastError();//Get the Last Error
LogException(exception);//Custom Code
}
However be aware that if you do any error a user suffers will direct them onto your error page. It's often better to handle smaller errors on the page itself and present a simple message.
There are countless discussions on proper error handling - personally I like to catch everything the UI method which called it (OnPreRender, OnLoad OnEvent etc).
If you are developing an ASP.NET application, you can log unhandled exceptions in Global.asax in "Application_Error" method.
protected void Application_Error()
{
Exception exception = Server.GetLastError();
// Clear the error
Server.ClearError();
// Log exception
}

How can I handle the exception which throws on an external dll?

I have developed a project which uses an external dll as FTPServer, I have created the FTP Server on my project like this:
private ClsFTPServer _ClsFTPServer;
_ClsFTPServer = new ClsFTPServer(FTPUserName, FTPPassword, FTPPath);
The Code above creates an instance of FTP server class, the class starts the FTPserver on it's constructor, it works fine independently as a module while the clients send their request correctly, but when an incorrect request comes to FTP server it throws an exception and cause my application to crash.
How can I handle the exception thrown by the external dll to prevent my application from crashing?
I recently answered a similar (ish) question which may prove useful -
Catch completely unexpected error
EDIT. I have to agree with Hans' comment above - might be an idea to find another FTP server.
Just for completeness, here's the appdomain/thread exception setup from - http://msdn.microsoft.com/en-GB/library/system.windows.forms.application.threadexception.aspx
Application.ThreadException += new ThreadExceptionEventHandler (ErrorHandlerForm.Form1_UIThreadException);
// Set the unhandled exception mode to force all Windows Forms errors to go through
// our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// Add the event handler for handling non-UI thread exceptions to the event.
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
In case of using external unmanaged\unsafe code, .NET (above .net 4) by default cannot handle Memory Access Violation exceptions that happens inside of dll code.
in order to catch these kind of exceptions, there is three things to do. I did them and it worked for me:
Add these Attributes to the method that exception occurred inside of it :
(the method that calls the method of the unmanaged code.)
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
Add this tag to App.Config file below runtime tag :
<runtime>
<legacyCorruptedStateExceptionsPolicy enabled="true"/>
<!-- other tags -->
</runtime>
Catch these kind of exception by using System.AccessViolationException exception type :
try{
//Method call that cause Memory Access violation Exeption
}
catch (System.AccessViolationException exception)
{
//Handle the exception here
}
What i said is just the cure for these type of exception. for more information about this exception's ego and how this approach works, see System.AccessViolationException
You've probably already tried this, but just in case, have you tried wrapping it in a try catch?
try
{
_ClsFTPServer = new ClsFTPServer(FTPUserName, FTPPassword, FTPPath);
...
}
catch(Exception e)
{
...
}
By putting a try...catch block around every call into the object and its methods.
Something like:
try
{
// use the DLL in some way
}
catch (Exception e)
{
// Handle the exception, maybe display a warning, log an event, etc.)
}
Also note that while running under Visual Studio, if you go to the "Debug" menu and select "Exceptions..." it will allow the debugger to break on ALL exceptions if you start your program under the debugger, and not just unhandled exceptions. Just click the 'Thrown' checkbox next to "Common Language Runtime Exceptions".

How to get Type of Exception in C#

I want to check if the server is not accessible and if its not accessible i want to print a friendly message on my login page. Like when user input its credential and in exception i got
A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)
this exception. So how should i when which exception is occurred so i can display a message?
I know this is an older post, but if you are going to handle all exceptions the same way and/or are using the information for error reports or something similar (instead of notifying the user of the specifics) you can use the following.
try
{
//do something here
}
catch(Exception ex)
{
MessageBox.Show(ex.GetType().ToString()); //will print System.NullReferenceException for example
}
You need to know at code-time what exceptions to expect, in order to catch them accordingly. As Dimitrov stated, a SQLException is thrown when the connection to an SQL server fails, so catching that specifically is a good tactic.
You want to catch the various exceptions in order, like so:
try
{
//some code
}
catch(TypeOfException exOne)
{
//handle TypeOfException someway
}
catch (OtherTypeOfException exTwo)
{
//handle OtherTypeOfException some other way
}
catch (Exception ex)
{
//handle unknown exceptions in a general way
}
finally
{
//any required cleanup code goes here
}
Try to put the most unusual exceptions at the top, working your way down the list towards more common ones. The catch sequence is sequential - if you put catch(Exception) at the top, it will always catch on that line no matter what exceptions you code for beneath it.
You could try catching a SQLException:
try
{
// Try sending a sample SQL query
}
catch (SQLException ex)
{
// Print error message
}
you can use the same method that you use to check whether a parent class is of type subclass which is done using
obj is NotImplementedException
where your obj is of type Exception the parent class of all exceptions.
or if you want to use the exception object later then you can use:
var niException=obj as NotImplementedException
if(niException==null) //will be null when object is not of type NotImplementedException
return;
This logic is especially useful when you have a centralised class for handling exceptions and dont want to add multiple catch statements
Hope this helps.
try {
//some code } catch(TypeOfException exOne) {
//handle TypeOfException someway } catch (OtherTypeOfException exTwo) {
//handle OtherTypeOfException some other way } catch (Exception ex) {
//handle unknown exceptions in a general way } finally {
//any required cleanup code goes here }
try/finally and using are almost the same. using will try to do something with the object, whether it succeeds or not it will dispose of the object to stop memory leaking, but will not ignore the error preventing the code from continuing.
Try will try to perform the code inside the braces, if an error occurs it will ignore the error and exit the Try clause, then proceed on reading code, unless the error is critical which causes the program to crash. However when using streams it wont ensure the stream is closed/ dispose of, because when an error occurs it exits the try clause before reaching any code you might of added at the bottom for disposing (bad practice imo).
Try code requires either a Catch(s), and/or Finally statment. Catch gives you the opportunity to handle exceptions, generally or specific exceptions. an example of use could be, to generate a textfile of the error and save it. using wouldn't let you handle exceptions.
another example of using could be, you have a playlist, a song cant be found, the exception area nullreferece might remove the item from the list.
Finally is always executed, even if the error is critical and the program crashes, the code inside the finally clause will be executed, with stream objects this is where you should be placing your dispose code, so that if the object fails in the try clause its always disposed of.
hope i've helped present some clarity regarding using and try/catch/finally.
You have to catch the exception:
try
{
//Contact the server
}
catch(YourCouldNotContactServerException)
{
//Show some friendly message
}
try
{
// Your code
}
catch (SQLException ex)
{
Response.Write(ex.Message); // For web apps
Console.WriteLine(ex.Message); // For Windows apps
}
I think, the solution is:
catch (Exception ex)
{
Responce.Write("An error occured: " + ex.Message);
}

Easy way to catch all unhandled exceptions in C#.NET

I have a website built in C#.NET that tends to produce a fairly steady stream of SQL timeouts from various user controls and I want to easily pop some code in to catch all unhandled exceptions and send them to something that can log them and display a friendly message to the user.
How do I, through minimal effort, catch all unhandled exceptions?
this question seems to say it's impossible, but that doesn't make sense to me (and it's about .NET 1.1 in windows apps):
All unhandled exceptions finally passed through Application_Error in global.asax. So, to give general exception message or do logging operations, see Application_Error.
If you need to catch exeptions in all threads the best aproach is to implement UnhandledExceptionModule and add it to you application look here
for an example
Use the Application_Error method in your Global.asax file. Inside your Application_Error method implementation call Server.GetLastError(), log the details of the exception returned by Server.GetLastError() however you wish.
e.g.
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
log4net.ILog log = log4net.LogManager.GetLogger(typeof(object));
using (log4net.NDC.Push(this.User.Identity.Name))
{
log.Fatal("Unhandled Exception", Server.GetLastError());
}
}
Don't pay too much attention to the log4net stuff, Server.GetLastError() is the most useful bit, log the details however you prefer.
The ELMAH project sounds worth a try, its list of features include:
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.
Logging of nearly all unhandled exceptions.
A web page to remotely view the entire log of recoded exceptions.
A web page to remotely view the full details of any one logged
exception.
In many cases, you can review the original yellow screen of death that
ASP.NET generated for a given
exception, even with customErrors mode
turned off.
An e-mail notification of each error at the time it occurs.
An RSS feed of the last 15 errors from the log.
A number of backing storage implementations for the log
More on using ELMAH from dotnetslackers
You can subscribe to the AppDomain.CurrentDomain.UnhandledException event.
It's probably important to note that you are not supposed to catch unhandled exceptions. If you are having SQL timeout issues, you should specifically catch those.
Do you mean handling it in all threads, including ones created by third-party code? Within "known" threads just catch Exception at the top of the stack.
I'd recommend looking at log4net and seeing if that's suitable for the logging part of the question.
If using .net 2.0 framework, I use the built in Health Monitoring services. There's a nice article describing this method here: https://web.archive.org/web/20210305134220/https://aspnet.4guysfromrolla.com/articles/031407-1.aspx
If you're stuck with the 1.0 framework, I would use ELMAH:
http://msdn.microsoft.com/en-us/library/aa479332.aspx
hope this helps
There are 2 parts to this problem handling & identifying.
Identifying
This is what you do when the exception is finally caught, not necessarily where it is thrown. So the exception at that stage must have enough context information for you to idenitfy what the problem was
Handling
For handling, you can
a) add a HttpModeule. See
http://www.eggheadcafe.com/articles/20060305.asp
I would suggest this approach only when there is absolutely no context informaatn available and there might be issuus wiih IIS/aspnet, In short for catastrophic situations
b) Create a abstract class called AbstractBasePage which derives from Page class and have all your codebehind classes derive from AbstractBasePage
The AbstractBasePage can implement that Page.Error delegate so that all exceptions which percolate up through the n-tier architecture can be caught here(and possibly logged)
I would suggest this cause for the kind of exceptions you are talking about (SQlException) there is enough context information for you to identify that it was a timeout and take possible action. This action might include redirecting user to a custom error page with appropriate message for each different kind of exception (Sql, webservice, async call timeouts etc).
Thanks
RVZ
One short answer is to use (Anonymous) delegate methods with common handling code when the delegate is invoked.
Background: If you have targeted the weak points, or have some boilerplate error handling code you need to universally apply to a particular class of problem, and you don't want to write the same try..catch for every invocation location, (such as updating a specific control on every page, etc).
Case study: A pain point is web forms and saving data to the database. We have a control that displays the saved status to the user, and we wanted to have common error handling code as well as common display without copy-pasting-reuse in every page. Also, each page did it's own thing in it's own way, so the only really common part of the code was the error handling and display.
Now, before being slammed, this is no replacement for a data-access layer and data access code. That's all still assumed to exist, good n-tier separation, etc. This code is UI-layer specific to allow us to write clean UI code and not repeat ourselves. We're big believers in not quashing exceptions, but certain exceptions shouldn't necessitate the user getting a generic error page and losing their work. There will be sql timeouts, servers go down, deadlocks, etc.
A Solution: The way we did it was to pass an anonymous delegate to a method on a custom control and essentially inject the try block using anonymous delegates.
// normal form code.
private void Save()
{
// you can do stuff before and after. normal scoping rules apply
saveControl.InvokeSave(
delegate
{
// everywhere the save control is used, this code is different
// but the class of errors and the stage we are catching them at
// is the same
DataContext.SomeStoredProcedure();
DataContext.SomeOtherStoredProcedure();
DataContext.SubmitChanges();
});
}
The SaveControl itself has the method like:
public delegate void SaveControlDelegate();
public void InvokeSave(SaveControlDelegate saveControlDelegate)
{
// I've changed the code from our code.
// You'll have to make up your own logic.
// this just gives an idea of common handling.
retryButton.Visible = false;
try
{
saveControlDelegate.Invoke();
}
catch (SqlTimeoutException ex)
{
// perform other logic here.
statusLabel.Text = "The server took too long to respond.";
retryButton.Visible = true;
LogSqlTimeoutOnSave(ex);
}
// catch other exceptions as necessary. i.e.
// detect deadlocks
catch (Exception ex)
{
statusLabel.Text = "An unknown Error occurred";
LogGenericExceptionOnSave(ex);
}
SetSavedStatus();
}
There are other ways to achieve this (e.g. common base class, intefaces), but in our case this had the best fit.
This isn't a replacement to a great tool such as Elmah for logging all unhandled exceptions. This is a targeted approach to handling certain exceptions in a standard manner.
Timeout errors typically occur if you are not forcefully closing your sqlconnections.
so if you had a
try {
conn.Open();
cmd.ExecuteReader();
conn.Close();
} catch (SqlException ex) {
//do whatever
}
If anything goes wrong with that ExecuteReader your connection will not be closed. Always add a finally block.
try {
conn.Open();
cmd.ExecuteReader();
conn.Close();
} catch (SqlException ex) {
//do whatever
} finally {
if(conn.State != ConnectionState.Closed)
conn.Close();
}
This is old question, but the best method (for me) is not listed here. So here we are:
ExceptionFilterAttribute is nice and easy solution for me. Source: http://weblogs.asp.net/fredriknormen/asp-net-web-api-exception-handling.
public class ExceptionHandlingAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
var exception = context.Exception;
if(exception is SqlTimeoutException)
{
//do some handling for this type of exception
}
}
}
And attach it to f.e. HomeController:
[ExceptionHandling]
public class HomeController: Controller
{
}

Categories

Resources