Handling AggregateExceptions

I’ve written a couple of posts (see also) about how the AggregateException plays its part in exception handling in parallel systems. However, it has another trick up its sleeve when it comes to handling exceptions.

AggregateException has a Handle method that takes a delegate of Func<Exception, bool> i.e. It takes an Exception as a parameter and returns a bool. The return value indicates whether the function handled the exception or not.

Here is an example program that shows what how it works.

class Program
{
    static void Main(string[] args)
    {
        try
        {
            DoWork();
        }
        catch(AggregateException aex)
        {
            Console.WriteLine("Handle Remaining Exceptions");
            foreach(Exception ex in aex.InnerExceptions)
            {
                Console.WriteLine("{0}: {1}", ex.GetType().Name, ex.Message);
            }
        }

        Console.ReadLine();
    }

    private static void DoWork()
    {
        const int numTasks = 20;
        Task[] tasks = new Task[numTasks];
        for (int i = 0; i < numTasks; i++)
            tasks[i] = Task.Factory.StartNew(PerformTask);

        Thread.Sleep(2500);

        try
        {
            Task.WaitAll(tasks);
        }
        catch(AggregateException aex)
        {
            Console.WriteLine("AggregateException.Handle...");
            aex.Handle(ex => HandleException(ex));
            Console.WriteLine("Finished handling exceptions."); // This never shows
        }
    }

    public static bool HandleException(Exception ex)
    {
        if (ex is OddException)
        {
            Console.WriteLine("Handling: {0}", ex.Message);
            return true;
        }

        Console.WriteLine("Not handling: {0}", ex.Message);
        return false;
    }

    public static void PerformTask()
    {
        int? id = Task.CurrentId;
        Console.WriteLine("Performing Task {0}", id);

        if (id.Value % 13 == 0)
            throw new TriskaidekaException("Mwaaahaahaahaahaaaaaaaa!");

        if (id.Value % 2 == 1)
            throw new OddException("The task ("+id+") is distinctly odd.");
    }
}

The program starts 20 tasks (DoWork). Each task (PerformTask) simply outputs a line to the console to say what it’s id is and then throws an exception depending on some condition. There are two types of exception that it can throw.

Back in the main thread (DoWork) a Sleep statement gives the tasks a chance to get going (and hopefully complete). During this time, the tasks get the opportunity to output the following.

Performing Task 1
Performing Task 2
Performing Task 4
Performing Task 3
Performing Task 5
Performing Task 8
Performing Task 9
Performing Task 10
Performing Task 12
Performing Task 13
Performing Task 6
Performing Task 14
Performing Task 7
Performing Task 16
Performing Task 17
Performing Task 18
Performing Task 15
Performing Task 11
Performing Task 19
Performing Task 20

Then the Task.WaitAll statement is called which will potentially throw an AggregateException (in fact it will with 10 InnerExceptions).

Since the Task.WaitAll call is wrapped in a try/catch the AggregateException is caught. We output a message to say the exceptions are being handled. The AggregateException.Handle method calls the method given (HandleException) once for each of the InnerExceptions.

AggregateException.Handle...

The HandleException method either handles the exception (in which case it returns true) or it doesn’t (so returning false). In each case it also writes to the console to say what it has done. That console output looks like this:

Handling: The task (19) is distinctly odd.
Handling: The task (17) is distinctly odd.
Handling: The task (15) is distinctly odd.
Not handling: Mwaaahaahaahaahaaaaaaaa!
Handling: The task (11) is distinctly odd.
Handling: The task (9) is distinctly odd.
Handling: The task (7) is distinctly odd.
Handling: The task (5) is distinctly odd.
Handling: The task (3) is distinctly odd.
Handling: The task (1) is distinctly odd.

The AggregateException.Handle method then checks to see if any of the exceptions remain unhandled. If there are still unhandled exceptions then it rethrows. Since there is one remaining exception that is unhandled the line of code after the call to Handle is never called.

The try/catch block in the Main method catches AggregateException and just loops over the remaining exceptions to show what was left unhandled.

Handle Remaining Exceptions
TriskaidekaException: Mwaaahaahaahaahaaaaaaaa!

See also

Custom error pages and error handling in ASP.NET MVC 3

In ASP.NET MVC 3 a new bit of code appeared in the global.asax.cs file:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
}

The above method is called from the Application_Start() method.

Out of the box, what this does is set up a global filter for handling errors. You can still attribute controller methods or classes as before, but now, if you don’t have a specific HandleErrorAttribute attached to the controller method or class then the global one will take over and be processed.

However, you are not going to get custom errors just yet. If you have a bit of code that causes an exception to be thrown that is not caught then you will just end up with the Yellow Screen of Death as before. For example, this code:

public class HomeController : Controller
{
    // ...

    public ActionResult About()
    {
        throw new Exception("This is not good. Something bad happened.");
    }
}

Will produce this error

Error Handling - Without Custom Error

The missing part of the puzzle is to turn on Custom Errors. This happens in the web.config file. There are three basic options for the mode: “Off” which will show the YSOD to everyone, “RemoteOnly” which shows the YSOD on the local machine (the web server) and the custom error to everyone else, and “On” which shows the custom error to everyone including the local machine.

For development purposes I tend to leave it set to “RemoteOnly” so that I get the YSOD and I get to see what the error is, yet everyone else gets the custom error. However, for developing the actual custom errors themselves we’ll need to set the mode to “On” so we, as developers, get to see the error.

<system.web>
  <customErrors mode="On" defaultRedirect=”~/BadError.htm"/>
</system.web>

The defaultRedirect does not go to a controller action, it is set to a static HTML page that will be displayed if all else goes wrong. This is a final backstop to ensure that the user at least will see something nice event if the error page itself has some issues.

Normally, the error will show the ~/Views/Shared/Error.cshtml view. However, since the view can throw an exception itself there ought to be a backstop custom error page.

The HandleErrorAttribute defaults to using the view "Error" which will display shared view ~/Views/Shared/Error.cshtml.

You can change that by setting the view property on the HandleErrorAttrubute, like this:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute {View = "MyCustomError"});
}

I’ve set my error view to display the details of the exception for the purposes of this demo.

@model System.Web.Mvc.HandleErrorInfo

@{
    ViewBag.Title = "Error";
}

<h2>
    Sorry, an error occurred while processing your request.
</h2>
<p>Controller = @Model.ControllerName</p>
<p>Action = @Model.ActionName</p>
<p>Message = @Model.Exception.Message</p>
<p>StackTrace :</p>
<pre>@Model.Exception.StackTrace</pre>

NOTE: In normal production code you would never expose the details of the exception like this. It represents a considerable security risk and a potential attacker could use the information to gain valuable information about your system in order to construct an attack against it.

Now, if we re-run the same application and go to the About page (handled by the HomeController’s About action) then we will get our custom error page.

Performing additional actions on an exception

Overriding OnException in a Controller

If you want to perform additional actions, rather than just simply show a custom error page, then you can override the OnException method from the Controller class on your own controller derived class. If you want to do this for all controllers then  you may want to create a common base controller that all your controllers inherit from. For example:

public class CommonController : Controller
{
    protected override void OnException(ExceptionContext filterContext)
    {
        // Do additional things like logging here.
        base.OnException(filterContext);
    }
}

Then in each of your controllers, inherit from this common controller like this:

public class HomeController : CommonController
{ ...

That will ensure that all your controller have the same functionality.

Creating a FilterAttribute

You could alternatively create a FilterAttribute. This can provide benefits of providing global functionality if you add it to the global filter collection, or very fine grained functionality if you need it on a few sparse controller actions by adding it as an attribute on the controller action.

The filter may look like this:

public class LogExceptionFilterAttribute : FilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        // Log the exception here with your logging framework of choice.
    }
}

If you want to have the filter applied to all controller actions, you can set it up in the RegisterGlobalFilters method in the Global.asax.cs file like this:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new LogExceptionFilterAttribute());
    filters.Add(new HandleErrorAttribute());
}

Or, if you prefer to have finer grained control you can decorate individual controller classes or controller actions with it, like this:

[LogExceptionFilter()]
public ActionResult About()
{
    throw new Exception("This is not good. Something bad happened.");
}

Parallelisation in .NET 4.0 – Part 2 Throwing Exceptions

With more threads running simultaneously in an application there is increasing complexity when it comes to debugging. When exceptions are thrown you usually catch them somewhere and handle them. But what happens if you throw an exception inside a thread?

Naturally, if you can handle the exception within the thread then that makes life much easier. But what if an exception bubbles up and out into code that created the thread?

In the example in my previous post on Parallelisation in .NET 4.0 had the calls to a third party service happening in separate threads. So, what happens if somewhere in the call an exception is raised.

In the service call GetAvailability, I’ve simulated some error conditions to throw exceptions based on the input to illustrate the examples. This is what it looks like:

public HotelAvail GetAvailability(string hotelCode, DateTime startDate, int nights)
{
    // Throw some exceptions depending on the input.
    if (hotelCode == null)
        throw new ArgumentNullException("hotelCode");

    if ((hotelCode.Length > 10) || (hotelCode.Length == 0))
        throw new ArgumentOutOfRangeException(
            "Hotel Codes are 1 to 10 chars in length. Got code which was " +
            hotelCode.Length + " chars.");

    if (hotelCode.StartsWith("Z"))
        throw new AvailabilityException("Hotel code '" + hotelCode +
                                        "' does not exist"); // A custom exception type
    // ... etc. ...
}

The calling code, from the previous example, looks like this:

public IEnumerable<HotelAvail> GetAvailability(IEnumerable<string> codes,
        DateTime startDate, int numNights)
{
        return codes.AsParallel().Select(code =>
            new AvailService().GetAvailability(code, startDate, numNights))
            .ToList();
}

If we provide incorrect input into the service such that it causes exceptions to be raised then Visual Studio responds in the normal way by breaking the debugging session at the point closest to where the exception is thrown.

If we were to wrap the call to the service in a try catch block (as in the following code sample) then we’d except that Visual Studio wouldn’t break the debugging session as there is a handler (the catch block) for the exception.

public IEnumerable<HotelAvail> GetAvailabilityPlinqException(IEnumerable<string> codes,
        DateTime startDate, int numNights)
{
    try
    {
        return codes.AsParallel().Select(code =>
            new AvailService().GetAvailability(code, startDate, numNights))
            .ToList();
    }
    catch (Exception ex)
    {
        // Do stuff to handle the exception.
    }
    return null;
}

Normally, that would be the case, however if the handler is outside the thread that threw the exception, as in the above example, the situation is somewhat different. In this case the Exception Assistant will appear and highlight the exception (or the code nearest the exception if it can’t highlight the throw statement itself*)

AvailabilityException in Exception Assistant

This happens because the exception is not caught within the thread in which it was originally thrown.

The AggregateException

If you just tell the debugger to continue executing the application it will continue, but the code that created the threads will have to handle an AggregateException. This is a special exception class that contains an InnerExceptions (note the plural) property that contains all the exceptions thrown from each of the threads.

AggregateException.InnerExceptions

You can enumerate over each of the inner exceptions to find out what happened in each of the threads.

Be aware, however, that an Aggregate exception can, itself, contain an AggregateException. So simply calling InnerExceptions may yet yield another AggregateException. For example if the hierarchy of exceptions looks like this:

AggregateException Hierarchy

Then the results of iterating over the InnerExceptions will be:

foreach(Exception ex in aggregateException.InnerExceptions)
{
    // ... do stuff ...
}
  • AggregateException
  • ApplicationException

You can flatten the hierarchy into a single AggregateException object that doesn’t contain InnerExceptions with any additional AggregateException objects. To do this call Flatten() on the original AggregateException. This returns a new AggregateException which you can then call InnerExceptions on and not have to worry about any hierarchy.

For example:

foreach(Exception ex in aggregateException.Flatten().InnerExceptions)
{
    // ... do stuff ...
}

Which results in the following exceptions being enumerated by the loop:

  • ApplicationException
  • NullReferenceException
  • ArgumentException
  • DivideByZeroException

But it’s broken, why doesn’t it just stop?

Well, it does. Once a thread has thrown an exception that bubbles up and out then no new tasks are started, so no new threads are created, and no new work gets done. However, remember that there will be other threads running as well and if one breaks, maybe others will break too, or maybe they will complete successfully. We won’t know unless they are allowed to finish what they are doing.

Going back to the room availability example if the input hotel codes contain invalid codes then it will throw an exception that is not caught within the thread. What if a selection of good and bad hotel codes are passed:

1, 2, 3, Z123, 4, 5, 6, 1234567890ABC, 7, 8, 9

Of the above list “Z123” and “1234567890ABC” are both invalid and produce different exceptions. However, when running tests the AggregateException only contains one of the exceptions.

To show what happens, I’ve modified my “service” like this and run it through a console applications. Here’s the full code:

The service class

public class AvailService
{
    // ...

    public HotelAvail GetAvailability(string hotelCode, DateTime startDate, int nights)
    {
        Console.WriteLine("Start @ {0:HH-mm-ss.fff}: {1}", DateTime.Now, hotelCode);

        ValidateInput(hotelCode);

        // ... do stuff to process the request ...

        Console.WriteLine("  End @ {0:HH-mm-ss.fff}: {1}", DateTime.Now, hotelCode);
        return result;
    }

    private void ValidateInput(string hotelCode)
    {
        if (hotelCode == null)
        {
            Console.WriteLine("Error @ {0:HH-mm-ss.fff}: hotelCode is null", DateTime.Now);
            throw new ArgumentNullException("hotelCode");
        }

        if ((hotelCode.Length > 10) || (hotelCode.Length == 0))
        {
            Console.WriteLine("Error @ {0:HH-mm-ss.fff}: hotelCode is {1}", DateTime.Now, hotelCode);
            throw new ArgumentOutOfRangeException(
                "Hotel Codes are 1 to 10 chars in length. Got code which was " +
                hotelCode.Length + " chars.");
        }

        if (hotelCode.StartsWith("Z"))
        {
            Console.WriteLine("Error @ {0:HH-mm-ss.fff}: hotelCode is {1}", DateTime.Now, hotelCode);
            throw new AvailabilityException("Hotel code '" + hotelCode +
                                            "' does not exist");
        }
    }
}

The method on the controller class

public IEnumerable<HotelAvail> GetAvailability(IEnumerable<string> codes,
        DateTime startDate, int numNights)
{
    return codes.AsParallel().Select(code =>
        new AvailService().GetAvailability(code, startDate, numNights))
        .ToList();
}

The Main method on the Program class

static void Main(string[] args)
{
    string[] codes = "1,2,3,Z123,4,5,6,1234567890ABC,,7,8,9".Split(',');
    AvailController ctrl = new AvailController();

    DateTime start = DateTime.Now;
    try
    {
        var result = ctrl.GetAvailability(codes,
            DateTime.Today.AddDays(7.0), 2);
    }
    catch (AggregateException aex)
    {
        Console.WriteLine(aex.Message);

        foreach (Exception ex in aex.InnerExceptions)
            Console.WriteLine(" -- {0}", ex.Message);

    }
    finally
    {
        DateTime end = DateTime.Now;
        Console.WriteLine("Total time in ms: {0}",
                            (end - start).TotalMilliseconds);

    }
}

And the console output is:

Start @ 16-36-36.518: 7
Start @ 16-36-36.518: Z123
Start @ 16-36-36.518: 6
Start @ 16-36-36.518: 1
Error @ 16-36-36.526: hotelCode is Z123
  End @ 16-36-42.438: 1
  End @ 16-36-42.654: 6
  End @ 16-36-42.900: 7
One or more errors occurred.
 -- Hotel code 'Z123' does not exist
Total time in ms: 6400

As you can see only 4 items got started out of an initial input collection of 11 items. The error occurred 8ms after these items started. Those items that did not cause an error were allowed to continue to completion. The result variable in the Main method will never have anything because of the exception so we never get the results of the three items that did succeed.

Naturally, the best course of action is not to let the exception bubble up and out of the thread in which the code is executing.

 

 

* Note, there appears to be a bug in Visual Studio with the Exception Assistant not always highlighting the correct line of code.

The StackOverflowException

Take a look at the following code:

class Program
{
    static void Main(string[] args)
    {
        try
        {
            RecurseForever();
        }
        catch (StackOverflowException)
        {
            Console.WriteLine("Caught Stack Overflow Exception");
        }
        catch (Exception)
        {
            Console.WriteLine("Caught general Exception");
        }

        Console.ReadLine();
    }

    static void RecurseForever()
    {
        RecurseForever();
    }
}

What do you think the output of the program will be?

If you had asked me a few days ago I’d have said the output would be “Caught Stack Overflow Exception”, however that isn’t the case. If you run the code in the debugger this is what you actually get:

StackOverflowException

The exception simply isn’t caught.

If the application isn’t being debugged it will simply end at this point. It goes directly to jail. It does not pass GO. It does not collect £200.

ConsoleApplication2 has stopped working

The try-catch-ignore anti-pattern (again!)

I’ve blogged about this a few times, but today I just want to highlight the frustration this causes on fellow developers. Earlier today I saw a tweet from Chris Canal that said:

Are you swallowing exceptions there?! Hold on, let me get something to break your fingers with :|” [^]

All too often I’ve seen the just-ignore-it school of software development when it comes to error messages. It makes it very difficult to track down bugs.

If there is a valid reason for ignoring an exception then document it. State clearly in the comments exactly why you are ignoring the exception. Log the exception at the very least – I want to know when it happens, how often and why. I don’t like errors being swallowed up. I like to have them all fixed.

Incidentally, when I set up the development wiki in my company one of the first things was to put the quote on the front page “Always write software as if the person that will have to maintain it is an axe wielding maniac” – It is a very good rule to develop software by. I highly recommend it.

Throwing exceptions

When reviewing some code today I noticed some code that catches an exception, does something with it and then explicitly throws it again. The code looked something like this:

try
{
    // Do something that might cause an exception
}
catch (Exception ex)
{
    // Some stuff
    throw ex;
}

The problem with the above code is that when you throw the exception again the details about where the exception originated from are lost because the throw populates that part of the exception object. So the original details are replaced with the details about the current location in the code.

Consider the following program:

static void Main(string[] args)
{
    try
    {
        A();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        Console.WriteLine(ex.StackTrace);
    }
    Console.ReadLine();
}

private static void A()
{
    B();
}

private static void B()
{
    try
    {
        C();
    }
    catch (Exception ex)
    {
        // I can do something
        Console.WriteLine("Method C() catches the exception and partly handles it");
        Console.WriteLine();
        throw ex;
    }
}

private static void C()
{
    D();
}

private static void D()
{
    Exception ex = new Exception("This exception is thrown in D");
    throw ex;
}

The original exception is thrown by method D. The code in method B catches the exception and partly handles it, it then explicitly throws the original exception again. When the exception is finally caught in the Main method the call stack is truncated to method B. It can no longer see that method C and D were also called.

The output of the application is:

Method C() catches the exception and partly handles it

This exception is thrown in D
   at ConsoleApplication1.Program.B() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 40
   at ConsoleApplication1.Program.A() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 26
   at ConsoleApplication1.Program.Main(String[] args) in d:DevelopmentConsoleA
pplication1ConsoleApplication1Program.cs:line 14

As you can see, the stack trace only goes from the point of the second throw to the point that the exception is caught.

There are two correct solutions to this problem.

Solution 1: Wrapping the Exception

If you have additional information to add to the exception object you can create a brand new Exception and then put the original exception in as an inner exception like this:

try
{
    // Do something that might cause an exception
}
catch(Exception ex)
{
    // Some stuff
    Exception moreDetailedEx = new Exception("A message with more details", ex);
    throw moreDetailedEx;
}

NOTE: Please use a specific exception class and not Exception this makes catching specific types of exception easier and more efficient as the compiler can put in place some optimisations for you over you catching the base Exception class and examining it. I’m using Exception here simply to make the example easier to read.

So, if we change our program above to create a new exception and wrap the old one in it it will now look like this:

static void Main(string[] args)
{
    try
    {
        A();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.InnerException.Message);
        Console.WriteLine(ex.InnerException.StackTrace);
        Console.WriteLine();
        Console.WriteLine(ex.Message);
        Console.WriteLine(ex.StackTrace);
    }
    Console.ReadLine();
}

private static void A()
{
    B();
}

private static void B()
{
    try
    {
        C();
    }
    catch (Exception ex)
    {
        // I can do something
        Console.WriteLine("Method C() catches the exception and partly handles it");
        Console.WriteLine();
        Exception newEx = new Exception("This exception is thrown in B", ex);
        throw newEx;
    }
}

private static void C()
{
    D();
}

private static void D()
{
    Exception ex = new Exception("This exception is thrown in D");
    throw ex;
}

I’ve added some extra bits to the Main method to show the InnerException details too. The output of the program now looks like this:

Method C() catches the exception and partly handles it

This exception is thrown in D
   at ConsoleApplication1.Program.D() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 56
   at ConsoleApplication1.Program.C() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 50
   at ConsoleApplication1.Program.B() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 36

This exception is thrown in B
   at ConsoleApplication1.Program.B() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 44
   at ConsoleApplication1.Program.A() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 29
   at ConsoleApplication1.Program.Main(String[] args) in d:DevelopmentConsoleA
pplication1ConsoleApplication1Program.cs:line 14

As you can now see all the information is available. It can now be seen the patch from the final point the exception was caught to the point it was originally thrown.

Solution 2: Re-throwing the Exception

If you do not have any additional information to add to the exception you can simply use the throw keyword on its own and it will keep the existing exception object without altering it. For example:

try
{
    // Do something that might cause an exception
}
catch (Exception ex)
{
    // Some stuff
    throw;
}

Changing our program above to use the throw statement on its own will mean the program now looks like this:

static void Main(string[] args)
{
    try
    {
        A();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        Console.WriteLine(ex.StackTrace);
    }
    Console.ReadLine();
}

private static void A()
{
    B();
}

private static void B()
{
    try
    {
        C();
    }
    catch (Exception ex)
    {
        // I can do something
        Console.WriteLine("Method C() catches the exception and partly handles it");
        Console.WriteLine();
        throw;
    }
}

private static void C()
{
    D();
}

private static void D()
{
    Exception ex = new Exception("This exception is thrown in D");
    throw ex;
}

And the output now looks like this:

Method C() catches the exception and partly handles it

This exception is thrown in D
   at ConsoleApplication1.Program.D() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 52
   at ConsoleApplication1.Program.C() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 46
   at ConsoleApplication1.Program.B() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 40
   at ConsoleApplication1.Program.A() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 26
   at ConsoleApplication1.Program.Main(String[] args) in d:DevelopmentConsoleA
pplication1ConsoleApplication1Program.cs:line 14

As you can see the stack trace now shows you the entire route between the point the exception was caught and when it was thrown. We can also see from the message that the method C still caught and partly handled the exception.

Using the throw keyword like this actually translates to the CIL (MSIL) rethrow command. When you use throw with an Exception object it translates to the CIL throw command.

When the exception is thrown in D the CIL looks like this:

.method private hidebysig static void D() cil managed
{
    .maxstack 2
    .locals init (
        [0] class [mscorlib]System.Exception ex)
    L_0000: nop
    L_0001: ldstr "This exception is thrown in D"
    L_0006: newobj instance void [mscorlib]System.Exception::.ctor(string)
    L_000b: stloc.0
    L_000c: ldloc.0
    L_000d: throw
}

The key above is L_000d where it throws the exception.

Compare that to method B:

.method private hidebysig static void B() cil managed
{
    .maxstack 1
    .locals init (
        [0] class [mscorlib]System.Exception ex)
    L_0000: nop
    L_0001: nop
    L_0002: call void ConsoleApplication1.Program::C()
    L_0007: nop
    L_0008: nop
    L_0009: leave.s L_0020
    L_000b: stloc.0
    L_000c: nop
    L_000d: ldstr "Method C() catches the exception and partly handles it"
    L_0012: call void [mscorlib]System.Console::WriteLine(string)
    L_0017: nop
    L_0018: call void [mscorlib]System.Console::WriteLine()
    L_001d: nop
    L_001e: rethrow
    L_0020: nop
    L_0021: ret
    .try L_0001 to L_000b catch [mscorlib]System.Exception handler L_000b to L_0020
}

In the above CIL code the key is L_001e where it rethrows the exception. This is where the CIL is much more explicit than C#. In C# the throw keyword is overloaded and functions differently depending on whether it receives an exception object or not.

Crazy Extension Method

Here is an example of a crazy extension method that alters the semantics of method calling.

First the extension method:

public static class MyExtensions
{
    public static bool IsNullOrEmpty(this string target)
    {
        return string.IsNullOrEmpty(target);
    }
}

Instead of calling the static method IsNullOrEmpty() on string, we are turning it around to allow it to be called on a string type like an instance method. However, as you can probably tell, it may be called when the reference to the string is null. Normally this would result in an exception to say that you are attempting to call a method on a null value. However, this is an extension method and it actually works with nulls! This is probably not the best idea in the world, to be diplomatic about it.

Here is some calling code:

string a = null;
Console.WriteLine(a.IsNullOrEmpty());

Normally, an exception will be thrown if IsNullOrEmpty() is a real method. However, it isn’t in this case and the application happily writes “True” to the console.

 

What is a DAL (Part 4)

As has been mentioned previously, one of the purposes of the DAL is to shield that application from the database. That said, what happens if a DAL throws an exception? How should the application respond to it? In fact, how can it respond to an exception that it should not know about?

If something goes wrong with a query in the database an exception is thrown. If the database is SQL Server then a SqlException is thrown. If it isn’t SQL Server then some other exception is thrown. Or the DAL may be performing actions against a completely different type of data source such as an XML file, plain text file, web service or something completely different. If the application knows nothing about the back end database (data source) then how does it know which exception to respond to?

In short, it doesn’t. It can’t know which of the myriad of possible exceptions that could be thrown will be and how to respond to it. The calling code could just catch(Exception ex) but that is poor practice. It is always best to catch the most specific exception possible.

The answer is to create a specific exception that the DAL can use. A DalException that calling code can use. The original exception is still available as an InnerException on the DalException.

using System;
using System.Runtime.Serialization;

namespace Dal
{
    public class DalException : Exception
    {
        public DalException()
            : base()
        {
        }

        public DalException(string message)
            : base(message)
        {
        }

        public DalException(string message, Exception innerException)
            : base(message, innerException)
        {
        }

        public DalException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }
    }
}

The DAL will catch the original exception, create a new one based on the original and throw the new exception.

public DataSet GetPolicy(int policyId)
{
    try
    {
        SqlDataAdapter da =
            (SqlDataAdapter)this.BuildBasicQuery("GetPolicy");
        da.SelectCommand.Parameters.AddWithValue("@id", policyId);
        DataSet result = new DataSet();
        da.Fill(result);
        return result;
    }
    catch (SqlException sqlEx)
    {
        DalException dalEx = BuildDalEx(sqlEx);
        throw dalEx;
    }
}

The code for wrapping the original exception in the DAL Exception can be refactored in to a separate method so it can be used repeatedly. Depending on what it needs to do it may be possible to put that as a protected method on one of the abstract base classes

private DalException BuildDalEx(SqlException sqlEx)
{
    string message = string.Format("An exception occured in the Policy DALrn" +
        "Message: {0}", sqlEx.Message);
    DalException result = new DalException(message, sqlEx);
    return result;
}

Previous articles in the series:

 

 

Technorati Tags: , ,

 

Useless Error Message

Exception Processing Message 0xc0000013 Parameters 0x75BE023C 0x8343FCBC 0x75BE023C 0x75BE023C

Pointless error message

Well here’s a pointless error message from Microsoft Powerpoint 2007 running on Windows Vista.

What actually happened is that I picked from the list of recently opened files a presentation that was saved to a USB key which is no longer present. While the dialog title bar does give useful information to the user, the main message is filled with useless rubbish as far as a user is concerned.

Pressing cancel doesn’t immediately help – It just repeats the message. You have to click cancel a fair few times before it eventually tells you something useful – Such as it can’t actually find the file with the given path name.

Why wasn’t the user told immediately that it couldn’t locate the file instead of being presented with a bunch of hex?

Tags:

Friendly Error Messages (or not)

Microsoft are normally quite good at producing friendly error messages when things don’t work out. However today I rebooted my machine after installing security updates, I fired up Visual Studio and then attempted to open the solution I was working on. Visual Studio then complained that IIS wasn’t running ASP.NET 1.1. So I went to IIS to check that it hadn’t reset my default website to ASP.NET 2.0, but it had. I changed it over to ASP.NET 1.1 and attempted to open my solution again. Same error message.

Curious I went back to the IIS admin tool and expanded the tree further to see if the Virtual Directory needed changing too. However, I then saw that IIS was stopped, so I attempted to restart it. Nope. Nada. It reported “Unexpected error 0x8ffe2740″. What the heck is error 0x8ffe2740?!

A quick Google found me a forum that discussed this and told me that it was because something else was listening on port 80, the default HTTP port. So, why didn’t the error message tell me this. Why the cryptic hex value?

Anyway, once I knew something else was using the port, I needed to find out what. I have a very useful piece of freeware called TCPView from Sysinternals and it is quite interesting to see all the processes with an open network connection. I quickly found the offending application (Skype, if you are curious) and closed it down.

NOTE: This was rescued from the Google Cahe. The original date was Monday, 17th January 2005.

Tags:


Original comments:

If you want to keep using Skype, go to File > Options > Connection tab and uncheck ‘Use port 80 as an alternative for incoming connections’.

1/18/2005 4:16 PM | Mike Dimmick
Follow

Get every new post delivered to your Inbox.