In my ASP.NET MVC application, I do not want to report all exception messages to the user. But there are certain types of exceptions that I'd like to report to the user, so I created an action filter to decide if it's this particular type of exception, and if so then display the exception's message, otherwise display a generic message. So I created a custom exception called ClientException.
My filter looks something like this:
if (filterContext.Exception is ClientException)
message = filterContext.Exception.Message.Replace("\r", " ").Replace("\n", " ");
else
message = "An error occured while attemting to perform the last action. Sorry for the inconvenience.";
filterContext.HttpContext.Response.Status = "500 " + message;
I read this http://blogs.msdn.com/b/kcwalina/archive/2007/01/30/exceptionhierarchies.aspx where the author recommends using existing .NET exception types to report usage errors. However, by introducing my custom exception, I just have to do a single check in my filter. Is my approach okay?
I like this approach for a couple of reasons.
First, it fails safely. If someone doesn't explicity throw a ClientException, then the exception details are not reported. Forgetting to display something is a lesser problem than accidently displaying something.
Secondly, it allows the decision about whether to display the exception to be made at the proper place. Not all IOExceptions are displayed, for example. Some may be, and others wont be. The specific exceptions can be caught and transformed anywhere in the call stack, so that tranformation can be made at a place where it is known to be correct.
Both of those things together mean that a future developer will not innappropriately change a whole class of exception to be displayed, or think that something won't be displayed when it actually will be.
Also, the purpose of the using a particular exception type is to determine later what action to take in response to that exception. "Display this message to the user" is a perfectly good action to specify. Once that decision has been made, then the exact nature of the exception is completely irrelivant. (The original problem may be put in the InnerException property, for logging purposes, of course.)
So, in my opinion, this is a good design.
Your approach is fine IMO but there are alternatives. (We're software developers so there are always alternatives.)
You could harness the Exception Data dictionary to store a flag indicating whether or not an exception is a client exception. Then you could have your filter check for the existence of the flag.
If your approach works for you then it is fine. And are you surprised that a Microsoft blog is recommending that you use their Exception class? ;)
There are some .NET library features and 3rd party OSS stuff that will only work with .NET exceptions however.
To get the best of both worlds you could always extend the .NET Exception object into your own.
I would use different Threshold values based on the type of exceptions, and these Threshold values would be associated with the exception messages.
Based on the particular Threshold value logic you may want to decide whether or not to show exception.
My concerns with this solution is that very likely these exceptions will typically be thrown by objects in a business layer (or model objects in MVC terminology). The usage you describe is really what I would consider to be a presentation concern.
Typically you'd need to rethrow whatever exception you have in your model, only to communicate whether or not the exception can be exposed to the user or not.
What do you expect the user to do with the information? If the user can fix the situation perhaps there should not be an exception to signal the state to begin with?
I would stick to catching specific exceptions per case and do presentation decisions at the spot. You may send out an exception, as caught, used as model to a view though. I would still let the controller decide, not whomever throws the exception.
Related
Let's say you are using a library that returns error codes. You'd like to write a wrapper for the library, and you'd like to handle errors with exceptions in the code.
If the library is still in development by someone else, and if the error codes may change (there can be new ones, there can be deprecated ones, or some error codes may change meaning slightly), what would your solution be to handle this?
This is the situation that I'm in right now. In my case, the library is written in C++, and we're using C#. The coder of the library says the error codes may change, and I have to find a way to work with it.
Our initial solution is to:
Create an XML file that has the error codes in different categories (terminal ones, input errors, and so on).
Wrapper fetches these error codes on start.
Throws the appropriate exception by checking the category of the error code.
So let's say a method returns error code 100, then the wrapper checks the category of the error code. If it is a terminal error it throws a terminal error exception, if it is a user input error it throws a user input error exception.
This should work, but I feel like this is not the optimal solution. I'd like to know how good written enterprise software handle change of error codes.
What would you suggest doing?
Edit: I have already questioned the fact that error codes will be changing and the coder of the library says the code is in development. It's an algorithm, so even the way the algorithm works changes as it's original research (he's writing his PhD on that). So he says there may be different errors, or some may be irrelevant in the future.
The data-driven approach you're taking, using the XML file, seems like a good one, given the circumstances. However I'd question why the error codes are changing at all - this suggests that no proper design has been carried out for the library being developed. It ought to have a well-defined structure for its error codes, rather than requiring you to keep changing your interpretation of them.
You may want to try having an overall "library exception" exception class, and subclassing it for each different type of exception you want to throw based on the "type" of the library error. At least that way, you can catch all library errors, even if one of the specific types of exception slips through the net. ie. you'd catch something like LibraryException after trying to catch TerminalErrorException.
I guess you will solve this problem easier if you change your vision of the situation a little bit:
You are dealing with the framework, let's call that an external
framework.
On the other hand, you are writing a wrapper for the
framework - internal framework.
Your code (client application) uses internal framework, assuming that it provides the functionality used for the problem domain. As I understand, and as I believe, client application should not have any idea about the external framework.
Now, the question comes down to the following one: is the internal framework's functionality clearly outlined and finalized? or is that changing too?
If it's changing (possibly because of the external framework), then the internal framework is under the development. This means, client application needs to wait until internal framework is ready to announce a first version ready (possibly after the external framework is complete).
Now error handling:
Errors in the application serve like contracts. Caller of the function expects particular exceptional situations, and particular kinds of errors only. Each possible error is predefined and documented by each function, similar to its input parameters and return values.
What it means for you:
Define the final design of the internal framework (the sooner the better).
Decide what kinds of errors each function of the internal framework can throw.
Use internal framework from your client application and expect only expected and documented exceptions. Don't try/catch anything that is not expected from the internal framework. Basically, follow the contract.
If error code changes, that does not change the concept of the function in the internal framework. It still needs to throw the same kind of error it threw before (according to the contract). The only part that needs to be changed is, how to translate the new code to one of the expected (contracted) errors. You can solve it any way that works better.
Why is the last assumption fine? because we said the internal application's design is final and is not going to change. Error contracts are part of the final design too.
Example:
//external.
int Say(char* message);
//internal.
///<summary>
/// can throw (CONTRACT): WrongMessageException, SessionTimeOutException
void Say(string message) {
int errorCode = External.Say(message);
//translate error code to either WrongMessageException or to SessionTimeOutException.
}
Cannot translate? something is wrong either with current contracted errors or the external framework: maybe you should terminate the process? something went wrong, unexpected!!!
//client.
...
try {
Internal.Say("Hello");
}
catch (WrongMessageException wme) {
//deal with wrong message situation.
}
catch (SessionTimeOutException stoe) {
//deal with session timeout situation.
}
Let me know if anything raises the question.
Translating error codes to Exceptions:
This obviously is some kind of categorizing for each error code. Category can be each destination exception, and exceptions can be categorized by functions. This is exactly what the error contract means: categorize Exceptions by functions; and categorize error codes by exceptions.
Below is a pseudo configuration for this. Take this as an initial idea of how to categorize:
category Say [can throw]: { WrongMessageException, SessionTimeOutException }
category WrongMessageException [by error code]: { 100, 101 }
category SessionTimeOutException [by error code]: { 102, 103, 104 }
Of course you don't need to write a parser for such kind of impressions (this was human readable pseudo configuration). You can store similar sentences using XML or any kind of source, which will help you configure error translation rules and function contracts.
Reference
Book: Jeffrey Richter - CLR via C#, 3rd edition. Chapter 20 - Exceptions and State Management. Sub-Chapter - Guidelines and Best Practices. Sub-Sub-Chapter - Hiding an Implementation Detail to Maintain a "Contract".
This chapter will describe exceptions as contracts and will explain how to categorize contracts thrown by the function. This can confirm the correctness and the credibility of the explanations provided here.
What about this:
You said you have stored Error categories some where (DB or XML file)
lets amuse we have some master detail tables called ErrorCategory(Master) and ErrorDetail(Detail)
I will recommand adding a column (property) to your Errorcategory Table
Called CustomExceptionType, it will be a text property containing full name of assembly and class name of specified exception (ex: CustomExceptions,CustomExceptions.TerminalError )
We will need a base class 4 all of our custom exceptions, lets call it BaseCustomException calss
We will need an ExceptionFactory Class lets call it CustomExceptionFactory class
Our ExceptionFactory will have a method called CreateException, something like this
Public BaseCustomException CreateException(EceptinCategory category, ExceptionDetail detail)
{
var customException = Activator.CreateInstance(category.CustomExceptionType) as BaseCustomException;
customException.SetDetails(detail);
return customException;
}
so in run time our CustomExceptionFactory object will use CustomExceptionType to create a an instance of specific exception using Reflection.
I prefer CustomExceptionFactory & BaseCustomException to be implemented in a assembley
and all derived CustomExceptions be implemented in another assembly so our main application will be non related to CustomExceptions.Dll
In futur by changing of C++ factory, our main application will not need rebuilding and all we need is change in data of tables and impementaion in CustomExceptions.Dll.
(same solution could be implemnted using XML or Configuration file or ...)
Hop this will help.
OK, if you want to be flexible and not to depend on the code I think using reflection to generate custom class when you first run the application would be the best. Here is the rough explanation. If you like it I can explain it further.
The provider of the C++ code should create a class that will hold all error codes - for example public class Errors{public static readonly IOError = 100}.
When you start your application you will check this class for modification and if it is modified you will generate exception class for each error code.
In the above example it you will generate class IoException that inherit Exception .net class.
After that you can use it in the wrapper and catch each exception individually.
Another possible solution is to amend the xml that you are mentioned - for each error code add exception class - using the example the for error code 100 you will have IoException class. after that you need to implement this class and use it...
Better to depreciate old codes and leave their designations reserved than to have your code designations constantly changing. Since your author doesn't seem interested in design, have him report warnings and errors on the stderr stream that you can retrieve.
In addition, it seems simple enough to construct a CSV or XML with code-string pairs that the algorithm writer is free to edit as he sees fit. Reserve certain ranges of code number for different types of errors (1000s for input errors, 2000s for terminal errors, etc) have your wrapper interpret the return code using the code-string pair he wrote.
Then throw your exception based on the type of error, determined by the number range.
public class PageNotFoundException : HttpException
{
public PageNotFoundException()
: base(404, "HTTP/1.1 404 Not Found")
{
}
}
The idea is that rather than typing this each time
throw new HttpException(404, "HTTP/1.1 404 Not Found")
I'd rather write
throw new PageNotFoundException();
I was going to add an overload for including the innerException however I will never use this in a try/catch block.
Would you consider this good practice?
i.e. Inheriting from an exception and passing hardcoded information to base(...).
I decided to rewrite my answer to be specific to your actual question, and in a more broad sense that an MVC application isn't the only thing these best-practices apply to.
(1) Answer. This is not good practice. You should use a exception builder method instead that throws HttpException directly.
public static void ThrowPageNotFoundException() {
throw new HttpException((Int32)HttpStatusCode.NotFound, "HTTP/1.1 404 Not Found");
}
(2) DO. Use exception builder methods (eg. the code I provided). This allows for you to avoid the extra performance cost of having your own exception type, and allows for it to be inlined. Members throwing exceptions do not get inlined. This would be the proper substitute for convenience throwing.
(3) DO. Use base class library exceptions whenever possible, and only create a custom exception when there is absolutely no base exception that meets the needed requirements. Creating custom exceptions adds deeper exception hierarchy, which makes debugging harder when it does not need to be, adds extra performance overhead, and also adds extra bloat to your code base.
(4) Do NOT. Throw the base class System.Exception. Use a specific exception type instead.
(5) Do NOT. Create custom exceptions for convenience. This is not a good reason for a custom exception, because exceptions are intrinsically costly.
(6) Do NOT. Create custom exceptions just to have your own exception type.
(7) Do NOT. Throw exceptions that can be avoided by changing the calling code. This would suggest that you have a usability error in the API rather than an actual problem.
Anyone who has read Framework Design Guidelines from the .NET development series will know these practices, and they are very good practices. These are the very practices that the .NET framework was built upon, and MVC as well.
If you are the one throwing the exception in the first place, then yes - it's OK. However, if you catch an HttpException and then try to throw a PageNotFoundException instead, you should put the original exception as the InnerException.
While this is a nice construct in your own code for your own use, one consideration is that it can promote coding by convention which can be dangerous when you're dealing with other/new developers.
In your own libraries, if you are consistent about throwing a PageNotFoundException whenever a 404 HttpException should be thrown, it might make more sense to catch (PageNotFoundException). However, when you start using other libraries that don't have your custom exception, you will miss 404 HttpExceptions thrown by other code. Likewise, if you have other developers contributing at a later date (or even your own additions in the future), the consideration that PageNotFoundExceptions are what's being caught by most of the functionality may be missed and new 404 HttpExceptions could be thrown in the new modules, which would likewise not be caught by copy/pasted calling code.
Basically, constructs like this increase the acclimation time required for working on the project, and should be handled in such a way that this cost is minimized (made sufficiently visible in an easy to find central shared objects library that isn't already too cluttered).
On the other hand, there is certainly value in centralizing the generation of your HttpExceptions if you're what looking for is essentially the factory pattern benefits; it may be worth just going with that instead if that's what you're trying to get out of it (throw ExceptionFactory.NewPageNotFound()).
I'm designing a class library that will be sent out to the public for use with their applications. It interacts with a custom db system that they need to install on their servers.
I'm having trouble deciding how to throw exceptions from this dll which is mainly a wrapper to the custom db system.
I assume I have to create custom exceptions that can indicate various types of errors, including validations, data integrity errors etc.
This dll will be eventually used by public facing web sites. I would like to provide a good feedback to the end user by throwing proper exceptions so that the site can make a decision to display them or not. But I'm not sure if it is possible to anticipate all the user input errors. In case of an unexcepted event, do I just throw a regular .net exception with the error message?
I have used many third party dlls that do not give you a clear way to handle the errors and I don't want to be one of them.
The only reason to creaqte a custom exception is if the calling code needs to catch it explicitly to know the difference between your exception and some other exception.
If the caller is going to treat your exception exactly the same as, say, InvalidOperationException, then you should throw InvalidOperationException instead.
See Choosing the Right Type of Exception to Throw.
You should rethrow custom exceptions where your DLL knows more about the error than is indicated in the exception you are catching, if you don't know about it, then you don't know MORE about it, just pass it along.
Just to be clear, this doesn't mean you can't throw your own exceptions on detecting errors.
I'm working on a logging program, and I'd like to avoid processing the same Exception object repeatedly when it is being logged repeatedly because it is percolating up through a nested call structure. So I'd like to be able to format the Exception object once, and give the formatted version a unique "exception number" and then tag the Exception object somehow so I can recognize it if it turns up again in a later log call.
The idea I've come up with is to misuse the HelpLink field of the Exception object. I'll set it to contain a string version of my "exception number". Then I can recognize the Exception object if it shows up again momentarily in another log call.
But is this maybe a bad idea? Are there any gotchas involved that I haven't thought of? If so, does anyone have a better idea?
EDIT:
To explain the situation a bit more, this logger will only be used on my own programs.
Instead of 'abusing' HelpLink property, you could use Data property to add extra information to the Exception. It contains key/value pairs that provide additional user-defined information about the exception.
While I agree with TheVillageIdiot, I would point out that more generally speaking, if you want to change the behavior of Exception, then you should create your own Exception class that add's additional pertinent information. That's why we use inheritance and polymorphism, after all. :)
Definitely it is not okay to use Exception.HelpLink because logger should be concerned with logging the exception information only in given format or any default format. If same exception is coming again and again it is problem of the executing assembly or program not the logger.
Better still you can explore the options of using log4net for logging and custom reporting interface to format/group exception from the log files or database tables created/updated by log4.net
No it is not acceptable to misuse the HelpLink. As #Greebo mentioned if you need additional properties you could create your own exception classes. An alternative might be to use the Data property that is part of the System.Exception class.
Question: Are your exception handlers doing any handling other than logging?
If not then most likely your don't need the handlers. Just let the exception (using a finally block for cleanup) bubble up the call stack and handle it at the outmost layer. If your handlers are handling the exception then I'm not sure why you would have the same exception further up the stack. I would think it would be more likely that you would create a new exception setting the inner exception to the one that was handled.
Your code should not be catching and logging the exception at every level. There's no reason that your code should ever be seeing the same exception twice. This sounds very much like you are using "catch every exception", which is a major anti-pattern.
Is there anything wrong with having an asp.net page throw a (custom error) if a a required querystring parameter is missing and having global.asax catch it with Application_Error, then transfer the user to an error page? I have several base classes that perform these checks and I am not sure of the best way to communicate the error to a user.
So, something like this:
int reqParam;
if(!isParamSet("myReqParam", out reqParam))
{
throw new QuerystringParamMissingException();
}
which is then caught by Application_Error in global.asax.
Also, from a security standpoint how much information should I be providing to the user? Just that it was an error, or that a querystring parameter was missing, or which parameter was missing, or maybe even what that parameter indicates is used for?
It all depends on how serious an error it is and whether the user can easily recover from the error.
One view is that the user shouldn't be able to make invalid calls - all links that require query strings should be validated client side, so during the normal operation of the site all query stings will be complete and valid. Therefore it would be a serious error if there were parameters missing, so raising an exception is a perfectly valid approach.
It would be useful if you want to stop people modifying the query string to gain access to parts of your system they shouldn't. They're likely to miss off a parameter and displaying a custom error page might not give them any clues about what they got wrong.
You should log the error though - so at least you know what when wrong and where.
So long as you don't believe this situation should arise in normal application usage this is an acceptable solution.
What you do by letting the Exception bubble up the stack is destory any chance of recovering from the error, in this case you may not be able to recover anyway.
I believe you should not let your application throw an error as long as you can control the situation. I mean since you know what a parameter could be missing...so you could prompt the user for that instead of throwing an error and then letting the application handle the rest of the case.
Instead provide a user friendly message and help the user understand what went wrong!
Thanks,
Take care.
You should log this error that was (you have to be sure) caused from user manually manipulating the query string and then redirect to a default page(home or login-page).
When the missing parameter is caused by your application f.e. not full validating user input, then you should eliminate the cause.
Just remember that there's a performance cost to throwing exceptions. It's a lot more performant to just page redirect to the error page & handle the error without throwing an exception.
That being said, it is rather convenient to just throw an exception, since there's a lot of configurable as well as built-in mechanisms in ASP.NET for dealing with exceptions, for instance:
HttpContext.Error
HttpContext.AllErrors
HttpContext.IsCustomErrorEnabled
<customErrors defaultRedirect="..."> node in the web.config