Guide to setting up secure Content Approval Workflows – 1 of 2 – Johnny Mullaney
Guide to setting up secure Content Approval Workflows – 2 of 2 – Johnny Mullaney
Related to my previous series on setting up Secure Content Approval Workflows, I had a discussion with someone who followed the steps but their ERP Integration API was sporadically throwing the following error when updating content:
System.ComponentModel.DataAnnotations.ValidationException: Content is locked by ‘Epi Admin’ with lock identifier ‘contentapproval’
What Causes the Error?
This error is thrown when a version of content is in the middle of an approval workflow and the EPiServer Content Repository attempts to update the content. The error is saying that EPiServer will not allow this content to get updated while it is going through an approval workflow.
This makes perfect sense as if content is partially approved, we don’t really want to be updating it.
However the scenario explained to me by the developer and agreed with the client, was that this content should be updated regardless of the approval sequence.
Content Lock Evaluator
EPiServer’s IContentLockEvaluator determines if content is locked for editing under given circumstances. The default implementation is this internal class is as below.
internal class ContentApprovalLockEvaluator : IContentLockEvaluator
{
public static string Identifier = "contentapproval";
private readonly IContentVersionRepository _contentVersionRepository;
private readonly IApprovalRepository _approvalRepository;
public ContentApprovalLockEvaluator(
IContentVersionRepository contentVersionRepository,
IApprovalRepository approvalRepository)
{
this._contentVersionRepository = contentVersionRepository;
this._approvalRepository = approvalRepository;
}
public ContentLock IsLocked(ContentReference contentLink)
{
ContentVersion contentVersion = this._contentVersionRepository.Load(contentLink);
if (contentVersion == (ContentVersion) null)
return (ContentLock) null;
if (contentVersion.Status != VersionStatus.AwaitingApproval)
return (ContentLock) null;
ContentApproval result = this._approvalRepository.GetAsync(contentLink).Result;
if (result == null)
return (ContentLock) null;
return result.Status != ApprovalStatus.InReview ? (ContentLock) null : new ContentLock(contentLink, result.StartedBy, ContentApprovalLockEvaluator.Identifier, result.Started);
}
}
Content in an approval workflow will return a lock status and block any updates.
Solution
The solution for this use case was to inject our custom implementation of the Content Lock Evaluator to allow content in an approval workflow to be updated. Our implementation would simply return null meaning the content is not locked.
public class CustomContentLockEvaluator : IContentLockEvaluator
{
public ContentLock IsLocked(ContentReference contentLink)
{
return null;
}
}
Warning
Proceed with caution. This was the solution in a very specific integration where the risks of removing the Content Lock logic was considered and understood by all.
Depending on your situation, consider maintaining as much of the logic in the default EPiServer implementation as possible.