I don't know what we can do with a custom exception, what we can't do with a built-in one. It seems a naive question but I really have no idea about that.
What do you think?
The reason for the different types of exceptions is to allow you to be able to catch just the ones you want with your handlers, letting the others go on up the stack. So you can arrange to catch exceptions for certain, occasionally-expected situations just by the type of the exception.
You may not need to create your own very often at all, actually. But if you do, it would be because you need to be able to throw and capture an exception type more specific than what is available, and perhaps with additional information attached.
It is useful to create a custom exception if:
There is no built-in exception that expresses the type of error condition you have.
You want to catch only that specific type of exception and not exceptions coming from the framework.
But usually if there already is an exception in the framework that you could use then it is better to use it instead of creating your own exception for the same thing.
You could use it for implementing special error handling for things related to your application. Suppose you build a banana application, then you could have an OutOfBananasException. If your application gets out of bananas you can throw the exception and catch it later on with special error handling.
try
{
EatBananas();
}
catch(OutOfBananasException oobe)
{
GetMoreBananas();
}
catch(Exception e)
{
TellUserAndAbort();
}
Edit:
The reason to use your own Exceptions instead of the built in is to make it clear to everyone reading you code or using your library what type of error has occurred. You should only create your own exceptions when you can not find any suitable built in exception.
Edit2:
One thing you can do with your own exceptions that you can not do with built in is to add properties describing things about the error condition that the error handler might use. If you have an exception relating to customers you exception could have properties for customer name and customer id and thus make it possible for the error handler to display informative error messages to the user.
There's only a few exceptions in .NET that are treated in a special manner, like ThreadAbortException, which can't (normally) be caught and handled and swallowed.
Other than that, exception types are just exception types. You can do pretty much the same with your own exceptions that you can do with the ones defined in the framework.
The benefits of custom exceptions have been outlined here, but before you create your own make sure the BCL doesn't already have one fitting your needs:
http://mikevallotton.wordpress.com/2009/07/08/net-exceptions-all-of-them/
(There's 141 of them!)
One annoyance with the built-in exceptions is that there is no systematic distinction made between exceptions that indicate that
an operation failed but a retry might succeed; the system state is as it was before the operation was attempted.
an operation failed, and a retry isn't likely to help; nonetheless, the system state is as it was before the operation was attempted;
an operation has failed in such a way as to potentially corrupt something else.
It may be useful to catch exceptions and rethrow one of three custom exceptions (meanings defined above) based upon where the exception was caught. When the exception is rethrown, pass the original exception as the InnerException parameter.
Incidentally, it's possible to define generic exceptions. I'm not quite sure of the pros and cons of doing so, and I've never seen anyone else do it. One could define e.g. a TransientFaultException(of T) which inherits from a (custom) TransientFaultException; an application which catches a TimeoutException could rethrow as a TransientFaultException(of TimeOutException) and have it caught as either a TransientFaultException(of TimeoutException) or a TransientFaultException. Unfortunately, one would have to know the type of the exception to be taught to create the proper generic. If one were to catch an Exception and pass it to a factory method for TransientFaultException, the new exception would be of type TransientFaultException(of Exception), regardless of what type of exception was originally thrown.
Custom exceptions allow you to do 2 things:
Capture custom typed-data in the exception
Capture a custom exception occurrence
You should only create a custom exception when there isn't a built in exception to handle as necessary.
As an example, in our application we have DataLayerException which is thrown when the datalayer encounters an error (and includes the specific DBMS exception as an inner exception).
We also have DataLayerSingleResultNoneException - which is when we expect a single result back but there is no result, and DataLayerSingleResultManyException which is when we expect a single result but get many back. This allows us to catch the different problems an action them accordingly.
Related
When to examine the InnerException property of the Exception class and its derivatives? Microsoft's "Best practices for exceptions" doesn't provide any advise on when to examine for inner exceptions. Should I do it only when exceptions are rethrown and caught in my code? Should I do it always, even when I enclose in try-catch block standard functions like System.IO.File.Move?
Who might use such a feature?
Sometimes, developers convert one exception (typically one definied by Microsoft) into another exception (typically an exception defined on their own).
This can make an API simpler, e.g. as in the example you have given with File.Move(). Instead of the 7 possible Microsoft exceptions, such an API could just throw a simple "That didn't work" exception with details inside, so your code only needs to handle one type of exception.
When to use it?
I would look into them during the development phase when using the 3rd party framework. If they tend to be empty, there's no value in writing code for it.
If you write a logger / tracer or generic debug output, I would definitely consider it.
Exceptions I know that have InnerExceptions:
TargetInvocationException
AggregateException
Ultmately the answer here is simply: whenever it is useful for you to do so, which is entirely contextual. For the vast majority of cases, it isn't actually worth checking much on the exception at all - other than reporting it; just "do the thing, oops, failed" - you should usually have more using and finally than catch, IMO - because usually there isn't anything useful you can do with an exception except bubble it upwards.
However, in some cases, there is useful context. Classic examples would be AggregateException, TargetInvocationException and TypeInitializationException or anything coming from XmlSerializer. Those are pretty rare, so you wouldn't want to start checking for them explicitly unless you have very good reason to expect them. In terms of your general error reporting code: yes it makes sense to log the inner exceptions, but .ToString() usually does that automatically, IIRC.
As an example from some real code involving InnerException - there is a scenario in my network code where I don't care about a very specific situation only detectable via the combination of outer and inner exception; when does this job for me:
try
{
await _server.RunClientAsync(connection.Transport).ConfigureAwait(false);
}
catch (IOException io) when (io.InnerException is UvException uv && uv.StatusCode == -4077)
{ } //swallow libuv disconnect
(everything other than that scenario is bubbled)
First, I'm already familiar with the simple exception handling syntax but I'm asking about the best place, the best time and the best way to deal with them.
I'm building an N-Layered application. so I think the DAL will sometime generate some errors to handle .. and I just learned about the SqlException class, what's the deal with that class ? I once saw a code that handles the SqlException then it handles Exception!
After knowing the practice and where I'm going to handle them, I'm planning to create a method to connect to the database and log the errors in a database so I could fix it but still I don't know what information should I collect to allow me identify the whole situation!
I thought exceptions handling was not a big deal. but every now and then I read some strange advices -that I never understood- on the questions comments but no one could answer me since it was some very old questions!
"Don't just explicitly catch
exceptions"
"the code that is used by
higher-layers in your application must
always only throw exceptions and never
worry about how to deal with them."
EDIT
What about Page_Error event and Application_Error .. I saw that they are a good practice for handling errors
Exception handling is a big deal, and it's not simple to design a good strategy for that.
First of all, some general rules:
Exceptions occur when the running code is completely unable to go ahead, so maybe it tried to handle some internal exceptions but ultimately failed. Think about TCP connection: if a damaged packet arrives, it's an exception, but TCP protocol can handle it. If too many are damaged, an I/O or socket exception is thrown
Exceptions can not always be handled. In almost all cases, when you get an exception from underlying layers you are unable to run corrective code. If your application depends on a DB and that is offline, when you get the exception about it you can only display an error message
Exceptions can be unexpected, and can reveal design or implementation flaws. For example, an implementation flaw can be the situation in which you have a redundant DB but when you fail to connect to frist mirror you don't try with the second
For the third point, it's important to log exceptions and periodically analyse logs to find any weird situation. So, let's begin with the concrete answer.
First of all
think about "handling" the exception. When you write every single code line, think about the possible problems that may prevent it from completing, and think about the possible corrective actions. if any are possible. An error message is not a good handling way, it's the latest strategy.
Don't start to write try-catch(Exception), but prefer specific exceptions. If you need to parse strings to numbers etc, then expect FormatException, if you need to cast from Object to your type expect InvalidCastException
When you write lower-level layers
don't hesitate to throw exceptions!! Don't do like many folks do, ie. return null or use (like ANSI C) a boolean return value and reference parameters. Exceptions are there for that. If you can handle an exception (ie. you don't find a local file but you know you have a remote backup, so handle FileNotFoundException by calling the remote mirror, but if you can't still connect then ultimately throw) then do it and try to resume computation, but if you cannot then throw. And don't forget to throw the inner exception, if present, because it is helpful for logging in the highest layer.
Basically, you can still decide to throw an exception on your own even if you don't catch any! And this is highly recommended especially when function parameters are invalid!
Another good option is to still log in the underlying layers. You actually want to log no matter an exception occurs.
When you log
remember to give an adequate severity to the messages. If you find via code that your DB is offline, that's not an unexpected exception. Still log it as an error, but don't worry about code bugs when you investigate the logs. Instead, if you catch an exception that your code is unable to recognize (a NullReferenceException is a classic example) then log with highest severity, ie. fatal, to give it maximum priority!
A good strategy for ASP.NET
can surely be based upon Page.OnError method. If you have a base page class for all of the pages of your site, you should definitely override that method. In that method, you should first log your exception.
You also shouldn't abuse of try-catch(Exception) blocks, because if you don't catch an exception you can't handle with catch, you will have to handle it via OnError.
When you run such a method, don't immediately think about Server.RemoveError(). You can prefer to have a static HTML page for HTTP 500 error (that is triggered when an unhandled exception bubbles to ASP.NET runtime) that displays a courtesy message to the user.
Briefly
Don't hesitate to throw in underlying layers if anything strange occurs
As said by your advice, don't handle exceptions you are unable to handle (if you catch an exception you can't handle, rethrow it)
LOG!!!!!!!!!!!!!!!!!
Don't disclose exception details to final users on a public website, never!! By default, ASP.NET prevents that from occurring, but you could still use OnError to print stack trace
Use OnError, or Application_Error as single central point to handle all unexpected exceptions
Periodically examine logs against error/fatal messages to find issues with your code, then think about maintaining/debugging/fixing it
Take a look at elmah. It's a logger for asp.net. Renders all errors on a nice summary page.
http://code.google.com/p/elmah/
The best way to handle exceptions is in the specific layer they apply to. If it is a constraint volation, for example, 2 users with the same name, you should let that bubble up to the UI and alert the user.
Same goes with any business rule violations. Those should bubble up to the UI so the end user knows what went wrong.
A SQL Connectivity error is best handled in the DAL...etc..
The how/when/where to catch exceptions may depend on what your trying to do exactly, its difficult to give an exact catch all always correct answer.
As to your specific questions,
I just learned about the SqlException
class, what's the deal with that class
? I once saw a code that handles the
SqlException then it handles
Exception!
Its good practice to handle the specific exception you believe may occur, if your not sure what type this exception is you can just 'Exception', if you want something specific to occur on a 'SQLException' and something else to happen with an 'Exception' then there is certainly nothing wrong with writing code that handles both.
"Don't just explicitly catch
exceptions"
I believe this is refering to code like this
try
{
int i = 1/0;
}
catch(Exception e)
{
//do nothing
}
This exception will be caught but you'll never know it happened, hence this is not a good idea, and the person using the code will be scratching their head as to whats going on.
I think what you are asking here is a Error/Exception Handling Strategy for any application.
I think it includes:
Where - All places where you think an exception can occur or which need more monitoring like DB calls, External Service Calls, Use of Arrays, User Input Parsing, Type Casting and so on...
How - All you high level layers should throw the exception and it should be captured at the entry point and processed to understand the root cause. Usually you do this in Application_Error() where you catch the exception and log it for troubleshooting. How you log an exception is upto you. A Log File or DB driven log is an option based on your requirements and available resources.
IMO apart from extremely rare circumstances I only ever use exception handling for I/O related code where there are interactions with services and file systems whose functionality and maintenance is beyond the control of my applications.
I have always considered the use try/catch statements to manipulate the logic (flow-of-control) in a program in the same way if/else statement work to be extremely bad practice. Most common exceptions can be avoided if you use the tools at hand correctly.
Currently I'm in the process of writing a client class that utilizes DNS, Sockets, and SSL among other classes that love to throw exceptions. Other people will be implementing this class, so I was wondering what the best practice is for throwing exceptions.
Should I create my own custom exception so they know that it is my class throwing the exception or should I allow the classes and methods I call (DNS, Sockets, etc.) to throw their own exceptions? Currently, the code is in the hundreds of lines and growing with many different method calls. What is the best practice for throwing exceptions in this situation?
If the BCL contains classes that already convey the meaning you want (ArgumentNullException, for instance), use those.
Reserve using your own exception classes for things that are specific to your API.
If you feel that you can add information, by all means raise your own exception but do not swallow exceptions - propagate them up as inner exceptions of your own.
It is fine to throw your own exceptions if they add information, but don't swallow the exceptions from the underlying services unless there is a security concern.
If you are catching one exception and and throwing a new one, assign the old one to the InnerException property of the new one. You can nest as many Exceptions as necessary in this way, which creates a hierarchical "view" into how the exception propagated, which is very helpful for debugging.
The worst thing you can do is throw an ApplicationException with details in the message string. IF you find yourself needing to do that, it's time for a custom exception.
It really depends on your audience, i.e. the consumers of your class.
For example, if you are essentially wrapping a lot of different exceptions, it may be a good idea to create custom exceptions that would simplify the error handling in the consumer.
If you do create custom exceptions, be sure to include the original exception into the InnerException of your custom exception, unless you explicitly have a reason to hide it. This will people using your class the most information available, as well as cover you if an exception comes back that your class doesn't completely cover.
If you want anyone to catch and recover from your exceptions, it's probably best to use a small hierarchy of custom exception types, probably organized by the expected degree of recoverability (e.g. have an exception type indicating 'something unexpected happened, but the socket is probably still good', another for 'the socket state cannot be trusted, but starting over with a new socket connection might work', and another for 'the host says what you're doing won't work; don't even bother retrying unless you have reason to believe something has changed'). The particulars of what caused an exception are often less important to the 'catching' code than the nature of the violated post-conditions.
Is there a best-practice or industry standard for throwing exceptions from a toolkit API?
Should the user facing methods catch and wrap up Exception in some sort of CustomException so that users only have to worry about CustomExceptions coming out of the API?
Or is the convention to just let those bubble up?
We're concerned with being able to document all possible exceptions our API methods might throw. (For example, if our API method calls Stream.Write() which throws 4 or 5 exceptions, we'd have to document all of those in addition to other exceptions that other called methods might throw.)
We were thinking of doing something like this:
public void customerFacingApiMethod(){
try {
//api functionality goes here
} catch (Exception e) {
throw new CustomException(e);
}
}
In my opinion having the API throwing only one exception type is a bad idea. One of the good things with different exceptions is that you can choose to catch different types of exceptions and handle them differently. Wrapping up exceptions into a single exception type would remove that facility.
Use the exception types provided by the framework where appropriate, and create your own custom exception types for specific situations where appropriate. And above all, make sure to document for each method which exceptions they may throw.
When throwing exceptions, make sure that the user-facing exceptions are all relevant to what the user actually did wrong with regards to your toolkit. That might mean catching or merging different filesystem exceptions into a single exception but you shouldn't ever just catch Exception and throw a new one - that's not actually telling the toolkit user what they did wrong.
You should follow the same concepts as the .NET Framework. Your users already use the framework, so they know how it works and expect certain behavior.
Throw an ArgumentException-derived exception if an argument from the client is invalid (use ArgumentNullException, ArgumentOutOfRangeException, etc. as appropriate).
Throw an IOException-derived exception for IO errors.
Etc...
In your documentation, clearly state the preconditions for your public API and state the exceptions that will be thrown when they fail (like MSDN does).
I don't like it. If you wrap all exceptions into a CustomException it will be difficult to catch specific exceptions without searching inside the object for the InnerExcpetion (possibly multiple levels deep if your API also uses other APIs that do the same thing). If there's an OutOfMemoryException, I'd like to know that without having to go searching for it.
Don't use the same exception for all.
You need the different exception types to be able to separate one case from another. For anything that you'd let it flow up until a generic exception handler block catches it would seem k, but you are preventing any other code recovery - extra actions that operate on specific cases.
You can wrap a set of exceptions, if those fit into a specific scenario that can be handled by the calling code. Don't forget that some framework exceptions already communicate the situation well.
What Fredrik Mork says is very true. I also like to add to that that you can easily document the exceptions that are thrown with xml comments (and GhostDoc).
So an API user can lookup in the documentation to see what exceptions can be thrown. However, there is a downside.
If you have a deep callstack inside your API and especially if the cyclomatic complexity becomes high (i.e. num of possible branches) you cannot recover all possible exceptions that can be thrown (perhaps by the runtime?)
So i would recommend to only throw if something if recovery is not possible and only throw in the upper layer of your API, i.e. no deeper than 2 deep. And catch all exceptions that are thrown deeper in your callstack and return them as InnerException or something like that.
There are two types of exceptions to consider (ignoring StackOverflowException, etc., which you can't do anything about anyway):
Those that are caused by external issues (like file IO), which have to be handled.
Those that can always be avoided with properly validated input.
It usually makes sense for the IO-type exceptions to be passed up the call stack unmodified, since there isn't anything you can really do about it anyway. Exceptions to this would be anticipated errors for which you might do retries, or asking the user what to do, if your API operates at the GUI level (which would be rather unusual).
Just be sure to document which exceptions of this type your API methods can throw.
Of the second type (exceptions that can always be prevented), these exceptions may be generated by your API on bad input, but should never be passed up the call-stack from the lower levels. Input to anything you call should be validated so that these errors do not occur, and if, for some reason, they can occur, then these exceptions should be wrapped up. Otherwise, the code that uses your API will have to deal with exceptions at the wrong level of abstraction.
And once again, be sure to document what sort of input will not generate exceptions, and what kinds of exceptions to expect if these rules are broken.
In all cases, throw exceptions that make sense to the user of your API, not the person programming the API itself.
The problem with catching System.Exception in the general case is that by doing so, you're effectively saying "I don't have any idea of why this failed, and that's okay, because I know I can continue anyway!"
That's rarely, if ever, true.
Wrapping up all exceptions in a single custom exception type means that your consumers will just catch that type - which is then the moral equivalent of catching System.Exception. While you may satisfy some policy/FXCop rule by doing that, you're really still just catching System.Exception.
For your exception policy, I'd start with asking this: "If I didn't know what this API actually talked to, what kind of exception would I expect to get back?" And remember that a method is a request to an object to do something, and an exception is the object's way of letting you know that it couldn't, and why.
If you create a single exception type for use throughout your API, its meaning will be vague to client applications that encounter that exception type. Instead, consider creating an exception class hierarchy for your API.
To do so, first define an abstract base exception type:
CustomException
...and then derive more specific exception types from it. For example:
CustomFooException
CustomBarException
CustomFizException
CustomFuzException
The abstract base type CustomException will never be directly thrown from your API. However, a client of your API can catch the base exception type CustomException if it doesn't care about which specific derived exception was thrown from your API.
For more on the idea of developing an exception class hierarchy, see this answer and other answers to this question: Why create custom exceptions in .NET?
Also see this answer which introduces the idea of making the base class of your exception hierarchy abstract.
Anyway, I'm a little confused about when to propagate an exception and when to wrap it, and the differences.
At the moment, my understanding tells me that wrapping an exception would involve taking an exception like DriveNotFound (in IO) and then wrap it with the general IOException.
But with the concept of propagating an exception, is this only something that happens if I have an empty catch clause? So in an ASP.NET web app, it would propagate to global.asax. Or in the case of a recently deployed web app, an unhandled HTTPException gave a yellow screen of death and wrote a log to Windows Server (this is a web app I'm rewriting). So the exception happens in a method, it could be handled at the class level, displayed in the page, and then goes up to global.asax or Windows Server.
Why exactly do I want to wrap an exception with a more generic one? The rule is to handle an exception with the most specific type (so DriveNotFound for obviously a drive not found). Also, how would I choose between wrapping and replacing an exception?
Is the exception handling chain just the try and catch (or catches) clauses? I assume from the wording, yes.
Finally, why and how would I want to let an exception propagate up the callstack?
I did read the MS PandP guide on exception handling, but I guess the examples didn't engage me enough to fully understand everything.
This question comes from Enterprise Library the ability to wrap/propagate an exception and etc. It's the propagating I'm not sure about, and the differences in replacing/wrapping an exception.
Also, is it ok to insert complex error handling logic in a catch block (e.g. ifs/elses and things like that).
Thanks
No less than 6 questions :-)
But with the concept of propagating an exception, is this only something that happens if I have an empty catch clause?
An exception will propagate upwards until it is caught by a catch block further up the call stack that handles either that specific exception's type or an exception type nearer the base type of that exception's hierarchy. So, for example, all managed exceptions derive from System.Exception, so a catch block that intercepts System.Exception will catch every managed exception.
Why exactly do I want to wrap an exception with a more generic one?
I'm not sure what you mean by "wrap". Do you mean catch an exception, replace it with another, and add the original as the InnerException property of the new exception? Or something else?
I think there's rarely a good reason to replace an exception with a more generic exception. But you can certainly replace an exception with another exception, for one or more of 3 reasons:
To hide implementation details from the caller.
To improve the level of an abstraction so that it's more meaningful to the caller.
To throw a custom exception that's very specific to the problem in hand.
Also, how would I choose between wrapping and replacing an exception?
I'm sorry, but I still don't understand how you're defining these two as different.
Is the exception handling chain just the try and catch (or catches) clauses?
Here are the basics of what happens when an exception is thrown:
The CLR walks sequentially down the list of Catch blocks within the local Try...End Try block, looking for a local Catch block with an exception filter matching the exception that was thrown.
If a local Catch block has an exception filter that matches the exact exception that was thrown, the code in that Catch block is executed, followed by the code in the Finally block. Then execution continues at the first statement following the End Try.
Alternatively, if the exception that was thrown derives from the exception specified by a local Catch block, the same actions happen as described in the second step. For example, an exception filter that catches ArgumentException will also catch exceptions derived from ArgumentException, such as ArgumentNullException, InvalidEnumArgumentException, DuplicateWaitObjectException, and ArgumentOutOfRangeException.
If no local Catch block matches the exception that was thrown, the CLR walks back up the call stack, method by method, looking for a Catch block that wants to respond to the exception. If no matching Catch block is found in the call stack, the exception is considered to be unhandled.
Alternatively, if a matching Catch block is found somewhere in the call stack, the code in every Finally block between the throw and the catch is executed. This starts with the Finally belonging to the Try block where the exception was thrown and finishes with the Finally in the method below the method where the exception was caught.
After this clean-up has been completed for all methods below where the exception was caught, control is transferred to the Catch block that caught the exception, and this code is executed. Next to run is the Finally block of the Try where the exception was caught. Now that the call stack has been unwound and the error clean-up has been completed, the final step is to continue execution at the first statement following the End Try where the exception was caught.
If code within a Catch block causes another exception to be thrown, the original exception is automatically appended to the new exception using the InnerException property. In this way, exceptions can be stacked without any loss of information.
You should avoid placing clean-up code within a Finally block that might throw an exception, unless that code is within its own Try block. Without this added protection, the CLR behaves as though the new exception was thrown after the end after the Finally block and looks up the call stack for a remote Catch block that wants to respond to the new exception. The original exception will be lost unless the original Catch block saved it.
Finally, why and how would I want to let an exception propagate up the callstack?
Why: Whenever you don't specifically understand the exception and know how to recover from it, you should let it propagate upwards.
How: By only catching exception types that you understand and know how to handle. Occasionally you need the details of any exception in order to do a proper recovery. In this case, you can catch it, do the recovery, then re-throw it by using the throw; statement.
Also, is it ok to insert complex error handling logic in a catch block (e.g. ifs/elses and things like that).
Generally yes, because any new exception caused by code in your Catch block will have the old exception automatically attached to it via the InnerException property. But it's not wise to provoke this mechanism if you can avoid it, so the simpler code you have, the better. Another good reason to keep your Catch code simple is that it often won't go through the same degree of testing as your main-line code.
There is already a rather good question about this with lots of good answers and discussion. See here:
Best Practice for Exception Handling in a Windows Forms Application?
It's all about conveying the right meaning to your callers. I doubt there's cause to wrap a specific exception in a more generic one - that helps no one.
Consider an API that has nothing to do with file access but accesses a config file behind the scenes. If the config file is not present you might wrap the FileNotFoundException in a ConfigurationException so that the correct problem is conveyed to callers.
why and how would I want to let an
exception propagate up the callstack?
You would let an exception propagate if you can't handle it. It's that simple. If there is nothing your code can or should do to work around the exception, then let it propagate. When propagating, be careful how you do so:
throw ex;
is different to:
throw;
The former throws away the old stack trace and creates another from the point the exception is thrown. The latter preserves the original stack trace.
Of course, if you can't handle the exception then you might not bother to catch it in the first place (maybe you want to log though).
I usually do this:
Business logic assemblies (dlls) don't handle exceptions unless they are FULLY understood
Exceptions that are expected but not handleable are wrapped in a single exception type and are allowed to roll up the call stack (i.e., all the different exceptions that can happen during a database interaction are wrapped in a single RepositoryException and thrown)
Unexpected exceptions are allowed to propagate (never include a catch(Exception ex) in a dll)
Exceptions are handled only at the last possible moment (i.e., controller for the UI)
Its usually only far up in the call stack that you know exactly what you're doing (what the current business process is) and how to handle exceptions properly.
This is the best resource I've found for implementing a coherent exception handling strategy in .NET
http://msdn.microsoft.com/en-us/library/cc511522.aspx