This may be a little broad so I'd appreciate any pointers.

Is there a way to replace the typical 404 response with 410 for pages that have been deleted? Obviously I'd like to keep 404 responses for genuine 404's.

Thanks.

up vote 5 down vote accepted

You certainly could, but it requires a couple moving parts:

Track the pages when they are deleted so you can look them up later

To know whether a requested URL used to exist or not, you'll need to track pages as they're deleted so you can check that list later.

You'll need an item:deleted event handler:

public class PageDeletionLogger
{
    public void ItemDeleted(object sender, EventArgs args)
    {
        var deletedItem = Event.ExtractParameter(args, 0) as Item;
        var formerParentId = Event.ExtractParameter(args, 1) as ID;

        if (deletedItem == null || formerParentId == (ID)null || formerParentId == ID.Null)
            return;

        // If this item is being manipulated in a different database (e.g. "web" because it's being published), ignore it
        if (!"master".Equals(deletedItem.Database?.Name, StringComparison.OrdinalIgnoreCase))
            return;

        // If this item is a template or a branch, ignore it
        if (deletedItem.Paths.Path.StartsWith("/sitecore/templates/"))
            return;

        // Ignore items that aren't pages
        if (!TemplateManager.GetTemplate(deletedItem).IsDerived(new ID("id-of-base-page-template")))
            return;

        // TODO:Log the page details/URL here
    }
}

(And you'll need this handy template checking method [beware: it's recursive]):

public static class TemplateExtensions
{
    public static bool IsDerived([NotNull]this Template template, [NotNull]ID templateId)
    {
        return template.ID == templateId || template.GetBaseTemplates().Any(baseTemplate => IsDerived(baseTemplate, templateId));
    }
}

And you'll need to patch it into config:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
    <sitecore>
        <events>
            <event name="item:deleted">
                <handler type="Custom.Events.PageDeletionLogger,Custom" method="ItemDeleted" />
            </event>
        </events>
    </sitecore>
</configuration>

Look them up as part of the HttpRequestBegin pipeline

Then, when incoming requests are processed, you'll need to look them up in your list of deleted pages and see whether they should get a 410 or 404.

public class DeletedPageResolver : HttpRequestProcessor
{
    public override void Process(HttpRequestArgs args)
    {
        // If we resolved a context item, get out
        if (Sitecore.Context.Item != null)
            return;

        var listOfDeletedPageUrls = // TODO: Get the list of deleted page URLs
        if (listOfDeletedPageUrls.Contains(args.Context.Request.RawUrl))
        {
            // TODO: Set your 410 HTTP status code
        }
    }
}

And, of course, you'll need to patch that into config, too:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
    <sitecore>
        <pipelines>
            <httpRequestBegin>
                <processor type="Custom.Processors.HttpRequestBegin.DeletedPageResolver, Custom" patch:after="processor[@type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']"/>
            </httpRequestBegin>
        </pipelines>
    </sitecore>
</configuration>

Disclaimer

I've not worked with the 410 status code before, so it's possible you'll need to do more to avoid having the page redirect to an error page (e.g. resolve the Sitecore.Context.Item to a page that has the 410 error content you want to display).

  • Superb, thanks a lot - this is far more than I had hoped for. – Sean T Oct 17 at 15:11

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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