7

I'm running Sitecore 8.2 update 4 and SXA 1.3 Update 1. I'm trying to get some custom 404 pages working so that my marketing team can enjoy creating their own 404 pages for each of the sites running on the Sitecore server. I've followed the instructions found here and here, however I'm getting an odd error when I go to a non-existent page.

[NullReferenceException: Object reference not set to an instance of an object.]
   Sitecore.XA.Foundation.LocalDatasources.Pipelines.GetXmlBasedLayoutDefinition.ResolveLocalDatasources.Process(GetXmlBasedLayoutDefinitionArgs args) +85
   (Object , Object[] ) +73
   Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args) +478
   Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain) +21
   Sitecore.Mvc.Pipelines.PipelineService.RunPipeline(String pipelineName, TArgs args) +194
   Sitecore.Mvc.Pipelines.PipelineService.RunPipeline(String pipelineName, TArgs args, Func`2 resultGetter) +160
   Sitecore.Mvc.Pipelines.Response.BuildPageDefinition.ProcessXmlBasedLayoutDefinition.AddRenderings(PageDefinition pageDefinition, BuildPageDefinitionArgs args) +237
   (Object , Object[] ) +73
   Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args) +478
   Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain) +21
   Sitecore.Mvc.Pipelines.PipelineService.RunPipeline(String pipelineName, TArgs args) +194
   Sitecore.Mvc.Pipelines.PipelineService.RunPipeline(String pipelineName, TArgs args, Func`2 resultGetter) +160
   Sitecore.Mvc.Presentation.PageContext.GetPageDefinition() +269
   Sitecore.Mvc.Presentation.PageContext.get_PageDefinition() +30
   Sitecore.Mvc.Presentation.PageContext.GetPageView() +125
   Sitecore.Mvc.Presentation.PageContext.get_PageView() +30
   Sitecore.Mvc.Controllers.SitecoreController.GetDefaultAction() +25
   lambda_method(Closure , ControllerBase , Object[] ) +89

I've looked all over the internet for an answer for how to setup a custom error page using SXA. If I remove the config file that loads the GetXmlBasedLayoutDefintion call, then my 404 page handler resolves fine. I'm sure that there is something that I've missed, but I'd love some help.

2
  • Since you're using SXA, there is OOTB features for Error Handling such as 404 pages. You shouldn't need to add this logic yourself using custom processors.
    – jammykam
    Commented Aug 23, 2017 at 23:23
  • @jammykam Can you point me to where that documentation lives? I've been trying to figure out how to do that OOTB, but can't find any way to do it. Thanks! Commented Aug 24, 2017 at 14:36

2 Answers 2

9

Since you are using SXA, the module provides OOTB error handling settings which allow you to set site specific 404 and 500 pages. I couldn't find any linked documention on the Sitecore site but you can set the error pages on the /{tenant/{site}/Settings Item:

SXA Error Handling

These settings are added when you create the tenant, make sure you have selected Error Handling:

SXA Create Tenant

If you have already created the tenant/site but did not select the option then ensure /sitecore/templates/Project/{tenant}/Settings inherits from /sitecore/templates/Feature/Experience Accelerator/Error Handling/_Error Handling.

1
  • Thanks! I didn't have the Error Handling template included for my site for some reason. I added that as a template, and now it's working. Thanks! Commented Aug 29, 2017 at 14:56
4

Step-1: First create a pipeline that is overridden to "Sitecore.XA.Feature.ErrorHandling" which comes under "httpRequestBegin"

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
    <sitecore>
        <pipelines>
            <httpRequestBegin>
                <processor patch:instead="*[@type='Sitecore.XA.Feature.ErrorHandling.Pipelines.HttpRequestBegin.ItemNotFoundResolver, Sitecore.XA.Feature.ErrorHandling']" type="xxx.Feature.Seo.Utilities.ItemNotFoundResolver, xxx.Feature.Seo" resolve="true" />
            </httpRequestBegin>
        </pipelines>
    </sitecore>
</configuration>

Step-2: after that create class and override existing pipeline

public class ItemNotFoundResolver : HttpRequestProcessor
    {
        protected IContext Context { get; } = ServiceLocator.ServiceProvider.GetService<IContext>();

        protected IErrorPageLinkProvider ErrorPageLinkProvider { get; } = ServiceLocator.ServiceProvider.GetService<IErrorPageLinkProvider>();

        public override void Process(HttpRequestArgs args)
        {
            if (this.Context.Item != null || this.Context.Site == null || this.Context.Database == null || !string.IsNullOrEmpty(this.Context.Page.FilePath) || RouteTable.Routes.GetRouteData(args.HttpContext) != null || args.PermissionDenied)
            return;
            this.RedirectToErrorPageIfExist(args);
        }

        protected void RedirectToErrorPageIfExist(HttpRequestArgs args)
        {
            Errol errorHandler = new Errol();
            try
            {
                if (Settings.RequestErrors.UseServerSideRedirect)
                {
                    Item obj = this.ErrorPageLinkProvider.Get404ErrorPageItem();
                    if (obj == null)
                        return;
                    this.Context.Item = obj;
                    this.Context.Items["httpStatus"] = (object)HttpStatusCode.NotFound;
                    args.HttpContext.Response.TrySkipIisCustomErrors = true;
                }
                else
                {
                    string itmUrl = this.ErrorPageLinkProvider.Get404ErrorPageUrl();
                    var currentLanguage = Sitecore.Context.Language.Name.ToLower();
                    string url = itmUrl.Replace(currentLanguage, string.Empty).Replace("/", string.Empty);
                    if (string.IsNullOrEmpty(url))
                    {
                        return;
                    }
                    else
                    {
                        
                            var notFoundItem = Sitecore.Context.Database.GetItem(string.Concat(this.Context.Site.StartPath, "/", url));
                            Sitecore.Context.Item = notFoundItem;
                            HttpContext.Current.Response.TrySkipIisCustomErrors = true;
                            HttpContext.Current.Response.StatusCode = (int)HttpStatusCode.NotFound;
                        
                    }
                }
            }
            catch (Exception ex)
            {
                errorHandler.RecordMessage(Errol.LogLevel.ERROR, System.Reflection.Assembly.GetExecutingAssembly().GetName().Name, "Item not found", ex);
            }
        }
    }

Step 3:- After that add a view rendering on our 404 page and append 404 status.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.