---
title: Content item query API
related:
  - https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/reference-content-item-query.md
  - https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/content-item-database-structure.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).

Content item query is the default system API for content item retrieval. It allows you to retrieve content items based on their [content type](https://docs.kentico.com/documentation/developers-and-admins/development/content-types.md). Each query can be modified using SQL-like fluent API.

Using content query consists of the following steps:

1. Building the query using `ContentItemQueryBuilder`.
2. Running the query using `IContentQueryExecutor` and mapping the result to a model class for further use.

## Build queries

To build content item queries, use `ContentItemQueryBuilder`. The class provides fluent API that allows you to tailor each query to your requirements.

```csharp title="Build a query" highlight="4-7"
using CMS.ContentEngine;
// ...

// The builder class must be directly instantiated
var builder = new ContentItemQueryBuilder();
// Selects all items of the 'Acme.Article' content type
builder.ForContentType("Acme.Article");
```

Each `ForContentType` call begins a subquery where you can further adjust the retrieval parameters for the corresponding content type.

```csharp title="Parameterize a subquery" highlight="4-6"
// Selects an article called 'Security'
builder.ForContentType("Acme.Article", subqueryConfiguration => 
{
    subqueryConfiguration
        .TopN(1)
        .Where(where => where.WhereEquals("ContentItemName", "Security"));
});
```

> **Info:** For all available parameterization options, see [Reference - Content item query](https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/reference-content-item-query.md).

Finally, the entire query can be modified.

```csharp title="Parameterize the entire query" highlight="6"
builder.ForContentTypes(parameters =>
        {
            parameters.OfContentType("Acme.Article", "Acme.NewsRelease")
        })
        // Sorts all records according to the 'ContentItemName' column
       .Parameters(globalParams => globalParams.OrderBy("ContentItemName"));
```

The following diagram illustrates the general structure of content queries:

![Content item query structure diagram](https://docs.kentico.com/docsassets/documentation/content-item-query-api/ContentItemQueryStructure.png "Content item query structure diagram")

> **Info:** **Loading other objects**
>
> To learn how to retrieve other types of data from the Xperience database, see [ObjectQuery API](https://docs.kentico.com/documentation/developers-and-admins/api/objectquery-api.md).

## Run queries and map the result

Queries are executed using `IContentQueryExecutor`, which retrieves data according to the passed `ContentItemQueryBuilder` instance. When retrieved, the query result is a collection of database rows. To transform the data into a typed format suitable for C#, part of query execution is a process known as _model binding_.

Model binding maps the data from each row to a C# object, assigning each column an appropriate C# type in the process. The resulting object instance is called a _strongly-typed representation_ of the database data. Xperience provides [code generators](https://docs.kentico.com/documentation/developers-and-admins/api/generate-code-files-for-system-objects.md) that enable developers to generate model classes (C# objects) directly mirroring each content type's database representation. These classes are directly used in the model binding process.

`IContentQueryExecutor` provides two approaches to facilitate model binding:

- [GetMappedResult\<TModel>](#using-getmappedresult-methods) (`GetMappedWebPageResult<TModel>` for page content types). These methods fully abstract the model binding process, directly returning strongly-typed models.
- [GetResult\<TModel>](#using-getresult-methods) (`GetWebPageResult<TModel>` for page content types). These methods expose the model binding logic that gives you direct access to each row of the database data, allowing you to customize the mapping process.

> **Note:** When retrieving pages, use the page-result variants (`GetMappedWebPageResult<TModel>` or `GetWebPageResult<TModel>`) together with a page model class. To read or filter by page fields (such as the URL or tree path), the query must also include page data, see [ForWebsite](https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/reference-content-item-query.md#fcts-forwebsite) or [WithWebPageData](https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/reference-content-item-query.md#fcts-wwpd).

### Using GetMappedResult methods

Using `GetMappedResult<TModel>`, the system runs the query and binds the result to a collection of _TModel_ classes automatically in the background. This approach is recommended for the majority of scenarios.

```csharp title="Run a query using GetMappedResult<TModel>" highlight="12-13"
using CMS.ContentEngine;

// Contains an instance of 'IContentQueryExecutor'
// obtained using dependency injection
private readonly IContentQueryExecutor contentQueryExecutor;

var builder = new ContentItemQueryBuilder();
builder.ForContentType(Article.CONTENT_TYPE_NAME);

// The 'Article' class is generated by the code generator
// for a corresponding 'Article' content type
IEnumerable<Article> articles = 
    await contentQueryExecutor.GetMappedWebPageResult<Article>(builder);
```

The model binding logic matches database column names to the model's properties, with certain exceptions made for system data.

When retrieving data that consists of multiple content types, you must, using the _TModel_ generic, cast the result to a type shared by all model classes. Depending on the contents of the result, you have the following options:

- Use `IContentItemFieldsSource`. This interface is by default implemented by all [generated model classes](https://docs.kentico.com/documentation/developers-and-admins/api/generate-code-files-for-system-objects.md).

  ```csharp title="Getting items of multiple content types" highlight="16"
  using CMS.ContentEngine;

  // Contains an instance of 'IContentQueryExecutor'
  // obtained using dependency injection
  private readonly IContentQueryExecutor contentQueryExecutor;

  var builder = new ContentItemQueryBuilder();
  builder.ForContentTypes(query =>
  {
      query.OfContentType(Article.CONTENT_TYPE_NAME, Blog.CONTENT_TYPE_NAME);
      query.WithContentTypeFields();
  });

  // Gets a mixed collection of articles and blogs
  IEnumerable<IContentItemFieldsSource> result = 
      await executor.GetMappedResult<IContentItemFieldsSource>(builder);

  // Gets all articles 
  List<Article> articles = result.OfType<Article>().ToList();
  // Gets all blogs
  List<Blog> blogs = result.OfType<Blog>().ToList();
  ```

- When retrieving items that share a [reusable field schema](https://docs.kentico.com/documentation/developers-and-admins/development/content-types/reusable-field-schemas.md), reference the schema interface in _TModel_:

  ```csharp title="Getting items that share a reusable field schema" highlight="15"
  using CMS.ContentEngine;

  // Contains an instance of 'IContentQueryExecutor'
  // obtained using dependency injection
  private readonly IContentQueryExecutor contentQueryExecutor;

  var builder = new ContentItemQueryBuilder();
  builder.ForContentTypes(query =>
  {
      query.OfReusableSchema("PageMetadata");
  });

  // Gets a collection of items with the 'PageMetadata' schema
  IEnumerable<IPageMetadata> result = 
      await executor.GetMappedWebPageResult<IPageMetadata>(builder);
  ```

- Use `System.Object` in case the data shares no common ancestor type.

The `GetMappedResult` methods also provide overloads that allow you to manipulate the model after its data was bound.

```csharp title="Modify bound data" highlight="2"
IEnumerable<Article> articles =
    await executor.GetMappedWebPageResult<Article>(builder, null, OverrideMapping);

// Called after each item is bound
// 'IContentQueryDataContainer' contains the current row data
// 'Article' is the instance of the bound model class
private Article OverrideMapping(IContentQueryDataContainer container, Article article)
{
    // Custom logic to modify/extend the default mapping...

    return article;
}
```

### Using GetResult methods

Using `GetResult<TModel>` allows you to take over the entire model binding process.

```csharp title="Run a query and map the data using GetResult<TModel>" highlight="10"
using CMS.ContentEngine;

// Contains an instance of 'IContentQueryExecutor'
// obtained using dependency injection
private readonly IContentQueryExecutor contentQueryExecutor;

// Executes the query specified within 'contentItemQueryBuilder'
// and binds it using the logic in the 'ModelBinder' delegate
var result = 
    await contentQueryExecutor.GetResult(contentItemQueryBuilder, ModelBinder);
```

Where `ModelBinder` is a delegate function used to map the retrieved data to the result (can be asynchronous) that gives you direct access to each retrieved data row. You can use `IContentQueryModelTypeMapper.Map`, or provide custom binding logic to map the data.

```csharp title="IContentQueryModelTypeMapper usage" highlight="14"
using CMS.ContentEngine;

// Contains an instance of 'IContentQueryModelTypeMapper' (e.g., obtained using dependency injection)
private readonly IContentQueryModelTypeMapper mapper;

// Maps the result to 'MyModelClass'
private MyModelClass ModelBinder(IContentQueryDataContainer container)
{
    // Maps the data from the container (representing 
    // one content item) to the model class
    // The mapper performs case-insensitive mapping from the type's 
    // database columns to the class's properties, with a few exceptions 
    // (see the method's API documentation)
    return mapper.Map<MyModelClass>(container);
}
```

Models can be either

- [generated classes](https://docs.kentico.com/documentation/developers-and-admins/api/generate-code-files-for-system-objects.md) – generated classes directly mirror content type fields as defined via the [field editor](https://docs.kentico.com/documentation/developers-and-admins/customization/field-editor.md) and work seamlessly with the mapper API.
- (advanced use case) custom classes – using custom classes enables you to map only desired columns. Before using custom classes, familiarize yourself with the mapper API or prepare custom mapping logic. 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.

```csharp title="Example - Retrieve and bind to a generated model class"
using System;
using System.Collections.Generic;

using CMS.ContentEngine;

// Contains instances obtained using constructor dependency injection
private readonly IContentQueryExecutor contentQueryExecutor;
private readonly IContentQueryModelTypeMapper mapper;

var contentItemQueryBuilder = new ContentItemQueryBuilder();

// Selects all objects of the 'VacationSpot' content type
contentItemQueryBuilder.ForContentType(VacationSpot.CONTENT_TYPE_NAME);

// Executes the query specified within 'contentItemQueryBuilder' and binds it to the 'VacationSpot' class generated for the 'VacationSpot' content type
IEnumerable<VacationSpot> result =
        await contentQueryExecutor
                .GetResult(contentItemQueryBuilder,
                           container => mapper.Map<VacationSpot>(container));
```

> **Tip:** See the **Content items** section in the [API Examples](https://docs.kentico.com/api.md) for more examples.

```csharp title="Example - Retrieve and bind to a custom model class"
using System;
using System.Collections.Generic;

using CMS.ContentEngine;

// Contains instances obtained using constructor dependency injection
private readonly IContentQueryExecutor contentQueryExecutor;
private readonly IContentQueryModelTypeMapper mapper;

// Executes the query specified within 'contentItemQueryBuilder' and binds it using the logic in 'DtoBinder'
IEnumerable<Dto> result = contentQueryExecutor.GetResult(contentItemQueryBuilder, DtoBinder);

// A function delegate that binds the returned records to a custom model.
// The content type of the item being bound is stored in 'IContentQueryDataContainer.ContentTypeName'
private Dto DtoBinder(IContentQueryDataContainer container)
{
    // 'IContentQueryModelTypeMapper' maps column data to corresponding 
    // properties based on matching names. For the example 'Dto' object,
    // only columns named 'Title' and 'Content' get mapped in addition to 'SystemFields'.
    // All other fields of the content type are ignored.
    return mapper.Map<Dto>(container);
}

// A data transfer object used as a container for the retrieved data
// The structure of these objects is completely under your control
public class Dto
{
    // Maps Xperience-specific fields
    // When mapping pages, use the 'CMS.Websites.WebPageFields' type instead
    public ContentItemFields SystemFields { get; set; }
    // Maps the 'Title' column from the database
    public string Title { get; set; }
    // Maps the 'Content' column from the database
    public string Content { get; set; }
}
```

### Query execution options

The `ContentQueryExecutionOptions` class allows you to optionally configure querying behavior. See [Reference - Content item query](https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/reference-content-item-query.md#icontentqueryexecutor-configuration) for a list of available configuration options.

```csharp title="Example - Configure query execution" highlight="6"
// Ensures the latest version of the selected content items, 
// regardless of workflow state (e.g., returns items in 'Draft')
contentQueryExecutor.GetResult(contentItemQueryBuilder,
                               ModelBinder,
                               new ContentQueryExecutionOptions()
                                    { ForPreview = true });
```
