SaaS CMS has officially launched! Learn more now.

Get all instances of a certain block type in EPiServer 8

Vote:
 

I may have missed the deep dive lesson on the EPiServer repository API's and figured there should be a simple way to retreive all blocks of a certain type that are published. But no, there seem to be no such thing and the other examples on this forum either perform horribly or are bad implementations that doesn't consider multiple versions, publish status and so on.

This is my routine at the moment, does anyone have any advice to make this a bit cleaner?

// loading a block type
var contentTypeRepository = ServiceLocator.Current.GetInstance();
var blockType = contentTypeRepository.Load();

// get usages, this also includes versions
var contentModelUsage = ServiceLocator.Current.GetInstance();
var usages = contentModelUsage.ListContentOfContentType(blockType);

var repository = ServiceLocator.Current.GetInstance();
var contactBlocks =
    usages.Select(u => repository.Get(u.ContentLink))
        .Where(x =>
            // ...filter published
            (x as IVersionable).Status.Equals(VersionStatus.Published)
            // remove deleted
            && !x.IsDeleted)
        .FilterForVisitor()
        .Cast();



Thanks

#122911
Jun 17, 2015 15:30
Vote:
 

Hi,

You could try to use FindPagesWithCriteria:

            var criterias = new PropertyCriteriaCollection();

            var criteria = new PropertyCriteria();
            criteria.Condition = CompareCondition.Equal;
            criteria.Name = "PageTypeID";
            criteria.Type = PropertyDataType.PageType;
            criteria.Value = _cotentTypeRepository.Load<RoomTypeList>().ID.ToString();
            criteria.Required = true;

            criterias.Add(criteria);


            ServiceLocator.Current.GetInstance<IPageCriteriaQueryService>()
                .FindAllPagesWithCriteria(ContentReference.RootPage, criterias , null, LanguageSelector.AutoDetect());
#122913
Jun 17, 2015 15:35
Vote:
 

I don't think FindPagesWithCriteria works with Blocks yet.

It's still a bit messy but this is what I've done:

public IEnumerable<T> GetBlocksOfType<T>()
    where T : BlockData
{
    BlockType blockTypeForT = ServiceLocator.Current.GetInstance<BlockTypeRepository>().Load<T>();
    IList<ContentUsage> contentUsages =
        ServiceLocator.Current.GetInstance<IContentModelUsage>().ListContentOfContentType(blockTypeForT);

    var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();
    var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();
    List<IContent> blocks = contentUsages
        .Select(contentUsage => contentUsage.ContentLink.ToReferenceWithoutVersion())
        .Distinct()
        .Select(contentReference => contentLoader.Get<IContent>(contentReference)).ToList();

    new FilterPublished().Filter(blocks);
    new FilterAccess().Filter(blocks);

    return blocks.OfType<T>();
    new FilterPublished().Filter(iContents);
    new FilterAccess().Filter(iContents);
            
    return iContents.OfType<T>();
}

And simply call with

IEnumerable<TeaserBlock> content = GetBlocksOfType<TeaserBlock>();

As you notice ListContentOfContentType gives you all versions of the blocks. Hence I make a Select on ToReferenceWithoutVersion and a Distinct.

Instead of your Where on Deleted and Publish I send the content through the built in Filters in EPiServer. In my case my Blocks might not have Templates, hence I use Publish and Access but In if you have Templates/Views for your blocks as well you could simply do FilterForVisitor since it's a composite of the filters Publish, Access and Template. 

Due to the proxy management of Blocks in EPiServer you need to cast back and forth between IContent and T. I prefer using OfType instead of Cast. But that might be me being paranoid.

#123736
Edited, Jul 17, 2015 15:55
Vote:
 

EPiServer give a disclaimer in the xml comment at class level, but this seems to work:

var db = ServiceLocator.Current.GetInstance<EPiServer.DataAccess.Internal.ContentListDB>();
return db.ListContentOfContentType(contentType, onlyPublished);
#185341
Nov 15, 2017 16:24
Vote:
 

I would NOT recommend that. Try to avoid parts of the Episerver API that is within an "internal" namespace.

EPiServer.DataAccess.Internal.ContentListDB

#185345
Nov 15, 2017 17:22
Vote:
 

if a block is on a page that is unpublished, i cannot get reference to that page. Any idea ?

#216074
Jan 23, 2020 11:50
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.