This blog post describes some options for handling exceptions in MVC solutions using the Sitecore ASP.NET web Content Management System (CMS), and provides an example of a global exception handler.
Updated 18.September.2012: See the "Revisited" link in the resources listead at the bottom of this page for information about important exception conditions that the solution described in this blog post does not address.
You can use a variety of techniques to handle different types of exceptions that can occur when processing requests with MVC using the Sitecore ASP.NET CMS:
Note that I have ordered these by scope, starting with the deepest scope and proceeding to the most general. The first approach listed here is out of scope for this blog post. I intend to write additional posts that address the second and third approaches. This blog post provides a solution using the fourth approach. Update 13.September.2012: the link about XSL exceptions at the bottom of this page describes a solution that uses the second approach. Update 14.September.2012: the link about rendering exceptions at the bottom of this page describes a solution that uses the third approach.
If you do nothing, and an MVC presentation component generates an exception, the Sitecore CMS 6.6 technology preview writes the exception message and stack trace to the output streamregardless of the value of the mode attribute of the /configuration/system.web/customErrors element in the /web.config file. Because exposing exception details to an outside world presents a security risk, I reported this to Sitecore customer service as case #370613; engineering may address this before releasing Sitecore CMS 6.6 as a product. Exception details do not appear in the Sitecore log; I did not investigate whether Sitecore clears the error in this case, if the exception handler registered by Sitecore’s HTTP module does not apply to MVC requests, or if something else prevents this. If engineering does not address this issue before you need to use Sitecore CMS 6.6, you can implement an mvc.exception pipeline processor as described in this blog post.
To implement a processor in the mvc.exception pipeline, create a class such as the following:
SC = Sitecore;
"MVC exception processing "
CustomErrorsMode mode = SC.Configuration.Settings.CustomErrorsMode;
(mode == CustomErrorsMode.Off
// to show details to Sitecore admins: || SC.Context.User.IsAdministrator
// to show in the Page Editor: || SC.Context.PageMode.IsPageEditor
// to show in Preview: || SC.Context.PageMode.IsPreview
// to show in the debugger: || SC.Context.PageMode.IsDebugging
|| (mode == CustomErrorsMode.RemoteOnly && HttpContext.Current.Request.IsLocal))
"An error occurred."
With this processor enabled, if an exception occurs while processing a request with MVC, Sitecore logs the exception and unless the value of the mode attribute is Off or is RemoteOnly and the request originated from the local machine (or you enable any of the additional criteria), redirects the browser to the URL specified by the ErrorPage setting in the Web.config file, appending a query string parameter named error containing the error message.
You can use a Web.config include file such as the following (/App_Config/Include/Sitecore.Sharedsource.Mvc.Exception.config in my case) to add this processor to the pipeline:
So far, I have tested this under only one case: a syntax error in an XSL rendering. Numerous additional exception contexts are possible and you should test each, for example if a controller or view throws an exception. Some of the settings in the /App_Config/Include/Sitecore.Mvc.config Web.config include file indicate additional potential exception conditions, such as if you try to register a route that matches the Mvc.IllegalRoutes setting, if the request attempts to activate a controller (Mvc.DetailedErrorOnMissingController) or an action (Mvc.DetailedErrorOnMissingAction) that does not exist.
@Nil: I think engineering must have fixed that one, but I would have to test to be sure. From the release notes: sdn.sitecore.net/.../ChangeLog.aspx When an error occurs, an exception will now be thrown instead of rendering a custom error message on the page, for example when the system encounters a non-existent controller or an incorrect Controller type. (368342) I think this means ASP.NET will handle it as it would a standalone MVC application (without Sitecore). I still think it might be a good idea to configure global exception management logic.
Hi John, I was trying to implement your idea in Sitecore 7 MVC because like you said I was getting detailed error's output regardless of the customerror attribute being on. However I seem to get a "Could not resolve type name: Sitecore.Sharedsource.Mvc..." whenever an error is thrown now. Any chance you can shed any light on this?
@Gavin: I don't see myself getting a chance to research this any time soon. Please follow or add to sdn.sitecore.net/.../ShowPost.aspx and if you don't get an answer in a reasonable time, I can find someone to help. I also recommend filing a support case at http://support.sitecore.net