by Paul Stovell via Paul Stovell on 12/14/2009 4:05:33 AM
Back to: Magellan Home
Because the Magellan framework handles many parts of the navigation lifecycle, there are a number of things that can go wrong. I want to dedicate this page to explaining the common exceptions that are thrown by Magellan, and look at techniques for handling them.
Where logical, Magellan throws standard .NET exceptions such as ArgumentNullException and InvalidOperationException. However, Magellan also has it's own set of custom exceptions that can be thrown. All custom Magellan exceptions derive from an abstract NavigationException class, which you can use if for some reason you want to handle all Magellan exceptions in a specific way (such as from a common exception policy handler).
ArgumentNullException
InvalidOperationException
NavigationException
This is usually thrown if there is something in Magellan that has not been setup properly. This can be thrown when:
ControllerBuilder.Current.SetControllerFactory
This is thrown when a navigation request has been made, but there is no logical way that Magellan could handle it. An example that causes this is when you use Navigator.Default to navigate to an action, and the action attempts to navigate to a page. Magellan can't navigate to the Page without knowing the NavigationService, so there is no way to fulfill this request. See the section on the Navigator for more details.
Navigator.Default
Page
NavigationService
This exception is thrown when an action is not found on the controller. This usually indicates that the controller exists, but the name of the action is incorrect, or the wrong controller was specified. Generally, actions should be public, non-static/shared methods, and must be declared as returning ActionResult or a derived type.
public
static
shared
ActionResult
This is thrown when an action threw an exception, and it wasn't handled by any of the Action Filters. Some pseudo code for how actions are invoked is below:
try call action() catch ex ask any of the action filters to handle it if handled = true, do nothing else, throw UnhandledActionInvocationException(ex)
As you can probably guess, the reason for throwing a custom exception instead of re-throwing the original, is that Magellan would lose the stack trace, which would make tracking the real exception down very hard. So instead, Magellan wraps it in this exception. You can check the InnerException property to see the real cause for the exception.
InnerException
As the code above suggests, Action Filters get a chance to handle exceptions. I'll talk more about that below.
This guy is thrown when the action was executed fine, but when the ActionResult which it returned threw an exception. This can happen for example if you return a StartProcessResult, but the process name doesn't exist.
As with action invocation, the action filters will get a chance to see and handle this exception too. If they choose not to, this exception will be thrown, with the real exception nested safely inside the InnerException.
This hopefully self-explanatory exception is thrown when you return a Page, Window or Dialog action result, but the view name you specify doesn't exist. This exception also includes the names of all of the attempted search locations where Magellan looked for the view in the aptly-named SearchLocations property.
Window
Dialog
SearchLocations
As with any exception handling guidance, the best approach is to avoid exceptions from happening in the first place. However, that's not always possible.
To avoid UnhandledActionInvocationException and UnhandledActionResultException, you can make use of Action Filters. The action filters section has more details.
UnhandledActionInvocationException
UnhandledActionResultException
Here is an example action filter that logs all navigation errors and shows a message box when they occur:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class HandleErrorsAttribute : Attribute, IActionFilter, IResultFilter { public void OnActionExecuting(ActionExecutingContext context) { } public void OnActionExecuted(ActionExecutedContext context) { if (context.Exception != null) { Trace.WriteLine(context.Exception); context.ExceptionHandled = true; MessageBox.Show(context.Exception.Message); } } public void OnResultExecuting(ResultExecutingContext context) { } public void OnResultExecuted(ResultExecutedContext context) { if (context.Exception != null) { Trace.WriteLine(context.Exception); context.ExceptionHandled = true; MessageBox.Show(context.Exception.Message); } } }
This can then be applied to a controller as simply as:
[HandleErrors] public class MyController : Controller ...
Your filter can also override the exception - for example:
public void OnResultExecuted(ResultExecutedContext context) { if (context.Exception is SqlException) { Trace.WriteLine(ex); context.Exception = new GenericException("A database issue occurred."); } }
That said, for the most part if your intention is to just log and suppress all exceptions, you can do so via the Application.Current.DispatcherUnhandledException event without involving Magellan. There are occasions where this form of handling could come in handy however.
Original Post: Magellan Exceptions
The content of the postings is owned by the respective author. CSharpFeeds is not responsible for the contents of the postings. This site is automatically generated and cannot be reviewed for abusive content. If you find abusive content on CSharpFeeds, please contact us. Designated trademarks and brands are the property of their respective owners. All rights reserved.