I see a few different ways of handling errors and error pages in Sitecore. I really like the way that we do it at Lightmaker, it makes things nice and simple and easy to debug! It also allows us as developers to follow good practice in our business and data layers and not worry about exception handling.
Don’t Catch Exceptions!
CA1031: Do not catch general exception types - Best practice for exception handling says that we should never catch general exception types! If you have this in your code, its time to think again and refactor:
1 | try |
The first rule of exception handling is: Do not do exception handling!
Catching
System.Exception
is the worst possible exception handling strategy. What happens when the application continues executing? It’s probably now in an inconsistent state that will cause extremely hard to debug problems in some unrelated place, or even worse, inconsistent corrupt data that will live on in the database for years to come.
It is so much better to simply allow any exceptins to bubble up to the top of the stack and leave a clear message and stack trace in the error log. Depending on the application, give some indication that there has been a problem in the UI.
How can we do this with Sitecore
In your Sitecore implementation, if you are following a good componentised practice, you probably have a few layers in your code. This is an example of what you might have in an MVC Sitecore project:
Business Layer: Handles getting data from Sitecore for searches or other complex functionality.
Controllers: Communicates with the business layer or Sitecore API to get build a view model and pass it to the view.
Presentation: Views, razor scripts that mix the markup and the data from the view model and present it to the user.
At any point in this flow of data from the Sitecore database to the user and exception could occur. I’m sure you are all good developers and make sure that objects are not null before using them etc… But there are just something that are out of our control!
Also some parts of our code might need to throw an exception. What if a required field has not been filled in by an editor. Somehow, despite validation, something has gone wrong. In these cases we should throw an exception, something has gone wrong and it should be logged and someone notified.
Where should we handle exceptions
The best thing would be a global exception handler at the application level, that catches any unhandled exception that our application throws. In Sitecore MVC we can do this by overriding the ExecuteRenderer
processor in the mvc.renderRendering
pipeline. In the process method, we can wrap the base.Process
method with a try/catch and then handle any exceptions that occur.
1 | public override void Process(RenderRenderingArgs args) |
Create this include file to override the processor:
1 |
|
If we catch an exception, we can log the error and also render a custom view in place of the original view for the rendering. Doing this means that we can display meaningful error messages for predefined conditions. A standard setup at Lightmaker is to display the error message if we are in the Page/Experience editor or if customErrors mode="Off"
To render the error view, we render the view to a string and use the RenderRenderingsArgs.Writer
to output the reusult:
1 | private void RenderError(RenderRenderingArgs args, Exception ex) |
RenderViewToString:
1 | public string RenderViewToString(string viewName, object model, ControllerContext controllerContext) |
This means that in our controllers, we can throw a RenderingParameterException
or a DatasourceNotSet
exception if the datasource or rendering parameters have not been set correctly. In the page/experience editor, the user would get a message indicating that the data needs to be fixed. But on the delivery website, the error is hidden from the end users.
Also when debugging the site locally or in a test/qa environment - where we can set custom errors to Off
, we can see the errors being caught.
The razor view for a rendering error would look like this:
1 | @model Sitecore.Exception.Handler.Models.RenderingErrorModel |
For full details of the code, including the methods that are referenced but not listed here - please see the project at https://github.com/GuitarRich/sitecore-exception-handler. This is currently being made into an installable Sitecore package and will be submitted to the Market Place this week.
Happy coding!
–Richard