Proper error handling in ASP.NET MVC2 - c#

I have an override OnException(ExceptionContext filterContext) in my base controller to catch the app during any errors, and then log them. The problem I'm getting in my app is this particular method is fired off four times for certain errors. I'll walk you through a scenario:
Let's say i navigate to:
http://localhost:180/someController/someAction?someId=XX
And I have poor object handling in my code. The Id passed in is an invalid one, and it retrieves some null object, I then, bc of my bad object handling, try to operate on a null object. I get an exception.
BaseController's OnException is fired off here.
That null object is still returned out to the view, where the view tries to bind it to something, or what have you.
BaseController's OnException is fired off here again, for the error in the view.
Essentially, only one error is important to me, but the trickle up effect is causing more errors to fire off, and spam my inbox :-/.
What is the correct way to catch an error in MVC2 and not have this happen to me?

I would recommend you inheriting from the HandleError attribute and rolling your exception handling in there. Overriding the OnException on a single controller means you either have a lot of exception handling code in a lot of controllers or your inherit from a base one, which due to the MVC pipeline is not really necessary in either case.
By using the attribute, you should have one occurrence of an error per action executed, and once the error is handled it won't fire again. Hopefully this will cut down on repeat exception messages.
I personally use attributes for the exception handling cause it's cleaner and more reusable and get's rid of a lot of noise within my actions.

First to explain why you are getting multiple errors. First error will be from trying to operate on a null object most likely in your model or controller. Your then probably getting a 2nd exception when the view is trying to bind to a null object when it is expecting an object to exist. Not exactly sure why you are getting 4 errors but could be because the code is trying to operate on an object that is currently null.
My first suggestion would be have your OnException code redirect the application to a friendly error page. Your probably just eating up each new exception and not letting the web.config handle the error pages properly if you have that setup to display an error page.
My second suggestion would be to add some code to check for null objects before you operate on them. These are commonly called Guard Clauses, and are very helpful and useful to implement. You can then determine a nice friendly way to handle errors without always logging an exception if you don't need to and to also display a friendly message to a user besides a generic "An Error has occured." message.
For example in your Controller you could check for a null object and pass an alternate view to the user if that object is null
Function Example As ActionResult
dim obj as Object = GetObject
If obj is Nothing Then
Return View("FriendlyNoObjectView")
Else
Return View(obj)
End If
End Function
I know this is vb (Sorry I know that better then c#) but the idea is the same. If you wanted you could still log that as an error, but you would then prevent the error from happening many times. It's always good practice to handle the error when it occurs and try not to let it float all the way to the top of the stack and cause multiple other errors.
Hope this helps these were just my quick thoughts from reading your question.

Related

Appropriate Exception to throw if you've manually detected a threading error

Suppose I write some multi-threaded C# code. (I know ... bad idea from the get-go ;) )
I have some code B, which I expect to only get called after code A has completed. I write and review my code carefully to convince myself that this is true, but I can't actually enforce that expectation, I can only check whether it is true.
So I put the checks in, and if the check ever fails, I want to throw and exception so that the developer gets a big shouty log message saying "Nope, ya fucked up; there's still an edge case where the threading doesn't do what you'd convinced yourself it did."
What's the best C# Exception type to throw here?
My instinct is to go with that old stand-by InvalidOperationException or possibly just a raw new Exception(message). But it would be nice if there were a slightly more specific type I could throw (like throwing an ArgumentException when that's the issue that's happened)
There are a few Exception types that auto-complete from Thread or Sync but they all look like they're intended for much deeper problems. i.e. there's something wrong with the actual threads. Here the thread are all fine ... it's the developer's threading logic that's in error.
Are there any sensible pre-existing Exception classes to use here?
An InvalidOperationException is the most suitable built in exception for this situation.
See it's official documentation remarks section:
InvalidOperationException is used in cases when the failure to invoke a method is caused by reasons other than invalid arguments. Typically, it is thrown when the state of an object cannot support the method call.
(emphasis mine).
Of course, there's nothing stopping you from creating your own Exception class if you want something more specific, but that would only make sense if you want the exception to carry information that doesn't fit inside the InvalidOperationException (and of course, if you do choose to create your own exception class, be sure to follow the guidlines in How to create user-defined exceptions:
Derive from an existing Exception class
use the word Exception as a suffix to the class name (MyVeryOwnSpecialException)
Implement at least three public constructors:
3.a: A constructor with no parameters
3.b: A constructor that takes in a string message
3.c: A constructor that takes in a string message and an Exception inner exception.

WCF Stripping detail from System.SecurityException

I am implementing IErrorHandler for a WCF service, with the intention of automatically logging the messages.
During testing I decided to throw a System.SecurityException with an inner exception and some user defined data:
try
{
LevelTwo();
}
catch (Exception innerEx)
{
var outerEx = new SecurityException("Is security special?", innerEx);
outerEx.Data.Add("foo", "bar");
throw outerEx;
}
Yet when it hits my ProvideFault method in my error handler it has already been converted to a System.ServiceModel.FaultException with a Message of "Access is denied". The original message, exception type, data and inner exception have all been lost, and I cannot log them. Other exception types work as expected, exposing all those properties for logging.
I presume that there is a framework implementation of IErrorHandler that is hit first, and converts it, stripping the detail and providing a generic message, which is all well and good generally, but not when I want to log the details.
Somebody has posted the same issue on MSDN but didn't get any particularly good answers.
Ideally I would like to change the order of the error handlers so that mine is hit first - is this possible?
If not - is it possible to remove the existing handler, and if so, are there any undesirable consequences?
EDIT
Following Christian's advice below it appears that the exception is getting caught by the code in SyncMethodInvoker.Invoke()
catch (System.Security.SecurityException e)
{
DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning);
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError
(AuthorizationBehavior.CreateAccessDeniedFaultException());
}
I think this means that Security Exceptions are a very special case, and that there probably isn't a good way around this, but I would appreciate any suggestions.
I'm not a proper computer right now, so I cannot test it myself, but I think WCF indeed converts any SecurityException into what you observe.
If you look at the complete call stack of your "rethrown" SecurityExceptions, you should see stack frames hinting at the location where they originate. With that information you can look into http://sourceof.net/ to look at the relevant code.
Having that said, there are multiple implementations of IOperationInvoker in WCF that handle the different calling styles (async, sync, etc.) of service operations.
For an example see:
http://referencesource.microsoft.com/#System.ServiceModel/System/ServiceModel/Dispatcher/SyncMethodInvoker.cs,181
http://referencesource.microsoft.com/#System.ServiceModel/System/ServiceModel/Dispatcher/AsyncMethodInvoker.cs,140
So, I think the order of IErrorHandlers is nothing that helps with this issue, as the exception gets converted/stripped/replaced before error handlers are even called.
I would consider creating my own fault type for security issues, like a SecurityFault type and then throwing that as FaultException<SecurityFault>(...). That fault type could have all the properties you want. Additionally, since the fault type is a DataContract and the properties are DataMembers, you don't risk getting serialization issues, because you may inadvertently put non-serializable data into the exception's Data.

Creating exception classes for lot different error codes

I am writing a custom .Net SDK for the mapping program MapInfo Pro, mapinfo only exposes two methods to use over COM void Do(string cmd) and string Eval(string cmd). When you use one of these methods and you do something invaild, it returns a a COMException with a error message and I get the error code from MapInfo. So for example an error message looks like this:
418 "Table not found."
Now I would like to throw some kind of meaning full exception rather then just a exception with a number and message that people have to catch then use a if block to check what error, something they say they only want to catch and do something meaning full with. Something like TableNotFoundException.
The biggest problem is there are currently 1999 possible error messages, now I don't want a exception class for everyone of those errors.
The idea of the SDK is that people use my objects and methods rather then Do and Eval(they can stil use them if they want).
Should I,
everywhere in my SDK that I call Do and Eval use a try catch and then check the error code and throw something more meaning full from there, because I know what errors I should get.
or
I have somekind of God lookup list in the Do and Eval that when a COMException is thrown it lookups the error code and throws the meaningfull error from there? Meaning I don't have to wrap every call to Do and Eval in try catch blocks(there are a lot of calls)
Bit of a tricky thing to explain so I hope people can understand it.
Thanks.
Wrap the calls to Do and Eval in your own function which catches MapInfo errors.
As there are so many error types, you could create an enum with some more descriptive names or a dictionary mapping error numbers to more friendly names (if the original ones aren't good enough) - you don't want 1999 exception classes, so I'd suggest using only one exception class that contains the error number and description. You're saying that users could use Do and Eval directly, so they should know how to handle these error numbers, anyway.
Alternatively, you could create a few hierarchical exception types and decide which one to throw (needs something a dictionary mapping 0-1999 => matching exception type) - that way, users can be a bit more specific about which types of errors to catch.
As per AndiDog, creating a few exception classes that group the couple of thousand errors into some reasonable types. You should probably still pass the original error number out, just in case.
While you're doing that, read this article to sort out how those groups might be assembled, and maybe which ones you DON'T want to catch.

Whether to create a custom exception or wait to occur NullReferenceException down the line?

I am confused. Whether to create a custom exception or .Net base class library has the relevant exception?
I am calling some kind of service or framework API and it returns back a null reference which is an exceptional case for my tier. I know that the system won't be able to proceed with null reference and I should get a NullReferenceException down the line if I proceed.
So, should I create a custom exception at that point or should I wait to occur the NullPointerReference?
See the code snippet below
Organization organization = OrganizationService.GetOrganizationById("123");
this.SetOrders(organization.Id); // This will give me NullReferenceException
please guide me.
Thanks and regards
123Developer
In general, its good practice to catch errors as soon as possible and handle them in the best manner possible - either by using default values to work around the error, or informing the user that you cannot proceed.
So in this specific case, if i understand correctly, i would test the variable for null, and if its null do not continue - bail out gracefully.
NullPointerReference exceptions are always hard to debug and should be avoided whenever possible. In certain cases you could use ArgumentNullException, if the "null" value is one of the passed parameters. Not in your case though and that's where I would recommend a custom exception.
Throw an InvalidOperationException if it has nothing to do with any arguments passed to your method, or an ArgumentException otherwise. Do this as soon as is reasonably possible, to avoid accidentally corrupting your state.
Aside from anything else, this allows you to give a more useful message, indicating what couldn't be found.
as a general rule you should only catch exceptions down the stack if you can add meaning to the exception itself.
In your particular case, I would suggest that you check the value for null, and throw an appropriate exception yourself (possibly an InvalidOperationException with a message of "Organization not found"?)
I often design a DataNotFoundException that is thrown when a get-operation based on an object ID fails. My rationale for doing so is that ID's are typically not entered by the user, but used only in the code, so if a search is performed using a non-existing ID the input is bad, and I want to signal that in a clear manner.

How to catch an exception thrown by a filter in .NET's MVC?

One of the filters on an application I'm developing checks to see if a user owns the item they are trying to alter. The action is decorated by the [RequiresOwnership] attribute, and inside the attribute logic, I check to see if the user owns the item, and if they don't, I throw an UnauthorizedAccessException.
My question is this: Where can I catch that exception? I would ideally like to redirect the user to a page explaining why what they tried to do wasn't allowed, instead of just showing an exception page. I don't think I would be catching the exception inside the action that is decorated by the attribute, so is there some base part of the application where I can handle exceptions thrown higher up, in the .NET MVC model?
EDIT: I realize that I could just redirect to a page via the filter itself, but that seems a little hacky to me. It would be nice to throw exceptions via attributes, and have one standard place where they can be caught and dealt with.
I think what you want is the [HandleError] attribute on your controller, which takes an optional path to an error handler view. The default is ~/Views/Shared/Error.aspx; you could add additional support for your specific exception there.
I had this problem, and the way I solved it was to add the exception to the FilterContext's TempData collection instead of throwing it. You can then check for it in your action method, re-throw it and deal with it appropriately:
In the attribute:
if (/*some error condition*/)
filterContext.Controller.TempData["Err"] = new Exception("An error");
And in the action method:
var e = TempData["Err"] as Exception;
if (e != null)
throw e;
It's a less than ideal solution, but as you mentioned, there's no useful place to catch exceptions from attributes.

Categories

Resources