Beware of IContentLoader.GetChildren() for CatalogContent

This is more of a self-to-note.

If you are using IContentLoader.GetChildren<T>(ContentReference), one important thing to remember is this uses the current preferred language. Normally when you get children of a catalog, or a node, that would not be a problem, because a catalog entity – node or entry, will be available in every language supported by the catalog. So if you just want to get the children references, the language is not important. (Note that, if you just need the children references, IRelationRepository should be a faster, more lightweight way to go, but that’s another story). If you want to get children in a specific language – which is the most common case, you know that you can use the other overload of GetChildren<T>(ContentReference, ILanguageSelector) , where you can specify the language you want to load.

Well, there is an exception for everything, and in this case, it’s when T is CatalogContent . So what’s wrong with this code:

var catalogs = _contentLoader.GetChildren<CatalogContent>(_referenceConverter.GetRootLink())

If you can’t spot it – don’t blame yourself. I made the mistake too. And not just once. Twice.

The problem here is that Catalog is the special catalog entity – in term that it can have languages on its own. And that would be a “gotcha!” moment when some of your catalogs do not appear in the result.

You can be surprised if Swedish Fashion is not returned.

If you develop a site with a known set of catalogs (or may be just one), this issue can be discovered quite early. But if you are working on different catalog sets which are unknown when you build the site, or even more, if you are working on a framework level (like I am), then this can be well hidden from your testing, only to come back and bite you later.

Now if you want to get all catalogs, here’s the correct way to do it:

var catalogs = _contentLoader.GetChildren<CatalogContent>(_referenceConverter.GetRootLink(), new LoaderOptions() { LanguageLoaderOption.MasterLanguage() });

This will return all catalogs, regardless of their language settings.

 

6 thoughts on “Beware of IContentLoader.GetChildren() for CatalogContent

  1. Good tip! Generally I’d recommend always using the language specific overloads to everything in IContentLoader. 🙂 You can send in the preferred current language if so, but it makes the API call and purpose a bit more clear and at the same time you safe guard for eventual cases like the one described above 😛

  2. Hi Quan.
    How can I get the Catalog for a specific node. In your example Fashion seems to be the only Catalog, but what if we have more?

    Thanks!

  3. Hi, as you said above we can get all the products which are under master language even we are running in different cultural specific language.
    Still I am facing some issue in getting all the products from the CMS.

    private void GetAllIndexItemsRecursive(ConcurrentBag list, ContentReference contentReference)
    {
    var nodes = contentLoader.GetChildren(contentReference, CultureInfo.GetCultureInfo(“en”));
    _ = Parallel.ForEach(
    nodes,
    node =>
    {
    try
    {
    var sw = Stopwatch.StartNew();
    PopulateIndexedItems(node, list);

    GetAllIndexItemsRecursive(list, node.ContentLink);
    sw.Stop();
    log.Error($”{node.ContentLink}, {sw.ElapsedMilliseconds} ms”);
    }
    catch (Exception e)
    {
    log.Error($”Index error, {e.Message}”, e);
    }
    });
    }

    Its giving different count of records each time I am running! with respect to different site language.

Leave a Reply

Your email address will not be published. Required fields are marked *