views:

736

answers:

8

What is a good error handling practice for an asp.net site? Examples? Thanks!

+3  A: 

One practice that I find to be especially useful is to create a generic error page, and then set your defaultRedirect on the customErrors node of the web.config to that error page.

Then setup your global.asax for logging all unhandled exceptions and then put them (the unhandled exceptions) in a static property on some class (I have a class called ErrorUtil with a static LastError property). Your error page can then look at this property to determine what to display to the user.

More details here: http://www.codeproject.com/KB/aspnet/JcGlobalErrorHandling.aspx

Max Schmeling
We do the same thing for all unhandled exceptions.
Esteban Araya
That sounds very thread-unsafe, of questionable value given HttpContext.Current.Server.GetLastError() and of course has the redirecting 200 codes problem in .NET2.0
annakata
It does sound very thread-unsafe, but I don't work with high enough traffic apps to worry about it. If you're working with higher traffic stuff it could be a problem.
Max Schmeling
+6  A: 

As with any dot net project I find the best way is to only catch specific error types if they are may to happen on the given page.

For example you could catch Format Exceptions for a users given input (just incase JavaScript validation fails and you have not use tryparse) but always leave the catching of the top level Exception to the global error handler.

     try
        {
            //Code that could error here
        }
        catch (FormatException ex)
        {
            //Code to tell user of their error
            //all other errors will be handled 
            //by the global error handler
        }

You can use the open source elmah (Error Logging Modules and Handlers) for ASP.Net to do this top level/global error catching for you if you want.

Using elmah it can create a log of errors that is viewable though a simple to configure web interface. You can also filter different types of errors and have custom error pages of your own for different error types.

John
A: 

Well, that's pretty wide open, which is completely cool. I'll refer you to a word .doc you can download from Dot Net Spider, which is actually the basis for my small company's code standard. The standard includes some very useful error handling tips.

One such example for exceptions (I don't recall if this is original to the document or if we added it to the doc): Never do a “catch exception and do nothing.” If you hide an exception, you will never know if the exception happened. You should always try to avoid exceptions by checking all the error conditions programmatically.

Example of what not to do:

try
{
   ...
}
catch{}

Very naughty unless you have a good reason for it.

MrBoJangles
A: 

You should make sure that you can catch most of the errors that are generated by your application and display a friendly message to the users. But of course you cannot catch all the errors for that you can use web.config and defaultRedirect by another user. Another very handy tool to log the errors is ELMAH. ELMAH will log all the errors generated by your application and show it to you in a very readable way. Plugging ELMAH in your application is as simple as adding few lines of code in web.config file and attaching the assembly. You should definitely give ELMAH a try it will literally save you hours and hours of pain.

http://code.google.com/p/elmah/

azamsharp
A: 
  1. Code defensively within each page for exceptions that you expect could happen and deal with them appropriately, so not to disrupt the user every time an exception occurs.

  2. Log all exceptions, with a reference.

  3. Provide a generic error page, for any unhandled exceptions, which provides a reference to use for support (support can identify details from logs). Don't display the actual exception, as most users will not understand it but is a potential security risk as it exposes information about your system (potentially passwords etc).

  4. Don't catch all exceptions and do nothing with them (as in the above answer). There is almost never a good reason to do this, occasionally you may want to catch a specific exception and not do any deliberately but this should be used wisely.

marcj
A: 

It is not always a good idea to redirect the user to a standard error page. If a user is working on a form, they may not want to be redirected away from the form they are working on. I put all code that could cause an exception inside a try/catch block, and inside the catch block I spit out an alert message alerting the user that an error has occurred as well as log the exception in a database including form input, query string, etc. I am developing an internal site, however, so most users just call me if they are having a problem. For a public site, you may wish to use something like elmah.

Chris Westbrook
A: 

Should I tryblock everything? Sometimes i dont want to catch anything specific, and an error will be catch by an method higher up in the hierarchy anyway.

If this is the main method, what is best practise of the sub method?


private void mainMethod()
{

  try
  {

     subMethod();
  }
  catch
  {
    //do something
  }
}


This:


private void subMethod()
{
  try{
   //code
   //code
  }
  catch
  {
    throw;
  }
}


Or this:


private void subMethod()
{
   //code
   //code
}


A: 
public string BookLesson(Customer_Info oCustomerInfo, CustLessonBook_Info oCustLessonBookInfo)
    {
        string authenticationID = string.Empty;
        int customerID = 0;
        string message = string.Empty;
        DA_Customer oDACustomer = new DA_Customer();

        using (TransactionScope scope = new TransactionScope())
        {
            if (oDACustomer.ValidateCustomerLoginName(oCustomerInfo.CustId, oCustomerInfo.CustLoginName) == "Y")
            {
                // if a new student
                if (oCustomerInfo.CustId == 0)
                {
                    oCustomerInfo.CustPassword = General.GeneratePassword(6, 8);
                    oCustomerInfo.CustPassword = new DA_InternalUser().GetPassword(oCustomerInfo.CustPassword, false);
                    authenticationID = oDACustomer.Register(oCustomerInfo, ref customerID);
                    oCustLessonBookInfo.CustId = customerID;
                }
                else // if existing student
                {
                    oCustomerInfo.UpdatedByCustomer = "Y";
                    authenticationID = oDACustomer.CustomerUpdateProfile(oCustomerInfo);
                }
                message = authenticationID;
                // insert lesson booking details
                new DA_Lesson().BookLesson(oCustLessonBookInfo);
            }

            else
            {
                message = "login exists";
            }
            scope.Complete();
            return message;
        }

    }
234234