LibrarySites.Banner

Handling Errors in the Sitecore ASP.NET CMS

This blog post explains how you can override the ExecuteRequest processor in the httpRequestBegin pipeline to control how the Sitecore ASP.NET web Content Management System (CMS) handles some kinds of errors.

As specified in the Sitecore Presentation Component API Cookbook linked in the Resource section at the end of this blog post, under certain error conditions, the ExecuteRequest processor in the httpRequestBegin pipeline may redirect or transfer to the error pages specified. For example, if layout details do not specify a layout for the context device for the context item, the ExecuteRequest processor redirects to the URL specified by the LayoutNotFoundUrl setting in the Web.config file. Technically, if the RequestErrors.UseServerSideRedirect setting in the Web.config file is true, Sitecore invokes the System.Web.HttpContext.Current.Server.Transfer() method; otherwise it invokes the System.Web.HttpContext.Current.Response.Redirect() method.

You might want to handle these types of error conditions differently. For example, you might want to log the condition or throw an potentially throw an exception rather than redirecting. If you throw an exception, ASP.NET should handle it according to how you configure the /configuration/system.web/customErrors element in the /web.config file, which you cannot configure with a Sitecore Web.config include file.

To override the default logic for handling such error conditions, you can implement a solution based on the following prototype. For most error conditions, this prototype simply logs a warning and invokes the corresponding logic in the default implementation. When a layout does not exist for an item or the context user does not have read access to the definition item for that layout, this solution logs a warning and throws an exception.

namespace Sitecore.Sharedsource.Pipelines.HttpRequest
{
  using System;
  using System.Web;
  
  using SC = Sitecore;
  
  public class ExecuteRequest : SC.Pipelines.HttpRequest.ExecuteRequest
  {
    protected override void RedirectOnLayoutNotFound(string url)
    {
      SC.Diagnostics.Log.Warn(
        this + " : No layout for " + HttpContext.Current.Request.RawUrl + " (" + Sitecore.Context.User + " - " + Sitecore.Context.Device.Name + ")",
        this);
  
      if (true)
      {
        throw new Exception("No layout.");
      }
      else
      {
        base.RedirectOnLayoutNotFound(url);
      }
    }
  
    protected override void RedirectOnItemNotFound(string url)
    {
      SC.Diagnostics.Log.Warn(
        this + " : No item for " + HttpContext.Current.Request.RawUrl + " (" + Sitecore.Context.User.Name + ")",
        this);
  
      if (false)
      {
        throw new Exception("No item.");
      }
      else
      {
        base.RedirectOnItemNotFound(url);
      }
    }
  
    protected override void RedirectOnNoAccess(string url)
    {
      SC.Diagnostics.Log.Warn(
        this + " : No access for " + HttpContext.Current.Request.RawUrl + " (" + Sitecore.Context.User.Name + ")"
        this);
  
      if (false)
      {
        throw new Exception("No access.");
      }
      else
      {
        base.RedirectOnNoAccess(url);
      }
    }
  
    protected override void RedirectOnSiteAccessDenied(string url)
    {
      SC.Diagnostics.Log.Warn(
        this + " : No site access for " + HttpContext.Current.Request.RawUrl + " (" + Sitecore.Context.User.Name + ")"
        this);
  
      if (false)
      {
        throw new Exception("No site access.");
      }
      else
      {
        base.RedirectOnSiteAccessDenied(url);
      }
    }
  }
}

You can use a Web.config include file based on the following (Sitecore.Sharedsource.ExecuteRequest.config in my case) to enable this processor:

<configuration xmlns:patch="https://www.sitecore.com/xmlconfig/">
  <sitecore>
    <pipelines>
      <httpRequestBegin>
        <processor type="Sitecore.Pipelines.HttpRequest.ExecuteRequest, Sitecore.Kernel">
          <patch:attribute name="type">Sitecore.Sharedsource.Pipelines.HttpRequest.ExecuteRequest,Sitecore.Sharedsource</patch:attribute>
        </processor>
      </httpRequestBegin>
    </pipelines>
  </sitecore>
</configuration>

Resources