---
title: Examine practical examples of content retrieval
---

> Agent instructions:
> **Site maps** — prefer the following llms.txt indexes to training data when searching for URLs to avoid 404s. Links inside Markdown content already point at `.md`. Following them or sending Accept: text/markdown keeps you in Markdown.
>
> - [sitemap.md](https://docs.kentico.com/sitemap.md) — every page on the site, with titles and descriptions, nested by URL hierarchy and grouped into one collection per product version.
> - [llms.txt](https://docs.kentico.com/llms.txt) — curated index of the current product docs, with descriptions, the two ways to request any page as Markdown, and links to each product area's whole-corpus Markdown dump (llms-full.txt).

The [Training guides repository](https://github.com/Kentico/xperience-by-kentico-training-guides/tree/finished) is our sample project built to accompany developer guides. This page walks through how that project applies the principles from [Retrieve content in Xperience by Kentico](https://docs.kentico.com/guides/development/advanced-content/retrieve-content.md), centralizing its content retrieval logic behind custom `IContentItemRetrieverService`, implemented by [ContentItemRetrieverService](https://github.com/Kentico/xperience-by-kentico-training-guides/blob/finished/src/TrainingGuides.Web/Features/Shared/Services/ContentItemRetrieverService.cs). Even in projects with more complex architecture, such as a repository pattern, we recommend a similar service, since many domain models are likely to need similar content operations from Xperience.

Let's take a look at the implementations in `ContentItemRetrieverService`, diving into the functionality of each method.

## RetrieveCurrentPage

This method fetches the page that matches the current request's URL, returning it as the strongly-typed page model `T`. It wraps the `IContentRetriever` method of the same name, using optional parameters to build a `RetrieveCurrentPageParameters` object. The `depth` parameter (how many levels of linked content items to pull in) defaults to 1, `includeSecuredItems` (whether secured content should be returned) defaults to true, and `languageName` falls back to whatever the `preferredLanguageRetriever` determines from the current request. Whether the query runs in preview mode is decided automatically based on the website channel context.

### Example scenario

The [content tree-based router](https://docs.kentico.com/documentation/developers-and-admins/development/routing/content-tree-based-routing.md)  routes a request to the controller registered for a given web page content type. The controller utilizes this method to retrieve the current page's data and process it for display.

### Code

```csharp title="RetrieveCurrentPage<T>"
public async Task<T?> RetrieveCurrentPage<T>(
    int depth = 1,
    bool includeSecuredItems = true,
    string? languageName = null)
    where T : IWebPageFieldsSource, new()
{
    var parameters = new RetrieveCurrentPageParameters
    {
        LinkedItemsMaxLevel = depth,
        LanguageName = languageName ?? preferredLanguageRetriever.Get(),
        IsForPreview = webSiteChannelContext.IsPreview,
        IncludeSecuredItems = includeSecuredItems
    };

    return await contentRetriever.RetrieveCurrentPage<T>(parameters);
}
```

---

## RetrieveWebPageByContentItemGuid

Given the content item GUID of a web page content item, this method looks up that specific page and returns it as generic type. It builds a `RetrieveContentParameters` object with the usual depth, language, preview, and secured-items settings, then calls `IContentRetriever.RetrieveContentByGuids<T>` with the single GUID wrapped in an array. Since that call returns a collection (even though only one match is expected), the method takes the first result with `FirstOrDefault()`, returning `null` if nothing was found.

This method uses the content item GUID (`ContentItemGUID`) instead of web page item GUID (`WebPageItemGUID`), as the [Combined content selector](https://docs.kentico.com/documentation/developers-and-admins/customization/extend-the-administration-interface/ui-form-components/reference-admin-ui-form-components.md#combined-content-selector) (`ContentItemSelector`) form component utilizes the content item GUID for references.

### Example scenario

An editor selects a web page content item in widget properties, or in structured content. The widget or page template uses this method to retrieve selected page's data for display, assuming it is of content type `T`.

### Code

```csharp title="RetrieveWebPageByContentItemGuid<T>"
public async Task<T?> RetrieveWebPageByContentItemGuid<T>(
    Guid contentItemGuid,
    int depth = 1,
    bool includeSecuredItems = true,
    string? languageName = null)
    where T : IWebPageFieldsSource, new()
{
    var parameters = new RetrieveContentParameters
    {
        LinkedItemsMaxLevel = depth,
        LanguageName = languageName ?? preferredLanguageRetriever.Get(),
        IsForPreview = webSiteChannelContext.IsPreview,
        IncludeSecuredItems = includeSecuredItems
    };

    var pages = await contentRetriever.RetrieveContentByGuids<T>(
        [contentItemGuid],
        parameters);

    return pages.FirstOrDefault();
}
```

---

## RetrieveWebPagesByContentItemGuids

This is the plural counterpart to `RetrieveWebPageByContentItemGuid<T>`, looking up multiple web page content items by their content item GUIDs in a single call rather than one at a time. It builds the same kind of `RetrieveContentParameters` object with depth, language, preview, and secured-items settings, then calls `IContentRetriever.RetrieveContentByGuids<T>` with the full array of GUIDs, returning all matching pages instead of just the first.

### Example scenario

A widget or page template needs to display several editor-selected web page content items at once, e.g., a list of featured pages selected via a [Combined content selector](https://docs.kentico.com/documentation/developers-and-admins/customization/extend-the-administration-interface/ui-form-components/reference-admin-ui-form-components.md#combined-content-selector) (`ContentItemSelector`) form component. This method resolves all of the selected content item GUIDs to their page data in a single query.

### Code

```csharp title="RetrieveWebPagesByContentItemGuids<T>"
public async Task<IEnumerable<T?>> RetrieveWebPagesByContentItemGuids<T>(
    IEnumerable<Guid> contentItemGuids,
    int depth = 1,
    bool includeSecuredItems = true,
    string? languageName = null)
    where T : IWebPageFieldsSource, new()
{
    var parameters = new RetrieveContentParameters
    {
        LinkedItemsMaxLevel = depth,
        LanguageName = languageName ?? preferredLanguageRetriever.Get(),
        IsForPreview = webSiteChannelContext.IsPreview,
        IncludeSecuredItems = includeSecuredItems
    };

    var pages = await contentRetriever.RetrieveContentByGuids<T>(
        contentItemGuids.ToArray(),
        parameters);

    return pages;
}
```

---

## RetrieveWebPageChildrenByPath (with additionalQueryConfiguration)

This method finds all child pages beneath a given `path` and returns them as generic type `T`. It also lets you add extra filtering or sorting using the `additionalQueryConfiguration` delegate. It assembles a `RetrievePagesParameters` object configured to match children of the path, using the usual depth, language, and secured-items settings, and then passes that — along with the optional configuration action — to `IContentRetriever.RetrievePages<T>`.

> **Info:** Caching is disabled for this call to keep the training materials simpler. However, for production scenarios, we recommend configuring caching while taking into account the dependency requirements of page listings.

### Example scenario

Editors select a parent page in a widget property. This method selects the children of the selected page with the provided content type `T` and meets an additional filtering condition for display in the widget.

### Code

```csharp title="RetrieveWebPageChildrenByPath<T> (with additionalQueryConfiguration)"
public async Task<IEnumerable<T>> RetrieveWebPageChildrenByPath<T>(
    string path,
    int depth = 1,
    bool includeSecuredItems = true,
    Action<RetrievePagesQueryParameters>? additionalQueryConfiguration = null,
    string? languageName = null)
    where T : IWebPageFieldsSource, new()
{
    var parameters = new RetrievePagesParameters
    {
        LinkedItemsMaxLevel = depth,
        LanguageName = languageName ?? preferredLanguageRetriever.Get(),
        IsForPreview = webSiteChannelContext.IsPreview,
        PathMatch = PathMatch.Children(path),
        IncludeSecuredItems = includeSecuredItems
    };

    return await contentRetriever.RetrievePages<T>(
        parameters,
        additionalQueryConfiguration: additionalQueryConfiguration,
        cacheSettings: RetrievalCacheSettings.CacheDisabled);
}
```

---

## RetrieveWebPageChildrenByPath (without additionalQueryConfiguration)

This convenience overload simplifies the common scenario where no custom query configuration is required. Instead of duplicating logic, it delegates to the fuller overload above and passes `null` for the `additionalQueryConfiguration` parameter.

### Example scenario

Editors select a parent page in a widget property. This method selects the children of the selected page with the provided content type `T` for display in the widget.

### Code

```csharp title="RetrieveWebPageChildrenByPath<T>"
public async Task<IEnumerable<T>> RetrieveWebPageChildrenByPath<T>(
    string path,
    int depth = 1,
    bool includeSecuredItems = true,
    string? languageName = null)
    where T : IWebPageFieldsSource, new()
    => await RetrieveWebPageChildrenByPath<T>(
        path,
        depth,
        includeSecuredItems,
        null,
        languageName);
```

---

## RetrieveWebPageChildrenByPathAndReference

This method narrows down the children of a page to only those that reference a specific set of content items. Rather than reimplementing the query logic, it delegates to `RetrieveWebPageChildrenByPath<T>` and supplies an `additionalQueryConfiguration` delegate that calls `.Linking(referenceFieldName, referenceIds)`, filtering results down to pages whose specified reference field points at one of the given IDs.

### Example scenario

In a content model that keeps structured content in the _Content hub_ and uses page wrappers for web-specific metadata, one method retrieves the IDs of reusable content items that meet a certain criteria, such as a specific taxonomy tag. This method retrieves pages with the provided content type `T` from a given section of the content tree which reference those reusable items.

### Code

```csharp title="RetrieveWebPageChildrenByPathAndReference<T>"
public async Task<IEnumerable<T>> RetrieveWebPageChildrenByPathAndReference<T>(
    string parentPagePath,
    string referenceFieldName,
    IEnumerable<int> referenceIds,
    bool includeSecuredItems,
    int depth = 1,
    string? languageName = null)
    where T : IWebPageFieldsSource, new()
 => await RetrieveWebPageChildrenByPath<T>(
        path: parentPagePath,
        includeSecuredItems: includeSecuredItems,
        depth: depth,
        additionalQueryConfiguration: config => config.Linking(referenceFieldName, referenceIds),
        languageName: languageName);
```

---

## RetrieveWebPageSectionByPath

This method retrieves an entire section of the content tree — the page at a given path plus all of its children — using `PathMatch.Section` instead of `PathMatch.Children`, which excludes the root page. An optional `nestingLevel` can limit how many levels deep the section extends; if omitted, all descendants are included regardless of depth. Like `RetrieveWebPageChildrenByPath<T>`, it accepts an `additionalQueryConfiguration` delegate for further filtering or sorting, and disables caching for the same reasons.

### Example scenario

A sitemap or "section overview" feature needs to list a landing page together with everything nested beneath it (e.g., a Store landing page and all of its category and product pages) in a single query, rather than querying the parent and its children separately.

### Code

```csharp title="RetrieveWebPageSectionByPath<T>"
public async Task<IEnumerable<T>> RetrieveWebPageSectionByPath<T>(
    string path,
    int? nestingLevel = null,
    int depth = 1,
    bool includeSecuredItems = true,
    Action<RetrievePagesQueryParameters>? additionalQueryConfiguration = null,
    string? languageName = null)
    where T : IWebPageFieldsSource, new()
{
    var parameters = new RetrievePagesParameters
    {
        LinkedItemsMaxLevel = depth,
        LanguageName = languageName ?? preferredLanguageRetriever.Get(),
        IsForPreview = webSiteChannelContext.IsPreview,
        PathMatch = nestingLevel.HasValue
            ? PathMatch.Section(path, nestingLevel.Value)
            : PathMatch.Section(path),
        IncludeSecuredItems = includeSecuredItems
    };

    return await contentRetriever.RetrievePages<T>(
        parameters,
        additionalQueryConfiguration: additionalQueryConfiguration,
        cacheSettings: RetrievalCacheSettings.CacheDisabled);
}
```

---

## RetrieveWebPageByPathWithoutContext

Unlike most of the other retrieval methods, this one doesn't rely on the ambient website channel context to know which channel or language to query — instead, the caller explicitly provides `channelName`, `languageName`, and `forPreview`. This makes it useful in scenarios where you need to look up a page outside the current request's channel, such as cross-channel lookups. It builds a `ContentItemQueryBuilder` directly, scoping the query to the given website channel and matching a single exact path, then executes the query through `IContentQueryExecutor.GetMappedResult<T>` and returns the first matching page (or `null` if none exists).

### Example scenario

In a content item event handler that creates pages corresponding to reusable content items, this method retrieves the parent page under which you want to create an item's corresponding page.

### Code

```csharp title="RetrieveWebPageByPathWithoutContext<T>"
public async Task<T?> RetrieveWebPageByPathWithoutContext<T>(
    string pathToMatch,
    string languageName,
    string channelName,
    bool forPreview,
    bool includeSecuredItems)
    where T : IWebPageFieldsSource, new()
{
    var builder = new ContentItemQueryBuilder();

    builder.ForContentTypes(query =>
        {
            query.ForWebsite(channelName, PathMatch.Single(pathToMatch));
        })
        .InLanguage(languageName);

    var queryExecutorOptions = new ContentQueryExecutionOptions
    {
        ForPreview = forPreview,
        IncludeSecuredItems = includeSecuredItems
    };

    var pages = await contentQueryExecutor.GetMappedResult<T>(builder, queryExecutorOptions);

    return pages.FirstOrDefault();
}
```

---

## RetrieveWebPageChildrenByPathWithoutContext

This is the "without context" counterpart to the children-by-path methods below, and it's the most flexible of the bunch. Rather than being locked into a single content type or the ambient channel, it accepts an explicit `channelName`, a list of `contentTypeNames` to search across, and two configuration delegates — `customContentTypesQueryParameters` and `customContentQueryParameters` — that let the caller layer on additional type-level and query-level filtering. Internally, it builds a `ContentItemQueryBuilder` scoped to the children of `parentPagePath` within the given channel, applies the requested content types and linked-item depth, optionally restricts the query to a specific language, and then executes it with `IContentQueryExecutor.GetMappedWebPageResult<IWebPageFieldsSource>`, returning whatever pages match.

### Example scenario

In a content item event handler that creates pages corresponding to reusable content items, this method checks if a corresponding page for the reusable item already exists in a given content tree section.

### Code

```csharp title="RetrieveWebPageChildrenByPathWithoutContext"
public async Task<IEnumerable<IWebPageFieldsSource>> RetrieveWebPageChildrenByPathWithoutContext(
    IEnumerable<string> contentTypeNames,
    string parentPagePath,
    Func<ContentTypesQueryParameters, ContentTypesQueryParameters> customContentTypesQueryParameters,
    Func<ContentQueryParameters, ContentQueryParameters> customContentQueryParameters,
    bool forPreview,
    bool includeSecuredItems,
    string channelName,
    string? languageName = null,
    int depth = 1)
{
    Action<ContentTypesQueryParameters> contentTypesQueryParameters =
        config => customContentTypesQueryParameters(config
            .ForWebsite(channelName, PathMatch.Children(parentPagePath))
            .OfContentType(contentTypeNames.ToArray())
            .WithLinkedItems(depth)
            .WithContentTypeFields());

    var builder = new ContentItemQueryBuilder()
                        .ForContentTypes(contentTypesQueryParameters)
                        .Parameters(param => customContentQueryParameters(param));

    if (!string.IsNullOrEmpty(languageName))
    {
        builder.InLanguage(languageName);
    }

    var queryExecutorOptions = new ContentQueryExecutionOptions
    {
        ForPreview = forPreview,
        IncludeSecuredItems = includeSecuredItems
    };

    var pages = await contentQueryExecutor.GetMappedWebPageResult<IWebPageFieldsSource>(builder, queryExecutorOptions);

    return pages;
}
```

> **Note:** Since `contentTypeNames` is already known ahead of time here, [`IContentRetriever.RetrievePagesOfContentTypes`](https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/content-retriever-api.md) would be a more direct ContentRetriever-based alternative to building this query manually.

---

## RetrieveContentItemByGuid

This method is the reusable-content-item equivalent of `RetrieveWebPageByContentItemGuid<T>` — instead of a web page, it looks up a reusable content item (which lives in the _Content hub_ rather than a specific web channel) by its GUID. It builds a `RetrieveContentParameters` object with the standard depth, language, preview, and secured-items settings, calls `IContentRetriever.RetrieveContentByGuids<T>` with the single GUID, and returns the first match or `null` if the item wasn't found.

### Example scenario

Editors select a reusable content item in a widget's properties. The widget uses this method to query the reusable item's data and display it.

### Code

```csharp title="RetrieveContentItemByGuid<T>"
public async Task<T?> RetrieveContentItemByGuid<T>(
    Guid contentItemGuid,
    int depth = 1,
    bool includeSecuredItems = true,
    string? languageName = null)
    where T : IContentItemFieldsSource, new()
{
    var parameters = new RetrieveContentParameters
    {
        LinkedItemsMaxLevel = depth,
        LanguageName = languageName ?? preferredLanguageRetriever.Get(),
        IsForPreview = webSiteChannelContext.IsPreview,
        IncludeSecuredItems = includeSecuredItems
    };

    var items = await contentRetriever.RetrieveContentByGuids<T>(
        [contentItemGuid],
        parameters);

    return items.FirstOrDefault();
}
```

---

## RetrieveReusableContentItemsFromSmartFolder

This method pulls a page of reusable content items out of a specific smart folder, sorted by their last-published date and capped at a maximum count. After building the standard `RetrieveContentParameters`, it calls `IContentRetriever.RetrieveContent<T>` with a query that scopes results `InSmartFolder(smartFolderGuid)`, orders them by the `ContentItemCommonDataLastPublishedWhen` column — descending for `OrderByOption.NewestFirst` or ascending otherwise — and limits the result set with `TopN(topN)` (20 items by default). Caching is disabled so that newly published or reordered items show up immediately.

### Example scenario

Administrators configure a smart folder that dynamically collects gallery image content items meeting certain criteria. Editors select the folder in the properties of a widget, which uses this method to retrieve the contents of the smart folder.

### Code

```csharp title="RetrieveReusableContentItemsFromSmartFolder<T>"
public async Task<IEnumerable<T>> RetrieveReusableContentItemsFromSmartFolder<T>(
    Guid smartFolderGuid,
    OrderByOption orderBy,
    int topN = 20,
    int depth = 1,
    bool includeSecuredItems = true,
    string? languageName = null)
    where T : IContentItemFieldsSource, new()
{
    const string LAST_PUBLISHED_COLUMN_NAME = "ContentItemCommonDataLastPublishedWhen";

    var parameters = new RetrieveContentParameters
    {
        LinkedItemsMaxLevel = depth,
        LanguageName = languageName ?? preferredLanguageRetriever.Get(),
        IsForPreview = webSiteChannelContext.IsPreview,
        IncludeSecuredItems = includeSecuredItems
    };

    return await contentRetriever.RetrieveContent<T>(
        parameters,
        query => query
            .InSmartFolder(smartFolderGuid)
            .OrderBy(new OrderByColumn(
                LAST_PUBLISHED_COLUMN_NAME,
                orderBy.Equals(OrderByOption.NewestFirst) ? OrderDirection.Descending : OrderDirection.Ascending))
            .TopN(topN),
        RetrievalCacheSettings.CacheDisabled);
}
```

---

## RetrieveContentItemsBySchemaAndTags

This method finds reusable content items belonging to a given schema that are tagged with any of a specified set of taxonomy tags — handy for building tag-filtered listings such as "all articles tagged with these topics." It configures a `RetrieveContentOfReusableSchemasParameters` object with language, preview, secured-items, and content-type-field-inclusion settings, then calls `IContentRetriever.RetrieveContentOfReusableSchemas<IContentItemFieldsSource>` for the single schema, adding a `WhereContainsTags(taxonomyColumnName, tagGuids)` filter to the query. Since the return type is the generic `IContentItemFieldsSource` interface rather than a specific model, this method doesn't require a type parameter.

### Example scenario

Using a widget property in an article list widget, editors select taxonomy tags whose articles they want to display in the listing. This method finds reusable items with those tags, which a subsequent query can use to locate pages that reference those items.

### Code

```csharp title="RetrieveContentItemsBySchemaAndTags"
public async Task<IEnumerable<IContentItemFieldsSource>> RetrieveContentItemsBySchemaAndTags(
    string schemaName,
    string taxonomyColumnName,
    IEnumerable<Guid> tagGuids,
    bool includeSecuredItems = true,
    bool includeContentTypeFields = true,
    string? languageName = null)
{
    var parameters = new RetrieveContentOfReusableSchemasParameters
    {
        LanguageName = languageName ?? preferredLanguageRetriever.Get(),
        IsForPreview = webSiteChannelContext.IsPreview,
        IncludeSecuredItems = includeSecuredItems,
        IncludeContentTypeFields = includeContentTypeFields
    };

    return await contentRetriever.RetrieveContentOfReusableSchemas<IContentItemFieldsSource>(
        [schemaName],
        parameters,
        query => query.Where(where => where.WhereContainsTags(taxonomyColumnName, tagGuids)),
        RetrievalCacheSettings.CacheDisabled,
        configureModel: null);
}
```

---

## RetrieveContentItemsByTags

This method filters content items of a single, specific content type `T` by taxonomy tags, without requiring the taxonomy field to belong to a shared reusable field schema, unlike `RetrieveContentItemsBySchemaAndTags`, which requires a `schemaName`. It builds the standard `RetrieveContentParameters` and calls `IContentRetriever.RetrieveContent<T>`, adding a `WhereContainsTags` filter.

### Example scenario

A content type has its own dedicated taxonomy field that isn't shared through a reusable field schema (e.g., a `BlogPost` type with a `BlogPostTags` field). Editors select tags through a widget, and this method retrieves matching items of the specified type directly. There is no need to know or reference the schema name.

### Code

```csharp title="RetrieveContentItemsByTags<T>"
public async Task<IEnumerable<T>> RetrieveContentItemsByTags<T>(
    string taxonomyColumnName,
    IEnumerable<Guid> tagGuids,
    int depth = 1,
    bool includeSecuredItems = true,
    string? languageName = null)
    where T : IContentItemFieldsSource, new()
{
    var parameters = new RetrieveContentParameters
    {
        LinkedItemsMaxLevel = depth,
        LanguageName = languageName ?? preferredLanguageRetriever.Get(),
        IsForPreview = webSiteChannelContext.IsPreview,
        IncludeSecuredItems = includeSecuredItems
    };

    return await contentRetriever.RetrieveContent<T>(
        parameters,
        query => query.Where(where => where.WhereContainsTags(taxonomyColumnName, tagGuids)),
        RetrievalCacheSettings.CacheDisabled);
}
```

---

## RetrieveContentItemsBySchemas

This is a more general-purpose version of the schema-based retrieval methods: it can search across multiple reusable field schemas at once (rather than just one) and gives the caller full control over the query through the `additionalQueryConfiguration` delegate. After setting up the usual `RetrieveContentOfReusableSchemasParameters` — including `LinkedItemsMaxLevel` for controlling how deep linked items are resolved — it calls `IContentRetriever.RetrieveContentOfReusableSchemas<T>` with the list of schema names and the caller-supplied query configuration, again with caching disabled. An `includeContentTypeFields` parameter (default `true`) controls whether per-content-type fields are mapped; set it to `false` when the caller only reads content item metadata or reusable field schema fields, to skip mapping data that would otherwise be discarded.

### Example scenario

A visitor selects product attributes that correspond to taxonomy tags, which are assigned to products via multiple reusable field schemas. The back-end logic uses this method to find products which have one or more of the selected tags, which display logic can further refine with post-filtering.

### Code

```csharp title="RetrieveContentItemsBySchemas<T>"
public async Task<IEnumerable<T>> RetrieveContentItemsBySchemas<T>(
    IEnumerable<string> schemaNames,
    Action<RetrieveContentOfReusableSchemasQueryParameters> additionalQueryConfiguration,
    int depth = 1,
    bool includeSecuredItems = true,
    bool includeContentTypeFields = true,
    string? languageName = null)
{
    var parameters = new RetrieveContentOfReusableSchemasParameters
    {
        LanguageName = languageName ?? preferredLanguageRetriever.Get(),
        IsForPreview = webSiteChannelContext.IsPreview,
        IncludeSecuredItems = includeSecuredItems,
        IncludeContentTypeFields = includeContentTypeFields,
        LinkedItemsMaxLevel = depth
    };

    return await contentRetriever.RetrieveContentOfReusableSchemas<T>(
        schemaNames,
        parameters,
        additionalQueryConfiguration,
        RetrievalCacheSettings.CacheDisabled,
        configureModel: null);
}
```

---

## RetrieveParentItemsOfSchema

This method works in the opposite direction from the reference-based children lookup above: instead of finding pages that reference certain items, it finds reusable content items (filtered to a given schema) that reference a set of child item IDs through a specified field — effectively locating the "parents" of those children. It builds the standard `RetrieveContentOfReusableSchemasParameters` and calls `IContentRetriever.RetrieveContentOfReusableSchemas<T>` for the single schema, adding a `.LinkingSchemaField(referenceFieldName, referenceIds)` filter to match items whose reference field points at any of the supplied IDs.

### Example scenario

A product pricing service must find a price for any product passed to it, regardless of whether the product is a parent product or a product variant, regardless of where pricing information is stored. If a variant does not have pricing information, the service uses this method to look up its parent product.

### Code

```csharp title="RetrieveParentItemsOfSchema<T>"
public async Task<IEnumerable<T>> RetrieveParentItemsOfSchema<T>(
    string schemaName,
    string referenceFieldName,
    IEnumerable<int> referenceIds,
    bool includeSecuredItems,
    int depth = 1,
    bool includeContentTypeFields = true,
    string? languageName = null)
{
    var parameters = new RetrieveContentOfReusableSchemasParameters
    {
        LinkedItemsMaxLevel = depth,
        LanguageName = languageName ?? preferredLanguageRetriever.Get(),
        IsForPreview = webSiteChannelContext.IsPreview,
        IncludeSecuredItems = includeSecuredItems,
        IncludeContentTypeFields = includeContentTypeFields
    };

    return await contentRetriever.RetrieveContentOfReusableSchemas<T>(
        [schemaName],
        parameters,
        query => query.LinkingSchemaField(referenceFieldName, referenceIds),
        RetrievalCacheSettings.CacheDisabled);
}
```

---

## RetrieveWebPageByPath

This method retrieves a single web page by matching its exact tree path — the kind of path visible in the administration interface's Properties tab. It builds a `RetrievePagesParameters` object with `PathMatch.Single(pathToMatch)`, along with the usual language, preview, and secured-items settings, then calls `IContentRetriever.RetrievePages<T>` with caching disabled and no additional query configuration. Since the underlying call can technically return more than one result, it takes the first match with `FirstOrDefault()`.

### Example scenario

A C# component like a layout or view component expects a specific page to exist in the database, and uses this method to retrieve the data of a page with the given path, stored in a constant. (This is safer than using something like a GUID because if an editor accidentally deletes the expected page and clears the recycle bin, they can create a new page at the path, and it will work despite having a different GUID.)

### Code

```csharp title="RetrieveWebPageByPath<T>"
public async Task<T?> RetrieveWebPageByPath<T>(
    string pathToMatch,
    bool includeSecuredItems = true,
    string? languageName = null)
    where T : IWebPageFieldsSource, new()
{
    var parameters = new RetrievePagesParameters
    {
        LanguageName = languageName ?? preferredLanguageRetriever.Get(),
        IsForPreview = webSiteChannelContext.IsPreview,
        PathMatch = PathMatch.Single(pathToMatch),
        IncludeSecuredItems = includeSecuredItems
    };

    var pages = await contentRetriever.RetrievePages<T>(
        parameters,
        additionalQueryConfiguration: null,
        cacheSettings: RetrievalCacheSettings.CacheDisabled);

    return pages.FirstOrDefault();
}
```

---

## RetrieveWebPageByContentItemGuid

This non-generic overload looks up a web page by content item GUID when the exact web page content type isn't known ahead of time. Since most `IContentRetriever` methods require a concrete type and won't accept the `IWebPageFieldsSource` interface directly, this method falls back to the older, lower-level `ContentItemQueryBuilder` approach via the private [`RetrieveWebPages` helper](#retrievewebpages-helper), filtering with `WhereEquals(nameof(ContentItemFields.ContentItemGUID), pageContentItemGuid)`. It returns the first matching page, mapped generically to `IWebPageFieldsSource`, or `null` if nothing matches.

### Example scenario

An editor selects a web page content item in widget properties, or in structured content, using a [Combined content selector](https://docs.kentico.com/documentation/developers-and-admins/customization/extend-the-administration-interface/ui-form-components/reference-admin-ui-form-components.md#combined-content-selector) (`ContentItemSelector`) that allows selection from at least two types. The widget or template uses this method to retrieve selected page's data for display, regardless of the web page content type.

### Code

```csharp title="RetrieveWebPageByContentItemGuid"
public async Task<IWebPageFieldsSource?> RetrieveWebPageByContentItemGuid(
    Guid pageContentItemGuid,
    int depth = 2,
    bool includeSecuredItems = true,
    string? languageName = null)
{
    var pages = await RetrieveWebPages(parameters =>
        {
            parameters.Where(where => where.WhereEquals(nameof(ContentItemFields.ContentItemGUID), pageContentItemGuid));
        },
        depth,
        includeSecuredItems,
        languageName ?? preferredLanguageRetriever.Get());

    return pages.FirstOrDefault();
}
```

---

## RetrieveWebPagesByContentItemGuids

This is the non-generic, plural counterpart to `RetrieveWebPageByContentItemGuid`, used when the specific web page content type isn't known ahead of time and multiple pages need to be resolved by their content item GUIDs at once. Like the singular version, it falls back to the private `RetrieveWebPages` helper, filtering with `WhereIn` instead of `WhereEquals`, and returns all matching pages mapped generically to `IWebPageFieldsSource`.

### Example scenario

An editor selects multiple web page content items in widget properties, or in structured content, using a [Combined content selector](https://docs.kentico.com/documentation/developers-and-admins/customization/extend-the-administration-interface/ui-form-components/reference-admin-ui-form-components.md#combined-content-selector) (`ContentItemSelector`) that allows selection from at least two types. The widget or template uses this method to retrieve all of the selected pages' data for display, regardless of their web page content type.

### Code

```csharp title="RetrieveWebPagesByContentItemGuids"
public async Task<IEnumerable<IWebPageFieldsSource?>> RetrieveWebPagesByContentItemGuids(
    IEnumerable<Guid> pageContentItemGuids,
    int depth = 2,
    bool includeSecuredItems = true,
    string? languageName = null)
{
    var pages = await RetrieveWebPages(parameters =>
        {
            parameters.Where(where => where.WhereIn(nameof(ContentItemFields.ContentItemGUID), pageContentItemGuids));
        },
        depth,
        includeSecuredItems,
        languageName ?? preferredLanguageRetriever.Get());

    return pages;
}
```

---

## RetrieveWebPageById

This method mirrors `RetrieveWebPageByContentItemGuid` above, but looks a page up by its numeric `WebPageItemID` instead of its GUID — again useful when the specific page type isn't known in advance and the type-safe `ContentRetriever` API isn't an option. It delegates to the same private `RetrieveWebPages` helper, this time filtering with `WhereEquals(nameof(WebPageFields.WebPageItemID), webPageItemId)`, and returns the first matching page or `null`.

### Example scenario

A custom module includes binding data between pages and a custom class, which it sends to a controller in a POST request. The controller uses this method to look up the page's data.

### Code

```csharp title="RetrieveWebPageById"
public async Task<IWebPageFieldsSource?> RetrieveWebPageById(
    int webPageItemId,
    int depth = 2,
    bool includeSecuredItems = true,
    string? languageName = null)
{
    var pages = await RetrieveWebPages(parameters =>
        {
            parameters.Where(where => where.WhereEquals(nameof(WebPageFields.WebPageItemID), webPageItemId));
        },
        depth,
        includeSecuredItems,
        languageName ?? preferredLanguageRetriever.Get());

    return pages.FirstOrDefault();
}
```

---

## RetrieveWebPages (Private Helper)&#x20;

This private helper centralizes the shared query logic used by both `RetrieveWebPageByContentItemGuid` and `RetrieveWebPageById`, so neither has to duplicate it. It builds a `ContentItemQueryBuilder` scoped to the current website channel, includes linked items up to the given `depth` (with web page data included), applies whatever `Where` filter the caller passes in through the `parameters` action, and restricts the query to the given (or preferred) language. It then executes the query via `IContentQueryExecutor.GetMappedResult<IWebPageFieldsSource>` and returns the matching pages, respecting the preview and secured-items settings along the way.

### Example scenario

A component in your project needs to retrieve pages based on some kind of filtering data, but there is no way to know which content types are required. The `ContentItemRetrieverService` method that it utilizes calls this private method to retrieve the necessary pages.

### Code

```csharp title="RetrieveWebPages"
private async Task<IEnumerable<IWebPageFieldsSource>> RetrieveWebPages(
    Action<ContentQueryParameters> parameters,
    int depth,
    bool includeSecuredItems = true,
    string? languageName = null)
{
    var builder = new ContentItemQueryBuilder()
        .ForContentTypes(query => query
        .WithLinkedItems(depth, options => options.IncludeWebPageData(true))
        .ForWebsite(webSiteChannelContext.WebsiteChannelName))
    .Parameters(parameters)
    .InLanguage(languageName ?? preferredLanguageRetriever.Get());

    var queryExecutorOptions = new ContentQueryExecutionOptions
    {
        ForPreview = webSiteChannelContext.IsPreview,
        IncludeSecuredItems = includeSecuredItems
    };

    return await contentQueryExecutor.GetMappedResult<IWebPageFieldsSource>(builder, queryExecutorOptions);
}
```

---

## RetrieveWebPageAncestorsByTreePath

This method retrieves the ancestor chain of a page for use in breadcrumb navigation, given the page's tree path (e.g., `/Store/Cat_food/Purremo_Essentials_dry_cat_food`). It first uses the private `GetAncestorTreePaths` helper to split the tree path into a list of ancestor paths — one per level, from the root down to the immediate parent (or including the page itself if `includeCurrentPage` is `true`) — then passes that list to the private `RetrieveWebPages` helper, filtering with `WhereIn`. Since ancestors can be of different content types, results are mapped generically to `IWebPageFieldsSource` and ordered from the root down by tree path length, ready for direct rendering as a breadcrumb trail.

### Example scenario

A shared layout or view component needs to render breadcrumb navigation for the current page (e.g., Home > Store > Cat food > Purremo Essentials dry cat food), regardless of the content types of the pages along the way.

### Code

```csharp title="RetrieveWebPageAncestorsByTreePath"
public async Task<IEnumerable<IWebPageFieldsSource>> RetrieveWebPageAncestorsByTreePath(
        string treePath,
        bool includeCurrentPage = false,
        int depth = 1,
        bool includeSecuredItems = true,
        string? languageName = null)
    {
        var ancestorTreePaths = GetAncestorTreePaths(treePath, includeCurrentPage);

        if (ancestorTreePaths.Count == 0)
        {
            return [];
        }

        var pages = await RetrieveWebPages(parameters =>
            {
                parameters.Where(where => where.WhereIn(nameof(WebPageFields.WebPageItemTreePath), ancestorTreePaths));
            },
            depth,
            includeSecuredItems,
            languageName ?? preferredLanguageRetriever.Get());

        return pages.OrderBy(page => page.SystemFields.WebPageItemTreePath.Length);
    }

    /// <summary>
    /// Builds the tree paths of all ancestors of the given tree path, ordered from the root down to the immediate parent (or the page itself, if <paramref name="includeCurrentPage"/> is true).
    /// </summary>
    private static List<string> GetAncestorTreePaths(string treePath, bool includeCurrentPage)
    {
        string[] segments = treePath.Split('/', StringSplitOptions.RemoveEmptyEntries);
        int segmentsToInclude = includeCurrentPage ? segments.Length : segments.Length - 1;

        var ancestorTreePaths = new List<string>();
        string currentPath = string.Empty;

        for (int i = 0; i < segmentsToInclude; i++)
        {
            currentPath += $"/{segments[i]}";
            ancestorTreePaths.Add(currentPath);
        }

        return ancestorTreePaths;
    }
```

---

## What's next

Building on top of these content retrieval techniques, explore advanced, use-case-driven ways of working with content in Xperience by Kentico. Discover how to work with [reusable field schemas](https://docs.kentico.com/guides/development/advanced-content/work-with-reusable-field-schemas.md), filter content by [taxonomies](https://docs.kentico.com/guides/development/advanced-content/filter-content-based-on-taxonomies.md), and deliver content dynamically to editors with [smart folders](https://docs.kentico.com/guides/development/advanced-content/deliver-content-dynamically-with-smart-folders.md).
