ForceCurrentVersion 对 EPiServer 中已发布内容的奇怪行为

Strange behaviour with ForceCurrentVersion on published content in EPiServer

如果您尝试保存一些设置了 ForceCurrentVersion 标志的 published 内容,在看似不合逻辑的情况下它会失败。例如:

contentRepository.Save(publishedPage, SaveAction.ForceCurrentVersion);

会导致错误:

ERROR: The provided action 'ForceCurrentVersion' is not allowed on this content (ContentLink=257864_794789, VersionStatus=Published)

但是,如果我添加 SaveAction.Publish,这运行得很好:

contentRepository.Save(publishedPage, SaveAction.Publish | SaveAction.ForceCurrentVersion)

这有什么逻辑吗?


我为什么要问?

在升级到最新版本的 EPiServer 之前,以下代码对于 publishedunpublished 内容都非常有效:

// On the CreatedContent event

MakeTheShortUrlLowerCase(writablePage);

// Save without creating a new version:
contentRepository.Save(writablePage, SaveAction.ForceCurrentVersion | SaveAction.SkipValidation);

但升级后,保存功能的行为seem to have changed。为了让它再次工作,我们不得不通过对已发布内容的额外检查来使代码复杂化:

// On the CreatedContent event

MakeTheShortUrlLowerCase(writablePage);

// Check if published, then select save alternative
if (pageData.CheckPublishedStatus(PagePublishedStatus.PublishedIgnoreDates))
{
    contentRepository.Save(writablePage, SaveAction.Publish | SaveAction.ForceCurrentVersion | SaveAction.SkipValidation);
}
else
{
    contentRepository.Save(writablePage, SaveAction.ForceCurrentVersion | SaveAction.SkipValidation);
}

对我来说,这个 "fix" 似乎有些不必要,而且确实没有多大意义。


更新

为了将来参考,这是我最终做的事情:我实现了一个简单的助手 class 来处理使用 ForceCurrentVersion 的情况:

    private static SaveAction GetForcedSaveActionFor(IVersionable page)
    {
        var saveAction = SaveAction.SkipValidation | SaveAction.ForceCurrentVersion;
        switch (page.Status)
        {
            case VersionStatus.Published:
                saveAction = saveAction | SaveAction.Publish;
                break;
            case VersionStatus.CheckedIn:
                saveAction = saveAction | SaveAction.CheckIn;
                break;
            default:
                saveAction = saveAction | SaveAction.Save;
                break;
        }
        return saveAction;
    }

然后可以按如下方式使用:

            var saveAction = GetForcedSaveActionFor(pageData);
            contentRepository.Save(writablePage, saveAction);

这自然不会涵盖 VersionStatus 的所有情况,但您明白了。

我很确定您在第一次保存内容时不能使用 SaveAction.ForceCurrentVersion,即 "force" 没有以前的版本。一直都是这样。

我记得您不能将 ForceCurrentVersionPublish 结合使用,也就是说,您不能覆盖已发布的版本?它不会抛出异常,但您会有效地获得一个新版本(即您会在版本列表中看到内容的 先前发布 版本)。

ForceCurrentVersion 隐式表示 Save,尽管您不能再像 SaveAction.Save | SaveAction.ForceCurrentVersion 那样显式组合它们(抛出异常):http://world.episerver.com/documentation/Items/Upgrading/EPiServer-CMS/8/Breaking-changes/

SaveActions 枚举有一些非正统的拆分,其中一些值代表主要 命令(保存、发布、签入等),一些值代表不同的 选项(ForceCurrentVersion,SkipValidation)。

当仅将选项标志传递给 Save 方法时,您实际上只传递了 options 而没有任何 command。以前使用尽力而为的方法来找出在没有提供命令的情况下将使用哪个命令,但事实证明,在很多情况下这不是很可预测,并且还会导致内容在没有发布的情况下发布正在引发事件并发布要完成的特定验证。

已尝试针对 CMS 8 改善这种情况,现在要求您在更新已发布的内容时提供包含主要命令的 SaveAction。不幸的是,这会产生副作用,您需要更明确地说明应该使用哪个 SaveAction 命令。希望您能够隐藏实用方法背后的评估。

当前的解决方案在可用性方面还有很多不足之处,并且此代码中仍然存在边缘情况下的不规则性,但是由于很难在不进行重大更改的情况下在此处进行任何改进,因此进展可能会很慢。

更新

以上答案仅适用于 Episerver CMS 版本 9。此行为在 CMS 10 中已更改,SaveAction.ForceCurrentVersion 现在可以独立使用,无需将其与其他操作结合使用。有关此更新的详细信息,请参阅 this CMS 10 release note