World is now on Opti ID! Learn more
World is now on Opti ID! Learn more
Try using FindAllPagesWithCriteria instead of FindPagesWithCriteria
FYI - FindPagesWithCriteria returns all matching pages that the current user has read access for, whereas FindAllPagesWithCriteria returns all pages regardless of permissions.
Something like this?
var contentTypeRepository = ServiceLocator.Current.GetInstance<IContentTypeRepository>();
var contentModelUsage = ServiceLocator.Current.GetInstance<IContentModelUsage>();
var contentType = contentTypeRepository.Load<ArticlePage>();
var allArticlePages = contentModelUsage.ListContentOfContentType(contentType);
IContentModelUsage is awesome, but might give you more than you want.
ListContentOfContentType will give you every version of the content, each version in every language. So, if a page has been publisedh 5 times, and therefore has 5 versions; then that page will be listed 5 times here.
To fix this you can remove duplicate entries and convert ContentLink to non-versioned.
Add the following extension method to your code. Then you have the following method available: contentModelUsage.ListContentWithoutVersionOfContentType(contentType);
using EPiServer.Core;
using EPiServer.DataAbstraction;
using System.Collections.Generic;
using System.Linq;
namespace EPiServer.Core;
public static class IContentModelUsageExtensions
{
/// <summary>
/// Lists all content of desired type, without versions.
/// </summary>
public static IEnumerable<ContentUsage> ListContentWithoutVersionOfContentType(this IContentModelUsage contentModelUsage, ContentType contentType)
=> contentModelUsage.ListContentOfContentType(contentType)
.DistinctBy(_ => (_.ContentLink.ID, _.LanguageBranch))
.Select(content => new ContentUsage
{
ContentLink = content.ContentLink.ToReferenceWithoutVersion(),
LanguageBranch = content.LanguageBranch,
Name = content.Name
})
.ToArray();
}
Thomas, do you aggree? 😊
Yes, you are correct Tommy, but that's not the only case where IContentModelUsage could return more than you expect.
If you want usage of a block type, and that block type is used as a property on other content types – you will get both direct instances of the block type, and instances of content types that use the block type as a property (local block).
Under the hood, the SQL stored procedures netPageTypeGetUsage and netBlockTypeGetUsage are used. If you have specific needs, or deal with blocks that are used both as content types and local blocks, you could be better off writing your own stored procedure. IContentModelUsage could be confusing.
Here are the helper methods I have used to get all pages and blocks of a certain content type:
/// <summary>
/// Returns the children with type <typeparamref name="T">T</typeparamref> of the <paramref name="rootLink">root</paramref> recursively.
/// </summary>
/// <typeparam name="T">A page type of type SitePageData</typeparam>
/// <param name="rootLink">Root page to start looking</param>
/// <param name="getPublishedPagesOnly"></param>
/// <returns></returns>
public static IEnumerable<T> GetAllChildrenOfType<T>(ContentReference rootLink, bool getPublishedPagesOnly)
where T : PageData
{
var loader = ServiceLocator.Current.GetInstance<IContentLoader>();
var publishedStateAssessor = ServiceLocator.Current.GetInstance<IPublishedStateAssessor>();
bool Predicate(PageData x) =>
getPublishedPagesOnly
? publishedStateAssessor.IsPublished(x, PagePublishedStatus.Published)
: publishedStateAssessor.IsPublished(x, PublishedStateCondition.None);
var children = loader.GetChildren<PageData>(rootLink).Where(Predicate);
foreach (var child in children)
{
if (child is T childOfRequestedType && child.IsEPiServerPage())
{
yield return childOfRequestedType;
}
foreach (var descendant in GetAllChildrenOfType<T>(child.ContentLink, getPublishedPagesOnly))
{
yield return descendant;
}
}
}
public static List<T> GetAllBlocksOfType<T>(bool filterPublished = true) where T : IContentData
{
var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();
var contentTypeRepository = ServiceLocator.Current.GetInstance<IContentTypeRepository>();
var contentModelUsage = ServiceLocator.Current.GetInstance<IContentModelUsage>();
// get all usages of MyBlock, including versions
var contentType = contentTypeRepository.Load<T>();
var contentUsages = contentModelUsage.ListContentOfContentType(contentType);
// get distinct content references without version
var contentReferences = contentUsages
.Select(x => x.ContentLink.ToReferenceWithoutVersion())
.Distinct()
.ToList();
// fetch data from DB
var instances = contentReferences
.Select(contentReference => contentLoader.Get<IContent>(contentReference))
.ToList();
// remove unpublished
if (filterPublished)
{
new FilterPublished().Filter(instances);
}
var result = instances.Cast<T>().ToList();
return result;
}
I want to get all pages with type of ArticlePage from a controller of a partial.
Currently I have this code and pages is null?