How to prevent publishing a page with unpublished blocks or assets
EPiServer has a very powerful validation engine which is easily pluggable with custom validation rules.
I've been asked by a colleague to write a validation rule which would prevent a page from being published if it referenced an unpublished dependency (block/asset/...).
I thought it might be useful for some of you.
We need to hook to IContentEvents.PublishingEvent. We can do that from an initializable module:
[InitializableModule]
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class PublishEventInitializationModule : IInitializableModule
{
private DependenciesResolver dependenciesResolver;
public void Initialize(InitializationEngine context)
{
//Add initialization logic, this method is called once after CMS has been initialized
var contentEvents = ServiceLocator.Current.GetInstance<IContentEvents>();
contentEvents.PublishingContent += contentEvents_PublishingContent;
dependenciesResolver = ServiceLocator.Current.GetInstance<DependenciesResolver>();
}
void contentEvents_PublishingContent(object sender, EPiServer.ContentEventArgs e)
{
var dependencies = dependenciesResolver.GetUnpublishedDependencies(e.ContentLink).ToList();
if (!dependencies.Any()) return;
var text = dependencies.Count == 1 ? "dependency" : "dependencies";
e.CancelAction = true;
e.CancelReason =
$"You can't publish because you have {dependencies.Count} unpublished {text}. {string.Join(',', dependencies.Select(x => $"{x.Name} [{x.ContentLink}] "))}";
}
public void Preload(string[] parameters)
{
}
public void Uninitialize(InitializationEngine context)
{
//Add uninitialization logic
var contentEvents = ServiceLocator.Current.GetInstance<IContentEvents>();
contentEvents.PublishingContent -= contentEvents_PublishingContent;
}
}
As you can see we calculate unpublished dependencies and cancel the operation if necessary.
DependencyResolver traverses the dependencies, both direct and nested, so validation will still fail if for example a page depends on an ImageBlock which has an unpublished ImageData.
Full gist is here: https://gist.github.com/barteksekula/78ff1df20df2f2449497d94c218cfdad
You can just copy paste the file to your project and it will work like this:
Comments