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
- 检查ContentType无需通过名称匹配,直接用
修正集合比较逻辑,避免误判
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
相关产品推荐
相关产品推荐

