How do I implement error handling elegantly? For example, my data access layer can potentially throw 2 types of errors:
1) not authorized access, in which case the page should hide everything and just show the error message
2) errors that inform the user that something like this already exists in the database (say name not unique - for example), and in this case I wouldn't want to hide everything.
EDITED:
As a result of some comments here I devised that I should create derived specialized exception types, such as NotAuthorizedException, DuplicateException, etc etc.... it's all fine and dandy, however I can see 2 problems potentially:
1) Every stored proc has a return field p_error where it contains an error message. Upon getting the data from DB, I need to check this field to see what type of an error has been returned, so I can throw an appropriate exceptions. So, I still need to store my error types/error messages somewhere.....In other words, how do I should the exact message to the user (at certain times I need to) w/o checking the p_error field first. WHich brings me back to error object. Anyone?
2) I can this potentially turning into a nightmare where the number of exceptions equals the number of error message types.
Am I missing something here?
Much thanks to everyone!
You should check out the exception handling block in Enterprise Library. Lots of good tips and codeware surrounding wrapping exceptions and passing them between layers.
Where's your business layer, and why isn't it checking Authorization and integrity? The DAL is too low level to be checking those rules - if you hit a problem there, it's pretty much time to throw an exception. Your business layer or controllers can catch that exception, and display a reasonable message - but it's not something you should regularly be doing.
Create your own exception layer.
DALExceptionManager
DuplicateException
DatabaseException
BLLExceptionManager
NotAuthorizedException
InvalidDateException
In your Presentation Layer, Add this references and create a common exception handler.
In this way you know how to deal with the exception messages.
One option that I was thinking of
using is create an Error class, but
then I would need to pass it from UI
to business layer and the then to data
access layer by reference
I am not sure I understand this. You don't have to pass the error object in every layer. For example, in one of your example, errors that inform the user that something like this already exists in the database (say name not unique - for example) , a sql exception could be thrown by the framework, and you just need to catch the specific exception in your business layer, or UI layer.
Exception handling block by the Enterprise library suggested by other people will allow you define some policy-based exception handling in your web.config file. It could be good place if you want to develop some enterprise application. But for simple application, you may need not go that far.
What happens in the upper layers isn't up to your Data Access Layer. It shouldn't even be aware of what the upper layers are going to do. If you've got a duplicate key error, then it should throw something like a "DuplicateKeyException". If you should hit an authorization error (I presume you mean "exception"), then don't do anything with it - let it bubble back up to the UI layer, which can display an appropriate error page.
Remember that error status values and such things are the reason we invented exceptions.
Enterprise library exception handling block is the bomb as many have pointed out. Using policies you can do things like logging the exception, wrapping it in a different exception, throwing a new exception instead of the original one. Also, if you are looking to perform specific actions based on authentication errors or duplicate record errors etc, you could always create specific derived exception classes and catch those exception types which would precludes the need of passing any objects from the top down. Exceptions should always bubble up not down.
Related
I have a C# console project where I have separated out the business logic from the UI. The business logic calls an API, retrieves JSON data, and then updates a database with the data. The UI handles the display of the results and also loops through a queue to process records with the business logic.
My question is how to properly handle exceptions thrown by the business logic. The UI project currently handles exceptions that bubble up but I want to give as detailed an error message as possible. For example, sometimes the API fails to authorize or may be down and I want to log that specific exception. The problem is the UI project does not know anything about HttpRequestException without me adding a reference to the System.Net.Http library, which creates a dependency I don't want.
What is the "best practice" for handling exceptions in a project other than where they are generated?
If you want to pass detailed messages to the UI project without explicitly referencing System.Net.Http, consider catching these HTTP exceptions in the business logic, wrapping them in an exception type you define in that library, and re-throwing the new exception. Then your UI library only needs to know about the business logic library, which it's already referencing, and the business logic can provide the most informative message possible for things it can't properly recover from.
I'd say the best practice is to not handle them. You don't know what those exceptions are, so how can you "handle" them?
Either trust the Message property of these exceptions and display them to the users, or just tell the users "sorry, something bad happened".
Keep in mind that your users will need to read the detailed messages and decide what to do about them. Quite likely they'll either ignore the messages or else call someone to ask what to do about them. Make sure you log enough information to answer the call. Sometimes, you're just better off displaying a message that says, "Please call someone who can figure out what went wrong".
I am working on re-writing a business layer for one of the apps in company. For now, the business layer will interface directly with the web client. But in the future, it will be encapsulated with service interfaces and will be consumed by the same web client.
My question is that when a validation exception or other exceptions occur in the business layer, is it okay to throw custom exceptions or would it be better to use custom objects that represent errors ... like ValidationError, etc? Is it more expensive to throw an exception vs returning an object?
The most popular thought on this today is to throw the errors towards the application layer. I guess the idea is so that the interpretation of what went wrong and telling the user is more clear there than way down in the guts of the applications.
Some people catch errors everywhere and then throw them as they go, this leaves a trail of traceable documentation for the developer.
One other interesting point, if the developer makes all the error messages contain unique identifiers, then they are easily able to debug because they can pinpoint the code just by looking for that number.
Throwing an exception is way more expensive than returning an object. Exceptions should be used only for unexpected situations. Errors in validation of user input is not unexpected and should not result in an exception being thrown.
I have a situation where one of our developers wants to put a standard in place where we throw System.ComponentModel.DataAnnotations.ValidationExceptions in all our apps moving forward. An example would be that a user enters bad data into a form and our business logic layer throws a ValidationException which is handled at the calling layer.
However, I'm worried that this exception class is being used out of context and that one day we'll using some Dynamic Data Controls which make use of this exception and it will be difficult to tell the difference between when he's making use of the ValidationException vs times that the Dynamic Controls raise the exception.
We already use a custom exception class called something like "OurCustomException" and I think it would be better to just subclass off of that and create a OurCustomValidationException class. This way exceptions of different types can be clear cut.
Any opinions?
... it will be difficult to tell the
difference between when he's making
use of the ValidationException vs
times that the Dynamic Controls raise
the exception.
I think this is the main point you should be looking at when making that decision.
You seem to imply that the above (not being able to distinguish your own exceptions from "platform" validation exceptions) is a bad thing. That's not necessarily the case. IF you use the ValidationException exclusively to represent validation errors, then all your code can deal correctly with both your own and platform exceptions in the same way. No need to special-case platform exceptions from custom ones.
This is a win in my opinion. If you have both CustomException and ValidationException going back up to your toplevel layer for the same reasons, you'll have to repeat some logic one way or another. That's a bad thing (more maintenance, more chances of bugs creeping in).
So my opinion is that using the platform ValidationException is probably a good way to do it as long as you use it strictly for propagating validation problems.
Also think about the case where you would be giving/selling parts of your code to a third party (say it's real cool and you make a product out of it). It would probably be easier for the third party if your module throws "standard" exceptions (they can integrate it easily) rather than having to special-case all of his interface code for your module. Again, this is only valid if you stick with cases where a standard module would throw ValidationExceptions.
Lets look at it the other way around. You say:
our business logic layer throws a ValidationException
This is why I put strictly and exclusively above. You need to make sure you agree on what a validation error is. Lets look at two hypothetical problems:
"abc" is not a valid number
insufficient funds for this operation
For 1., the problem is simple/expected input validation error.
But in my opinion, 2. is not. It's a business logic problem. You could call it a validation issue (in the transaction, before the debit, you "validate" whether there are sufficient funds available) but I'd say its semantically very different.
I would advise not to put these two types of errors in the same exception "bag" as they have very different meanings, and may (often) lead to different application flow logic. (With the above two examples, 1. should keep the user on the very same form, as would any other "typo" kind of issue, but 2. should probably get him to a page that allows him to refill his account.)
To sum it up: using a standard exception seems like a good idea to me, as long as you stick with its expected semantics.
In our app, we use components developed by other teams. The question was how can I define a nicely way of exception handling than this
try
{
someComponent.DoStuff();
}
catch (Exception ex)
{
textLabel= ex.Message;
}
The component has no custom exception type, maybe a nicely way to do it would be to define a component specific Exception type and wrap this somehow?
I know the question is very basic, but I am interested more in the let's say how it is good to do it. If you call another component with no custom defined exception types, how do you handle any potential exceptions in an elegant way?
Ideally you would have the component development team do this for you - how else do they expect their clients to recognize and handle errors from their component? Scoping the exceptions that a component can raise is a fundamental part of good C# design.
If that's not an option, then implementing your own wrapper on top of the component to taxonomize its failure cases sounds like a good second best, and very noble of you into the bargain.
If the third-party library is poorly documented (they don't specify the exceptions that can be thrown by each method), there are tools available that can Reflect into the code and determine the possible Exceptions that may be thrown. This can get a bit daunting (there are a surprising number of exceptions that can be thrown for any given call), but it's better in principle than catching the general Exception type. Here is one commercial product that performs this type of analysis.
When you catch an error you are able to repackage it and then throw another error, at the most basic level you may just be adding more data - but, from what you've suggested, you could also replace the generic error with a custom error that, whilst it won't overcome the limitations of the response you've got from the component, would give the code further up the call stack the opportunity to respond more appropriately.
So in terms of just adding information in the most basic manner - by throwing a new exception with some additional text whilst still passing the original exception:
catch (Exception ex)
{
throw new Exception("This is more about where the exception occurred", ex);
}
Now, if you want to define your own custom component exception you change the new Exception to new ComponentSpecificException adding data as necessary to the constructor but never forgetting to set the inner exception. Exceptions also have a data collection of key, value pairs into which you can insert more information (by creating the exception, adding the data and then doing the throw).
That's all fairly generic - working forward from there, where you can't necessarily anticipate all the exceptions you have to handle you don't try - you set up logging so that you know when you've got a generic exception i.e. one that hits the final catch - and then over time add exception specific catches above the generic to provide more appropriate responses or, at the very least, package up the error into less general custom exceptions.
Not sure I've explained that very well - but the notion is that as its difficult to anticipate every possible error you want to have a strategy to develop your application in a systematic fashion as you discover new exceptions.
Assuming you want to catch every type of exception, this solution looks fine to me.
Either from your knowledge of using the component, or by using something like Reflector to analyze the compiled component, what possible exceptions can this component throw? Would providing exception handlers for these allow you to provide better feedback to you users?
The only reasonable (much less "elegant") way to handle exceptions is to log them if you can't recover from them.
Then notify the user there was a problem and offer them the chance to try again (if it's an interactive program).
If your application is exclusively for .NET developers, go ahead and show them the exception message (though Exception.ToString is better, since it includes a stack trace). Otherwise, don't display exception messages in your user interface - that's a security hole and will only confuse your users.
This title begs for more explanation.
Basically, I'm rolling an API that wraps a web service in a nice heirarchical model. This model exposes things in the form:
var obj = MyRemoteResource.GetForId(1234, SourceEnum.ThatSource);
ApiConsumerMethod(obj.SomeProperty); //SomeProperty is lazily loaded, and often exposes such lazily loaded properties itself
... etc ...
Where many different RemoteResources* (each with many properties exist). There's really aggresive cacheing going on, and request throttling to prevent inadvertantly DOS'ing the servers (and getting the IP of the caller banned).
I've got all this code working, but I'm not doing much in the way of error handling at the moment. Basically, if the consumer of an API provides an invalid ID, the web server is down, a connection times out, or any other of a plethora of request layer errors occur an exception just percolates up when a property is accessed.
I consider this far less than ideal.
So my question is, how should I wrap these errors up so that it is convenient for a user of this API to manage them?
Some routes I have considered:
Just wrap all exceptions in some API defined ones, and document them as thrown.
Expose a static ErrorHandler class that allows a user to register notification callbacks for specific errors; falling back to the above behavior when no registration has been made for specific errors.**
Null properties on error, and set a LastErrorCode.
Each of these approachs have strengths and weaknesses. I'd appreciate opinons on them, as well as alternatives I haven't thought of.
If it impacts the discussion at all, the platform class throwing these exceptions is WebClient. Furthermore, usage of WebClient is sufficiently abstract that it could easily be replaced with some other download scheme if needed.
*Which is to say, many different classes
**This would be... wierd. But it maps to the global nature of the failure. This is my least favorite idea thus far.
I wouldn't implement fancy error technologies (like events and stuff like this). It's not easy to judge where and how to use exceptions, but this is no reason to implements other stuff.
When you request an object by an id which doesn't exist, what do you have to tell the caller about this? If you just return null, the client knows that it doesn't exist, there is nothing more to say.
Exceptions force the caller to care about it. So they should only be used where the caller is expected to do something special. Exception can provide the information why something didn't work. But if it is an "error" the user could also ignore, an exception is not the best choice.
There are two common alternatives to exceptions.
Use return values which provide information about the result of an action. For instance, logon could return a LogonResult instead of throwing an exception.
Write two methods, one throwing an exception, and one (Try...) returning a boolean. The caller decides if it wants to ignore the "error" or not.
Personally I believe this is entirely dependent on the context of what your API end-user is trying to do. If this is the case, you should let them decide how to handle erors.
Recently when working with CSV files (very error prone) I used an API that allowed you to define the exception behaviour. You could either ignore the error, replace by some default value/action, or pass them off to an event handler.
I really liked this approach of letting the end user decide how to handle internal exceptions, because unless your API is very specific its difficult to preempt all scenarios.
I prefer to have an exception thrown at me when something bad happens. Exceptions are (for me, anyways) the common way to tell that something went wrong, and i find it more intuitive to catch, than to check a return value for null and check another property to see what went wrong..