What if you get a fresh instance of the page from content repository at moved event?
Same thing then.
Just realized that e.Content (or if you fetch from IContentRepository) is exactly the same on MovedContent as it is in MovingContent. Shouldn't MovedContent show how the content looks after the move or am i misunderstanding something?
This got to be considered a bug.
Just reflected the EPiServer.Core.dll and looked in the DefaultContentRepository.cs file. Here we can see what happens when you move something to waste basket:
public override void MoveToWastebasket(ContentReference contentLink, string deletedBy) { if (ContentReference.IsNullOrEmpty(contentLink)) { throw new System.ArgumentNullException("contentLink", "Parameter has no value set"); } ContentProvider provider = this._providerManager.GetProvider(contentLink.ProviderName); DefaultContentRepository.CheckCapabilities(provider, ContentProviderCapabilities.Delete); ContentReference contentLink2 = contentLink.ToReferenceWithoutVersion(); IContent content = this.Get<IContent>(contentLink2, NullLanguageSelector.Instance); ContentEventArgs eventArgs = new MoveContentEventArgs(contentLink, provider.WastebasketReference) { RequiredAccess = AccessLevel.Delete, OriginalParent = content.ParentLink, Descendents = this.GetDescendents(contentLink), Content = content }; this._contentEventsHandler.RaiseCancellableContentEvent("MovingEvent", "Moving content was cancelled by event handler.", eventArgs); if (!this._accessChecker.HasSufficientAccess(provider, contentLink, AccessLevel.Delete)) { throw new AccessDeniedException(contentLink, string.Format("The current user does not have sufficient rights to delete the page with id {0}", contentLink)); } if (provider.IsDefaultProvider && this._providerManager.HasEntryPointChild(contentLink)) { throw new CannotMoveProviderException("This page or some of it's descendants is parent to a page provider and it can't be deleted. Please remove page provider first in web.config file."); } provider.MoveToWastebasket(contentLink, deletedBy); this._contentEventsHandler.RaiseContentEvent("MovedEvent", eventArgs); }
As you see, the same eventArgs are sent to both MovingEvent and MovedEvent so no wonder that e.Content looks the same on both events. Not sure if this might have been fixed in later versions of EPiServer. (this customer is running epi 7.5).
If we look into the Publish method....
internal override void Publish(ContentReference contentLink, System.DateTime? delayPublishUntil, AccessLevel access) { if (ContentReference.IsNullOrEmpty(contentLink)) { throw new System.ArgumentNullException("contentLink"); } if (contentLink.WorkID == 0) { throw new System.ArgumentException("The version must be specified when publishing content", "contentLink"); } if (delayPublishUntil.HasValue && !PropertyDate.IsValidDate(delayPublishUntil.Value)) { throw new System.ArgumentOutOfRangeException("delayPublishUntil", string.Format("Publish date '{0}' must be a date between '{1}' and '{2}'.", delayPublishUntil.Value, PropertyDate.MinValue, PropertyDate.MaxValue)); } IContent content = this.Get<IContent>(contentLink, NullLanguageSelector.Instance); bool hasValue = delayPublishUntil.HasValue; SaveAction action = hasValue ? ((SaveAction)1026) : SaveAction.Publish; SaveContentEventArgs saveContentEventArgs = this._contentEventsHandler.CreateSaveEventArgs(content, action, access); this.RaisePreSaveEvents(saveContentEventArgs, false, false); if (!DefaultContentRepository.VerifyPreviousStateForPublishing(saveContentEventArgs.Content)) { return; } ContentProvider contentProvider = this.GetContentProvider(contentLink, false); DefaultContentRepository.CheckCapabilities(contentProvider, ContentProviderCapabilities.Edit); this.CheckSufficientAccess(contentProvider, contentLink, access); if (!hasValue) { contentProvider.Validate(content, (SaveAction)515); } saveContentEventArgs.ContentLink = contentProvider.UpdateStatus(content, action, delayPublishUntil); this._cacheManager.RemoveLocal(DataFactoryCache.ContentVersionCacheKey(saveContentEventArgs.ContentLink)); saveContentEventArgs.Content = this.Get<IContent>(saveContentEventArgs.ContentLink, NullLanguageSelector.Instance); this.RaisePostSaveEvents(content, saveContentEventArgs, false, false); }
Here we see that before the PublishedContent is called (which is done in the RaisePostSaveEvent method) the code first clears the cache and then repopulates the Content property of the eventargs.
Knowing this I was able to get around the problem by first clearing the episerver cache for this page by calling DataFactoryCache.RemovePage(e.ContentLink) and the fetching the content again by calling ServiceLocator.Current.GetInstance<IContentRepository>().Get<IContent>(e.ContentLink).
When putting content in the recycle bin the MovedContent event is fired in the IContentEvents repository. However at that time the IsDeleted property is still set to false on e.Content.IsDeleted even though if you look in the database at the same time you can see that the Deleted column is set to 1. Why is that and is there a better way of checking if a page is moved to recycle bin other than looking at the TargetLink property of the ContentEventArgs?