Skip to content
April 13, 2021 / kiranpatils

SXA Rendering Global Exception Handler

Challenge

We’ve been happily using SXA OOTB Components [and still doing the same :)]. But suddenly one day we started getting errors on the Site. Where the page would give an error. After troubleshooting further we figured out that. The data source item was deleted and the component was still looking for that data source item.

If it had been a custom component or MVC Component. We would have handled that exception. But unfortunately, that’s not the case with OOTB SXA Components.

One way to resolve this is. Configure Custom Error page: https://doc.sitecore.com/developers/sxa/93/sitecore-experience-accelerator/en/generate-a-custom-static-error-page.html. So, it shows our custom error page.

But we didn’t want to break a full page because of an error in one of the components. Instead, we wanted to keep the full page working without an error-ed component.

If it had been an MVC solution there are plenty of blogs to handle this using the Global MVC Rendering exception handling approach. But unfortunately, we couldn’t found any blog for SXA to do the same.

That’s why this blog post is coming to an existence on this earth!

Solution

We stumbled upon following posts to do the same in MVC (Thank you so much for this post):

And tried to fit it in SXA architecture.

Quick show config revealed that SXA has “SxaPageModeRenderingErrorStrategy” to handle such error in Experience editor mode. We noticed that the errored component was throwing and showing errors in Experience editor mode.

That was our Eureka Moment! We fired up the reflector and figured out the next steps.

Putting it together for you. So, you can go home (Or as per New Normal, go to the living room from the working room) on time to spend time with your loved ones!

Here you go!

using Microsoft.Extensions.DependencyInjection;
using Sitecore;
using Sitecore.Abstractions;
using Sitecore.DependencyInjection;
using Sitecore.Diagnostics;
using Sitecore.Mvc.Pipelines.Response.RenderRendering;
using Sitecore.Mvc.Presentation;
using Sitecore.XA.Foundation.Abstractions.Configuration;
using Sitecore.XA.Foundation.Multisite.Extensions;
using Sitecore.XA.Foundation.Presentation;
using System;
using System.IO;
using System.Web.Mvc;
namespace SCBasics.Foundation.SitecoreExtensions.Pipelines.RenderRendering
{
public class CustomPublishModeRenderingErrorStrategy : PageModeRenderingErrorStrategy, IRendererErrorStrategy
{
private readonly BaseLog _log;
public CustomPublishModeRenderingErrorStrategy(BaseLog log)
{
_log = log;
}
protected override string GetExceptionDetails(string prefix, string message, string stackTrace)
{
string pageModeRenderingErrorClass = ServiceProviderServiceExtensions.GetService<IConfiguration<PresentationConfiguration>>(ServiceLocator.ServiceProvider).GetConfiguration().PageModeRenderingErrorClass;
return this.GetPreCode(stackTrace);
}
public bool HandleError(Renderer renderer, Exception ex, TextWriter writer)
{
bool isCustomErrorHandlerEnabled = Sitecore.Configuration.Settings.GetBoolSetting("SCBasics.IsCustomErrorEnabled", true);
if (!isCustomErrorHandlerEnabled)
return false;
/*
* Sitecore.XA.Foundation.Presentation.Pipelines.RenderRendering.SxaPageModeRenderingErrorStrategy
* NON SXA References:
* https://www.teamdevelopmentforsitecore.com/Blog/robust-mvc-rendering-exception-handler
* https://www.sitecorenutsbolts.net/2015/10/23/Rendering-Exception-Handling-The-Right-Way/
*/
if (this.IsPageModeNormal())
{
return PublishModeHandleError(renderer, ex, writer);
}
if (!Context.Site.IsSxaSite())
{
return false;
}
return base.HandleError(renderer, ex, writer);
}
private bool PublishModeHandleError(Renderer renderer, Exception ex, TextWriter writer)
{
Assert.IsNotNull(renderer, "renderer");
Assert.IsNotNull(ex, "ex");
Assert.IsNotNull(writer, "writer");
if (!this.IsPageModeNormal())
{
return false;
}
string prefix = string.Format("Error Rendering {0}: ", renderer);
string str3 = this.GetExceptionDetails(prefix, ex.Message, ex.StackTrace);
// Log Error
_log.Error(string.Format("Failed to render component '{0}'", prefix), ex, this);
// Log main error in comment
writer.WriteLine("<!– Exception rendering component '{0}': {1} –>",
prefix + ":" + ex.Message,
str3);
// Log Inner exception in comment
Exception innerException = ex.InnerException;
string str2 = "Inner Exception: ";
while (innerException != null)
{
string str4 = this.GetExceptionDetails(str2, innerException.Message, innerException.StackTrace);
writer.WriteLine("<!– Inner Exception: {0} –>", innerException.Message);
innerException = innerException.InnerException;
}
return true;
}
}
}
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"&gt;
<sitecore>
<settings>
<!–Default true–>
<setting name="SCBasics.IsCustomErrorEnabled" value="true"/>
<!– USE SERVER-SIDE REDIRECT FOR REQUEST ERRORS
If true, Sitecore will use Server.Transfer instead of Response.Redirect to redirect request to service pages
when an error occurs (item not found, access denied etc).
Default value: false
–>
<setting name="RequestErrors.UseServerSideRedirect" value="true"/>
</settings>
<pipelines>
<mvc.renderRendering>
<processor type="Sitecore.Mvc.Pipelines.Response.RenderRendering.ExecuteRenderer, Sitecore.Mvc">
<param desc="rendererErrorHandler" type="Sitecore.Mvc.Pipelines.Response.RenderRendering.HttpExceptionWrappingRendererErrorStrategy, Sitecore.Mvc">
<param desc="rendererErrorHandler" type="Sitecore.Mvc.Pipelines.Response.RenderRendering.ChainedRendererErrorStrategy, Sitecore.Mvc">
<Handlers hint="list">
<handler patch:after="*[@type='Sitecore.XA.Foundation.Presentation.Pipelines.RenderRendering.SxaPageModeRenderingErrorStrategy,
Sitecore.XA.Foundation.Presentation']"
type="SCBasics.Foundation.SitecoreExtensions.Pipelines.RenderRendering.CustomPublishModeRenderingErrorStrategy,
SCBasics.Foundation.SitecoreExtensions" resolve="true"/>
</Handlers>
</param>
</param>
</processor>
</mvc.renderRendering>
</pipelines>
</sitecore>
</configuration>

Quick gist of above gist :

We are handling our custom pipeline after SxaPageModeRenderingErrorStrategy which is logging exception as HTML comment on the page when the site is in normal mode and show error on page when the site is in experience editor mode (That part is done by OOTB handler). You can change it as per your need.

In case you want to disable this functionality in any environment. you can set SCBasics.IsCustomErrorEnabled to false

That’s it – Happy Exception Handling! 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: