You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Episerver计划任务开发:排除指定页面的HeroBlock并设置属性

Episerver计划任务优化建议:排除特定页面内的Block

需求说明:开发Episerver计划任务,为HeroBlock设置指定属性,但需要排除主题为"ABC"的站点中,隶属于ArticlePage的HeroBlock。以下是当前实现代码,结合Episerver最佳实践给出优化建议:

当前实现代码

var contentType = _contentTypeRepository.Load(typeof(HeroBlock));

var heroBlockContentReferences = _contentModelUsage.ListContentOfContentType(contentType)
    .Select(contentUsage => contentUsage.ContentLink.ToReferenceWithoutVersion())
    .Distinct()
    .ToList();

foreach (var siteDefinition in _siteDefinitionRepository.List())
{
    var heroBlocksWithinArticlePages = new List<HeroBlock>();

    var startPage = _contentLoader.Get<StartPage>(siteDefinition.StartPage);

    // 按站点过滤HeroBlock引用
    var heroBlocks = heroBlockContentReferences
        .Where(contentReference => _siteDefinitionResolver.GetByContent(contentReference, true, true).Name == siteDefinition.Name)
        .Select(contentReference => _contentRepository.Get<HeroBlock>(contentReference))
        .ToList();

    if (!heroBlocks.Any())
    {
        continue;
    }

    if (startPage.ThemeName.Equals("ABC"))
    {
        var articlePages = _contentLocator.GetAll<ArticlePage>(startPage.ContentLink);
        foreach (var articlePage in articlePages)
        {
            var filteredHeroBlocks = articlePage.MainContentArea.FilteredItems
                .Select(contentItem => _contentRepository.Get<IContent>(contentItem.ContentLink))
                .Where(content => _contentTypeRepository.Load(content.ContentTypeID).Name.Equals("HeroBlock"))
                .Select(content => _contentRepository.Get<HeroBlock>(content.ContentLink));

            heroBlocksWithinArticlePages.AddRange(filteredHeroBlocks);
        }
    }

    foreach (var heroBlock in heroBlocks.Except(heroBlocksWithinArticlePages))
    {
        var writableCloneHeroBlock = (HeroBlock)heroBlock.CreateWritableClone();
        // 设置需要修改的属性
        _contentRepository.Save((IContent)writableCloneHeroBlock, EPiServer.DataAccess.SaveAction.Publish, EPiServer.Security.AccessLevel.Read);
    }
}

优化建议

  • 提升查询效率,减少不必要的Content加载

    • 检查ContentType无需通过名称匹配,直接用content is HeroBlock类型判断即可,避免重复调用_contentTypeRepository.Load
    • 原代码中先获取所有HeroBlock引用再逐个Get,可改为直接用_contentLocator.GetAll<HeroBlock>()并按站点过滤,减少多次_contentRepository.Get调用
    • 查找ArticlePage内的HeroBlock时,无需遍历所有ArticlePage再检查ContentArea,可通过EPiServer内容关系查询,直接获取父级为ArticlePage的HeroBlock
  • 修正集合比较逻辑,避免误判

    • heroBlocks.Except(heroBlocksWithinArticlePages)依赖对象实例的Equals方法,而IContent实例的Equals不一定基于ContentLink,建议改为通过ContentLink区分:
      var excludedLinks = heroBlocksWithinArticlePages.Select(b => b.ContentLink.ToReferenceWithoutVersion()).ToHashSet();
      var targetHeroBlocks = heroBlocks.Where(b => !excludedLinks.Contains(b.ContentLink.ToReferenceWithoutVersion()));
      
  • 增加异常处理与空值检查

    • 计划任务需处理_contentLoader.Get<StartPage>可能返回null的情况,避免空引用异常
    • 保存内容时添加try-catch块,捕获权限不足、内容已被修改等异常,防止单个内容保存失败导致整个任务终止
  • 优化保存操作

    • 保存时的AccessLevel.Read不符合权限逻辑,建议使用AccessLevel.NoAccess(表示不修改权限)或对应操作的权限
    • 若修改内容数量较多,考虑批量保存或分批次处理,减少数据库交互次数
  • 代码结构精简

    • 提取重复逻辑为独立方法,比如GetHeroBlocksForSite、GetExcludedHeroBlocksFromArticlePages,提升代码可读性与可维护性

内容的提问来源于stack exchange,提问作者Ms1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 14:25:28