---
title: Retrieve content items
related:
  - https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/content-item-query-api.md
  - https://docs.kentico.com/documentation/business-users/content-hub.md
  - https://docs.kentico.com/documentation/developers-and-admins/development/content-types.md
  - https://docs.kentico.com/documentation/developers-and-admins/development/content-retrieval/retrieve-page-content.md
---

> 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).

Xperience by Kentico provides the [ContentRetriever API](https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/content-retriever-api.md) as the primary and recommended approach for retrieving reusable content.

The ContentRetriever API works with:

- [Generated content type classes](https://docs.kentico.com/documentation/developers-and-admins/api/generate-code-files-for-system-objects.md) – classes generated by the system that allow you to work with [content type](https://docs.kentico.com/documentation/developers-and-admins/development/content-types.md) fields using strongly-typed objects. These classes also allow access to all general data (title, ID, GUID, creation date, publish date, etc.) as well.
- Custom data transfer objects (advanced use case) – using custom DTOs grants you control over the mapping logic. See [Custom model mapping](https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/content-retriever-api.md#custom-model-mapping). Note that some Xperience APIs that work with content items expect certain system fields to be present in the model and will not work as expected otherwise.

For more information about content querying and available parametrization, see [ContentRetriever API](https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/content-retriever-api.md) and [Reference - ContentRetriever API](https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/reference-content-retriever-api.md).

## Retrieve content items

To retrieve content items, use the `IContentRetriever` service from the `Kentico.Content.Web.Mvc` namespace. This service provides built-in caching, optimized performance, and simplified content retrieval with [generated classes](https://docs.kentico.com/documentation/developers-and-admins/api/generate-code-files-for-system-objects.md) for individual content types. The generated content type classes allow you to work with strongly typed objects and easily access their [fields](https://docs.kentico.com/documentation/developers-and-admins/customization/field-editor.md).

The ContentRetriever API provides several methods for different content retrieval scenarios:

- `RetrieveContent` – for retrieving items of a single content type
- `RetrieveContentOfContentTypes` – for retrieving items of multiple content types
- `RetrieveContentOfReusableSchemas` – for retrieving items using reusable field schemas
- `RetrieveContentByGuids` – for retrieving specific items by their GUIDs

Each method uses its corresponding parameter class (`RetrieveContentParameters`, `RetrieveContentOfContentTypesParameters`, etc.) to configure retrieval behavior.

For a detailed overview of the available methods and their parameters, see [Reference - ContentRetriever API](https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/reference-content-retriever-api.md).

```csharp title="Retrieve content items"
using System.Threading.Tasks;

using CMS.ContentEngine;
using Kentico.Content.Web.Mvc;

// IContentRetriever service obtained via constructor dependency injection
public class CustomComponent(IContentRetriever contentRetriever)
{
    private async Task SampleRetrieval()
    {
        // Retrieves 3 banners with linked items
        var banners = await contentRetriever.RetrieveContent<Banner>(
            new RetrieveContentParameters
            { 
                LinkedItemsMaxLevel = 1
            },
            query => query.TopN(3),
            new RetrievalCacheSettings(cacheItemNameSuffix:
                                        $"{nameof(RetrieveContentQueryParameters.TopN)}|3"));

        // Accesses the content item data
        foreach (Banner item in banners)
        {
            // Accesses content type fields
            string header = item.BannerHeaderText;

            // Accesses system fields
            VersionStatus status = item.SystemFields.ContentItemCommonDataVersionStatus;
        }
    }
}
```

For scenarios requiring advanced query customization, you can use the [content item query API](https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/content-item-query-api.md) with `ContentItemQueryBuilder` and `IContentQueryExecutor`.

### Filter content items based on tags

You can limit the retrieval to only content items with [specified tags](https://docs.kentico.com/documentation/developers-and-admins/configuration/taxonomies.md) tags using the `additionalQueryConfiguration` parameter with the `Where` method and its `WhereContainsTags` condition:

```csharp title="Filter by tags"
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

using CMS.ContentEngine;

using Kentico.Content.Web.Mvc;

// ...

// A collection of tags, e.g., obtained from a Tag selector
IEnumerable<Guid> tagIdentifiers;

var banners = await contentRetriever.RetrieveContent<Banner>(
    RetrieveContentParameters.Default,
    query => query.Where(where => where.WhereContainsTags("SomeTaxonomy", tagIdentifiers)),
    new RetrievalCacheSettings(cacheItemNameSuffix:
        $"{nameof(WhereParameters.Where)}|{nameof(WhereParameters.WhereContainsTags)}|SomeTaxonomy|tagIdentifiers"));
```

You can also create a `TagCollection` object and pass it as an argument of the `WhereContainsTags` method. The `TagCollection` object then represents a collection of all tags specified as the input and any tags that are children of the specified tags. This is useful when you need to retrieve all items that belong in a subtree of a taxonomy.

```csharp title="Filter by tag collection"
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

using CMS.ContentEngine;

using Kentico.Content.Web.Mvc;

// ...

// A collection of tags, e.g., obtained from a Tag selector
IEnumerable<Guid> tagIdentifiers;
var tagCollection = await TagCollection.Create(tagIdentifiers);

var articles = await contentRetriever.RetrieveContent<ArticlePage>(
    RetrieveContentParameters.Default,
    query => query.Where(where => where.WhereContainsTags("SomeTaxonomy", tagCollection)),
    new RetrievalCacheSettings(cacheItemNameSuffix:
        $"{nameof(WhereParameters.Where)}|{nameof(WhereParameters.WhereContainsTags)}|SomeTaxonomy|Collection"));
```

The retrieval API is designed to work with data from the [Tag selector](https://docs.kentico.com/documentation/developers-and-admins/customization/extend-the-administration-interface/ui-form-components/reference-admin-ui-form-components.md#tag-selector) editing component, which is a collection of identifiers (`IEnumerable<Guid>`).

- To convert a collection of identifiers to a collection of tags, you can use the `RetrieveTags` method of the `ITaxonomyRetriever` interface.

  ```csharp title="RetrieveTags"
  using System;
  using System.Collections.Generic;
  using System.Threading.Tasks;

  using CMS.ContentEngine;

  public class CustomComponent(ITaxonomyRetriever taxonomyRetriever)
  {
      // Accepts a collection of tag GUIDs, e.g., obtained from a Tag selector
      private async Task RetrieveTags(IEnumerable<Guid> tagIdentifiers)
      {
          // Retrieves a collection of Tag objects
          IEnumerable<Tag> tags = await taxonomyRetriever.RetrieveTags(tagIdentifiers, "en");

          // ...
      }
  }
  ```

- To convert a collection of `Tag` objects to a collection of identifiers, you can use the `Select` [LINQ](https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.select?view=net-8.0) method.

  ```csharp title="Select LINQ method"
  using System;
  using System.Collections.Generic;
  using System.Linq;

  using CMS.ContentEngine;

  // ...

  // A collection of Tag objects
  IEnumerable<Tag> tags;

  // Retrieves a collection of tag identifiers
  IEnumerable<Guid> tagIdentifiers = tags.Select(tag => tag.Identifier);
  ```

> **Tip:** **Using logical operators with tags**
>
> You can use the `And()` and `Or()` [logical operators](https://docs.kentico.com/documentation/developers-and-admins/api/objectquery-api.md#logical-operators) to combine multiple conditions. For example, the following code snippet shows how to retrieve items that contain both the first and the second tag from the provided list of tags at the same time:
>
> ```csharp title="Combine tag conditions"
> using System;
> using System.Collections.Generic;
> using System.Linq;
> using System.Threading.Tasks;
>
> using CMS.ContentEngine;
> using Kentico.Content.Web.Mvc;
>
> // ...
>
> // Accepts a collection of tag GUIDs, e.g., obtained from a Tag selector
> private async Task RetrieveTaggedContent(IEnumerable<Guid> tagIdentifiers)
> {
>     var banners = await contentRetriever.RetrieveContent<Banner>(
>         RetrieveContentParameters.Default,
>         query => query.Where(where =>
>             where.WhereContainsTags("SomeTaxonomy",
>                     new List<Guid> { tagIdentifiers.ElementAt(0) })
>                 .And()
>                 .WhereContainsTags("SomeTaxonomy",
>                     new List<Guid> { tagIdentifiers.ElementAt(1) })),
>         new RetrievalCacheSettings(cacheItemNameSuffix:
>             $"{nameof(WhereParameters.Where)}|MultipleTags|tagIdentifiers"));
> }
> ```

### Retrieve content items from smart folders

[Smart folders](https://docs.kentico.com/documentation/business-users/content-hub/content-hub-folders.md#smart-folders) give content editors the power to select a specific set of content items. This is achieved by configuring filter conditions, such as “items published in the last 7 days”, “items with the Acme tag”, etc.

For smart folders with [dynamic content delivery](https://docs.kentico.com/documentation/business-users/content-hub/content-hub-folders.md#enable-content-delivery-for-smart-folders) enabled, you can use `IContentRetriever` with the `additionalQueryConfiguration` parameter and the `InSmartFolder` parametrization method to retrieve the content items that match a folder's filter conditions. You can then display or otherwise use the retrieved items in your application. This allows content editors to control which items are delivered directly in the _Content hub_ UI, without needing to adjust the code.

The `InSmartFolder` method requires you to specify the smart folder by its ID, GUID or code name identifier. To get the identifier, we recommend using fields with the [Smart folder selector](https://docs.kentico.com/documentation/developers-and-admins/customization/extend-the-administration-interface/ui-form-components/reference-admin-ui-form-components.md#smart-folder-selector) UI form component. The smart folder selector is supported in the following scenarios:

- [Fields](https://docs.kentico.com/documentation/developers-and-admins/customization/field-editor.md) with the _Smart folder_ data type, added to the [content types](https://docs.kentico.com/documentation/developers-and-admins/development/content-types.md) used for [reusable content items](https://docs.kentico.com/documentation/business-users/content-hub.md) or [website channel pages](https://docs.kentico.com/documentation/business-users/website-content.md), or to [reusable field schemas](https://docs.kentico.com/documentation/developers-and-admins/development/content-types/reusable-field-schemas.md).
- Properties of [Page Builder](https://docs.kentico.com/documentation/developers-and-admins/development/builders/page-builder.md) components, such as [widgets](https://docs.kentico.com/documentation/developers-and-admins/development/builders/page-builder/widgets-for-page-builder.md), decorated by the`SmartFolderSelectorComponent` [attribute](https://docs.kentico.com/documentation/developers-and-admins/customization/extend-the-administration-interface/ui-form-components/reference-admin-ui-form-components.md#smart-folder-selector).

> **Tip:** You can also find the identifiers of smart folders manually in the _Content hub_ application – expand the menu actions of a folder and select _Properties_.

As smart folders can contain multiple content types, you can retrieve content either via the:

- `RetrieveContentOfContentTypes` method with a list of content types you want to retrieve from the smart folder
- `RetrieveContentOfReusableSchemas` method with a shared reusable schema implemented by the content types you want to retrieve from the smart folder

```csharp title="Retrieve content items from a smart folder"
using System;

using CMS.ContentEngine;
using CMS.DataEngine;
using Kentico.Content.Web.Mvc;

// ...

// A list of content types available in the smart folder
var contentTypes = new[] { ArticlePage.CONTENT_TYPE_NAME, BlogPage.CONTENT_TYPE_NAME };

var smartFolderGuid = model?.Properties?.SmartFolderSelectorField.Identifier ?? Guid.Empty;

var contentItems = await contentRetriever.RetrieveContentOfContentTypes<IContentItemFieldsSource>(
    contentTypes,
    RetrieveContentOfContentTypesParameters.Default,
    query => query.InSmartFolder(smartFolderGuid)
        .OrderBy(new OrderByColumn("ContentItemCommonDataLastPublishedWhen", OrderDirection.Descending))
        .TopN(5),
    new RetrievalCacheSettings(cacheItemNameSuffix:
        $"{nameof(RetrieveContentQueryParameters.InSmartFolder)}|{smartFolderGuid}|{nameof(RetrieveContentOfContentTypesQueryParameters.OrderBy)}|{nameof(OrderByColumn)}|{nameof(RetrieveContentQueryParameters.TopN)}|5"));
```

Setting the **order** and **maximum number** of retrieved items is not part of the options configured for the smart folder in the administration UI. If required, control these parameters using the `OrderBy` and `TopN` query parametrization.

The `InSmartFolder` parametrization causes the query to return an **empty result** if the specified smart folder:

- Doesn't exist
- Doesn't have dynamic content delivery enabled
- Has invalid filter conditions (for example if a tag saved in the _Taxonomy_ filter option was later deleted)

Using multiple `InSmartFolders` calls in a single query is not supported and results in an exception.

> **Tip:** **Retrieve content items of a single type from a smart folder**
>
> If you need to ensure that only items of one specific content type are retrieved (regardless of the smart folder’s filter condition), you can use `InSmartFolder` with the `RetrieveContent` method or provide just the one specific content type in the `RetrieveContentOfContentTypes` method.
>
> For example, to retrieve only items of the `ArticlePage` content type from a smart folder, you can use the following code:
>
> ```csharp title="Retrieve content items of a single type from a smart folder"
> using System;
>
> using CMS.ContentEngine;
> using Kentico.Content.Web.Mvc;
>
> // ...
>
> var smartFolderGuid = model?.Properties?.SmartFolderSelectorField.Identifier ?? Guid.Empty;
>
> var articleItems = await contentRetriever.RetrieveContent<ArticlePage>(
>     RetrieveContentParameters.Default,
>     query => query.InSmartFolder(smartFolderGuid),
>     new RetrievalCacheSettings(cacheItemNameSuffix:
>         $"{nameof(RetrieveContentQueryParameters.InSmartFolder)}|{smartFolderGuid}|{nameof(ContentTypesQueryParameters.OfContentType)}"));
> ```

#### Smart folder content and language fallbacks

[Language fallbacks](https://docs.kentico.com/documentation/developers-and-admins/configuration/languages.md) are **not** used when retrieving content items from a smart folder in a specific language.

For example, if you have Spanish configured to fall back to English, and you retrieve content from a smart folder in Spanish, items are not included if their Spanish language variant doesn't fulfill the folder's filter conditions (even if their English variant does).

#### Cache data retrieved from smart folders

[Caching the data](https://docs.kentico.com/documentation/developers-and-admins/development/caching/data-caching.md) of retrieved content items is recommended in most cases. However, smart folder conditions are set in the administration UI by content editors and are evaluated dynamically. Items move in and out of smart folders as their content and metadata changes. This makes it challenging to ensure that cached data does not become outdated.

The most practical approach is to set a reasonable short expiration time for cached data that is retrieved from a smart folder, depending on how often your project's content editors adjust content items and smart folder filter criteria.

In scenarios where you are retrieving one specific content type, you can also set a [cache dependency](https://docs.kentico.com/documentation/developers-and-admins/development/caching/cache-dependencies.md) on all items of the given content type, which ensures that the cache is cleared whenever any items of the type are updated.

> **Tip:** **ContentRetriever built-in caching**
>
> The `IContentRetriever` API provides [implicit caching](https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/content-retriever-api.md#implicit-result-caching) for all retrieval methods unless explicitly disabled. You can configure the cache behavior using `RetrievalCacheSettings`. For most scenarios, the built-in caching is sufficient and doesn't require manual cache management.

```csharp title="Cache data from a smart folder"
using System;

using CMS.ContentEngine;
using CMS.DataEngine;
using Kentico.Content.Web.Mvc;

// ...

// IContentRetriever with custom cache settings
var cacheSettings = new RetrievalCacheSettings(
    cacheItemNameSuffix: $"SmartFolder|{smartFolderGuid}",
    cacheExpiration: TimeSpan.FromMinutes(5));

var contentItems = await contentRetriever.RetrieveContentOfContentTypes<IContentItemFieldsSource>(
    new[] { "Sample.Type" },
    new RetrieveContentOfContentTypesParameters
    {
        WorkspaceNames = new[] { "MainContent" }
    },
    query => query.InSmartFolder(smartFolderGuid)
                    .OrderBy(new OrderByColumn("ContentItemCommonDataLastPublishedWhen", OrderDirection.Descending))
                    .TopN(5),
    cacheSettings);
```

### Content item security

Content items can be [secured](https://docs.kentico.com/documentation/business-users/content-hub/content-items.md#secure-content-items) using a three-tier access model. Each content item falls into one of three access levels:

- **Public** – accessible to all visitors without restriction.
- **Secured** – requires the visitor to [sign in](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication.md) before the content is displayed.
- **Secured with member roles** – requires the visitor to sign in _and_ belong to one or more designated [member roles](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication/member-roles.md).

By default, `IContentRetriever` excludes secured content items from query results. To include them, set the `IncludeSecuredItems` property of the `RetrieveContentParameters` object to `true`:

```csharp title="Retrieve secured content items"
using System.Threading.Tasks;

using Kentico.Content.Web.Mvc;

public class CustomComponent(IContentRetriever contentRetriever)
{
    // Information about whether to include secured items in the query execution passed from the caller
    public async Task ContentItemRetrieval(bool includeSecuredItems)
    {
        // Retrieves banners, including secured items if specified
        var banners = await contentRetriever.RetrieveContent<Banner>(
            new RetrieveContentParameters
            {
                IncludeSecuredItems = includeSecuredItems
            });
    }
}
```

#### Check content access with HasAccess

Use the `HasAccess` extension method on `IContentItemFieldsSource` to determine whether a visitor has access to a secured content item. The method accepts a `ClaimsPrincipal` and evaluates the item's security settings against the visitor's authentication state and role membership:

```csharp title="Check content access"
using CMS.ContentEngine;
using Kentico.Content.Web.Mvc;

// ...

// Retrieves banners including secured items
var banners = await contentRetriever.RetrieveContent<Banner>(
    new RetrieveContentParameters 
    { 
        IncludeSecuredItems = true
    });

foreach (Banner item in banners)
{
    // Returns true if the visitor is allowed to view the content
    bool canAccess = item.HasAccess(User);
}
```

`HasAccess` handles all three tiers of the access model:

- For public items, the method always returns `true`.
- For secured items, the method returns `true` if the visitor is signed in.
- For items secured with member roles, the method returns `true` if the visitor is signed in _and_ belongs to at least one of the required member roles.

> **Tip:** **HasAccess is the recommended approach**
>
> The `HasAccess` method is the recommended way to check content access in your presentation layer. It evaluates both authentication and role membership in a single call, replacing the need to check `ContentItemIsSecured` and `User.Identity.IsAuthenticated` separately.

#### Reflect content access in views

In Razor views, use `HasAccess` to display content based on the visitor's access level:

```cshtml title="Reflect content item security in views"
@using Kentico.Content.Web.Mvc

@model CompanyName.Models.MyModel

@if (Model.ContentItem.HasAccess(User))
{
    <p>@Model.ProtectedContent</p>
}
else if (User.Identity.IsAuthenticated)
{
    <p>
        You do not have the required member role to view this content.
    </p>
}
else
{
    <p>
        Sign in to view this content.
    </p>
}
```

#### Project security properties

The secured state of a retrieved content item is indicated by its `SystemFields.ContentItemIsSecured` property. The `ContentItemRequiredMemberRoleNames` property contains the code names of [member roles](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication/member-roles.md) required for access (e.g., `["Subscriber", "Premium_Member"]`). For public and secured items without role restrictions, the collection is empty or null.

> **Tip:** **Lazy loading of role data**
>
> The system only fetches role data from the database when at least one item in the query results has `ContentItemIsSecured` set to `true`. For queries that return only public items, no additional database calls are made.

Both pages and content items use the same properties to determine their security configuration. When working with collections of linked content items (provided, e.g., via a selection UI managed by 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) UI form component), you can determine security requirements via projection:

```csharp title="Project content item security properties"
// Contains a collection of sample 'Clinic' content items - retrieval code omitted for brevity
var clinics = await GetMedicalClinics();

// Projects the secured state of each content item
var securedClinics = clinics.Select(x => x.SystemFields.ContentItemIsSecured);

// Projects the required member role names for each content item
var requiredRoles = clinics.Select(x => x.SystemFields.ContentItemRequiredMemberRoleNames);
```

### Content item names

There are several name fields related to each content item that represent various names used throughout the system:

- **Code name** – a unique identifier of the content item, used primarily in code. Code names are stored in the `ContentItemName` property of each content item.
- **Display name** – the name displayed for the item in the administration interface. Display names are not available via the API, use a _Title_ field instead.
- **_Title_ field** – a custom [field](https://docs.kentico.com/documentation/developers-and-admins/development/content-types.md#add-fields) that we recommend you to add to your content types. The _Title_ field represents the name which is used when displaying the content item in the presentation layer.

### Date and time fields

`DateTime` fields and system properties of retrieved content items always have values in the time zone of the server where the application is running. If you wish to display values in a different time zone (e.g., in a website visitor's local time), perform a [time conversion](https://learn.microsoft.com/en-us/dotnet/standard/datetime/converting-between-time-zones) using the standard .NET API.

## Retrieve linked content items

To retrieve a list of content items linked to a page or another content item:

1. [Retrieve](#retrieve-content-items) the object representing the content item or page containing linked content items using `IContentRetriever`.
2. Retrieve linked content items by accessing content item fields of the retrieved object.

```csharp title="Retrieve linked content items"
using System.Linq;
using System.Threading.Tasks;

using CMS.ContentEngine;
using Kentico.Content.Web.Mvc;

public class CustomComponent(IContentRetriever contentRetriever)
{
    private async Task SampleContentQuery()
    {    // Retrieves 3 banners with linked items (1 level deep)
        var banners = await contentRetriever.RetrieveContent<Banner>(
            new RetrieveContentParameters
            {
                LinkedItemsMaxLevel = 1
            },
            query => query.TopN(3),
            new RetrievalCacheSettings(cacheItemNameSuffix:
                                            $"{nameof(RetrieveContentQueryParameters.TopN)}|3"));

        // Accesses the content item data
        foreach (Banner item in banners)
        {
            // Accesses linked content item
            Image image = item.BannerBackgroundImage.FirstOrDefault();

            // Accesses content type fields of the linked item
            string description = image.ImageShortDescription;

            // Accesses system fields of the linked item
            VersionStatus status = image.SystemFields.ContentItemCommonDataVersionStatus;
        }
    }
}
```

> **Tip:** You can set the `LinkedItemsMaxLevel` parameter in `RetrieveContentParameters` to ensure that the linked items are loaded within the same database query as the retrieved content item. The `LinkedItemsMaxLevel` parameter controls the depth to which linked items are retrieved.

## Retrieve assets

To retrieve information about an asset, like filename, file size, URL, or width and height (if available) from a content item that has an asset field:

1. [Retrieve](#retrieve-content-items) the object representing the content item or page containing linked content items using `IContentRetriever`.
2. Retrieve a `ContentItemAsset` object from the asset field and access its properties.
   - It is strongly recommended to use [generated content type classes](https://docs.kentico.com/documentation/developers-and-admins/api/generate-code-files-for-system-objects.md) that allow you to work with [content type](https://docs.kentico.com/documentation/developers-and-admins/development/content-types.md) fields using strongly-typed objects.

```csharp title="Retrieve content item assets"
using System.Linq;
using System.Threading.Tasks;

using CMS.ContentEngine;
using Kentico.Content.Web.Mvc;

public class CustomComponent(IContentRetriever contentRetriever)
{
    private async Task SampleContentQuery()
    {
        // Retrieves 3 banners with linked items
        var banners = await contentRetriever.RetrieveContent<Banner>(
            new RetrieveContentParameters
            {
                LinkedItemsMaxLevel = 1
            },
            query => query.TopN(3),
            new RetrievalCacheSettings(cacheItemNameSuffix:
                                            $"{nameof(RetrieveContentQueryParameters.TopN)}|3"));

        // Accesses the content item data
        foreach (Banner item in banners)
        {
            // Accesses linked content item
            Image image = item.BannerBackgroundImage.FirstOrDefault();

            // Accesses the asset object in the ImageFile property of the Image content type
            ContentItemAsset asset = image.ImageFile;

            // Accesses the properties of the asset
            int? width = asset.Metadata.Width;
            int? height = asset.Metadata.Height;
            string extension = asset.Metadata.Extension;
            string url = asset.Url;
        }
    }
}
```

### Retrieve image variants

To retrieve a specific [variant](https://docs.kentico.com/documentation/developers-and-admins/development/content-types.md#configure-image-variants) of an image asset:

1. [Retrieve](#retrieve-assets) the `ContentItemAsset` object.
2. Access the properties of the image variant using its code name identifier.

```csharp title="Retrieve image variants"
using CMS.ContentEngine;
using Kentico.Content.Web.Mvc;

// ...

// Retrieves a content item asset
// ...

// Accesses the asset object in the ImageFile property of the asset's content type
ContentItemAsset asset = myAsset.ImageFile;

// Accesses the properties of an image variant with the 'Hero' code name
if (asset.Metadata.Variants.ContainsKey("Hero")){
    int variantWidth = asset.Metadata.Variants["Hero"].Width;
    int variantHeight = asset.Metadata.Variants["Hero"].Height;
    string variantType = asset.metadata.Variants["Hero"].TransformationType;
    string variantUrl = asset.VariantUrls["Hero"];
}
```

To display the retrieved image variant on a live site of a [website channel application](https://docs.kentico.com/documentation/developers-and-admins/configuration/website-channel-management.md), you can also use the provided [Tag Helpers](https://docs.kentico.com/documentation/developers-and-admins/development/reference-tag-helpers.md#attribute-tag-helpers-images).

### Secured assets

[Content item assets](https://docs.kentico.com/documentation/business-users/content-hub/content-item-assets.md) configured to [require authentication or specific member roles](https://docs.kentico.com/documentation/business-users/content-hub/content-items.md#secure-content-items) return [HTTP 401 (Unauthorized)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/401) for assets that require authentication and [HTTP 403 (Forbidden)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/403) for signed-in members without at least one of the required roles. Asset security uses the same role-based access logic as [content item security](#content-item-security). In such cases, consider displaying a placeholder teaser image instead. For example, a popular practice is to display a blurred teaser image overlaid with a lock icon.

## Retrieve content items for preview

The `IContentRetriever` API automatically handles preview context, retrieving the appropriate content versions based on the current request context:

- For the live site, retrieves published versions according to security claims
- For preview and builders, retrieves the latest available version regardless of workflow state or security

You can use the `IsForPreview` parameter of the `RetrievePagesParameters` object to force either only preview or only live data.

```csharp title="Always retrieve latest data"
using Kentico.Content.Web.Mvc;

// ...

var banners = await contentRetriever.RetrieveContent<Banner>(
    new RetrieveContentParameters
    {
        IsForPreview = true
    });
```
