This morning I discovered that items are permanently deleted by the Sitecore Item Web API during a delete action. This is probably called out somewhere in its developer’s guide but I don’t recall having read this.
Regardless of whether it’s highlighted somewhere in documentation, I decided to investigate why this happens.
After combing through Sitecore Item Web API pipelines defined in \App_Config\Include\Sitecore.ItemWebApi.config and code in Sitecore.ItemWebApi.dll, I honed in on the following:
This above code lives in the only itemWebApiDelete pipeline processor that comes with the Sitecore Item Web API, and this processor can be found at /configuration/sitecore/pipelines/itemWebApiDelete/processor[@type=”Sitecore.ItemWebApi.Pipelines.Delete.DeleteScope, Sitecore.ItemWebApi”] in the \App_Config\Include\Sitecore.ItemWebApi.config file.
I don’t know about you, but I’m not always comfortable with deleting items permanently in Sitecore. I heavily rely on Sitecore’s Recycle Bin — yes, I have deleted items erroneously in the past, but recovered quickly by restoring them from the Recycle Bin (I hope I’m not the only one who has done this. :-/)
Unearthing the above prompted me to write a new itemWebApiDelete pipeline processor that puts items in the Recycle Bin when the Recycle Bin setting — see /configuration/sitecore/settings/setting[@name=”RecycleBinActive”] in the Web.config — is enabled:
using System.Collections.Generic; using System.Linq; using Sitecore.Configuration; using Sitecore.Data; using Sitecore.Data.Items; using Sitecore.Diagnostics; using Sitecore.ItemWebApi; using Sitecore.ItemWebApi.Pipelines.Delete; namespace Sitecore.Sandbox.ItemWebApi.Pipelines.Delete { public class RecycleScope : DeleteProcessor { private const int OKStatusCode = 200; public override void Process(DeleteArgs arguments) { Assert.ArgumentNotNull(arguments, "arguments"); IEnumerable<Item> itemsToDelete = arguments.Scope; DeleteItems(itemsToDelete); arguments.Result = GetStatusInformation(OKStatusCode, GetDeletionInformation(itemsToDelete)); } private static void DeleteItems(IEnumerable<Item> itemsToDelete) { foreach (Item itemToDelete in itemsToDelete) { DeleteItem(itemToDelete); } } private static void DeleteItem(Item itemToDelete) { Assert.ArgumentNotNull(itemToDelete, "itemToDelete"); // put items in the recycle bin if it's turned on if (Settings.RecycleBinActive) { itemToDelete.Recycle(); } else { itemToDelete.Delete(); } } private static Dynamic GetDeletionInformation(IEnumerable<Item> itemsToDelete) { return GetDeletionInformation(itemsToDelete.Count(), GetItemIds(itemsToDelete)); } private static Dynamic GetDeletionInformation(int count, IEnumerable<ID> itemIds) { Dynamic deletionInformation = new Dynamic(); deletionInformation["count"] = count; deletionInformation["itemIds"] = itemIds.Select(id => id.ToString()); return deletionInformation; } private static IEnumerable<ID> GetItemIds(IEnumerable<Item> items) { Assert.ArgumentNotNull(items, "items"); return items.Select(item => item.ID); } private static Dynamic GetStatusInformation(int statusCode, Dynamic result) { Assert.ArgumentNotNull(result, "result"); Dynamic status = new Dynamic(); status["statusCode"] = statusCode; status["result"] = result; return status; } } }
There really isn’t anything magical about the code above. It utilizes most of the same logic that comes with the itemWebApiDelete pipeline processor that ships with the Sitecore Item Web API, although I did move code around into new methods.
The only major difference is the invocation of the Recycle method on item instances when the Recycle Bin is enabled in Sitecore. If the Recycle Bin is not enabled, we call the Delete method instead — as does the “out of the box” pipeline processor.
I then replaced the existing itemWebApiDelete pipeline processor in \App_Config\Include\Sitecore.ItemWebApi.config with our new one defined above:
<?xml version="1.0" encoding="utf-8"?> <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> <sitecore> <pipelines> <!-- stuff is defined up here --> <itemWebApiDelete> <processor type="Sitecore.Sandbox.ItemWebApi.Pipelines.Delete.RecycleScope, Sitecore.Sandbox" /> </itemWebApiDelete> <!-- there's more stuff defined down here --> </sitecore> </configuration>
Let’s see this in action.
We first need a test item. Let’s create one together:
I then tweaked the delete method in my copy of the console application written by Kern Herskind Nightingale, Director of Technical Services at Sitecore UK, to point to our test item in the master database — I have omitted this code for the sake of brevity — and then ran the console application calling the delete method only:
As you can see, our test item is now in the Recycle Bin:
If you have any thoughts on this, please leave a comment.
Good post, thanks. One thought: I believe that Recycle() winds up calling Delete() if the recycle bin is active, so you could just call Recycle().
You are correct — good catch!
Mike