Retrieve page content

Web page content is stored in the database and edited through the administration interface using the content tree in website channel applications.

Xperience by Kentico provides the ContentRetriever API as the primary and recommended approach for retrieving page content. This API simplifies content retrieval with built-in caching, context awareness, and optimized performance.

The ContentRetriever API works with:

  • Generated content type classes – classes generated by the system that allow you to work with content type fields using strongly-typed objects. These classes also allow access to all general page data (page title, ID, GUID, creation date, publish date, etc.).
  • Custom data transfer objects (advanced use case) – using custom DTOs grants you control over the mapping logic. See Custom model mapping.

You can also use:

The implementation and complexity of the retrieval and management code depend on your preferences and project requirements, and can range from simple method calls within controller actions to custom solutions utilizing repository and service patterns. Install the sample Dancing Goat project to view a reference implementation.

Retrieve page data

To retrieve web page content, use the IContentRetriever service from the Kentico.Content.Web.Mvc namespace:

The service provides built-in caching, channel context awareness, and optimal retrieval performance. You can use the IContentRetriever to Retrieve the current page, Retrieve pages of a single content type, and more. See Reference - ContentRetriever API for a list of all available methods.

C#
Sample page retrieval


// Services obtained via dependency injection
private readonly IContentRetriever contentRetriever;

public async Task PageRetrieval()
{
    // Retrieves pages of the 'ArticlePage' content type from the /Articles section
    var pages = await contentRetriever.RetrievePages<ArticlePage>(
        new RetrievePagesParameters 
        { 
            PathMatch = PathMatch.Children("/Articles"),
        });

    // Displays the page data
    foreach(var page in pages)
    {
        Console.WriteLine(page.ArticleTitle);
        Console.WriteLine(page.ArticlePageSummary);
    }
}

For scenarios requiring advanced query customization, you can use the content item query API:

  • ContentItemQueryBuilder class with the ForWebsite query parametrization method – to create and parametrize custom queries specifically for retrieving website data.
  • IContentQueryExecutor interface and its GetMappedWebPageResult method – to execute custom queries and map the results to model classes.

Retrieve multilingual page data

To retrieve web page content in a specific language using the IContentRetriever, specify the desired language when calling the retrieval methods by providing them with a RetrievePagesParameters object with the LanguageName property set. If you omit the language, the method will return results in the primary language of the website channel.

C#
Sample multilingual page retrieval


// Retrieves pages in the Spanish language
var pages = await contentRetriever.RetrievePages<ArticlePage>(
    new RetrievePagesParameters { LanguageName = "es" }
);

Pages in fallback language

If the desired language variant of a page doesn’t exist, the query returns the page data in the fallback language, if fallbacks are configured and unless the UseLanguageFallbacks property of the RetrievePagesParameters object is explicitly set as false.

Filter pages based on content tree structure

You can set the query to only include pages from a certain section of the content tree or omit pages from a section using the PathMatch property of the RetrievePagesParameters object. PathMatch expressions can be combined to more accurately specify what pages are included in the query.

  • Single – only retrieves a single page that corresponds to the specified tree path.
    • E.g., PathMatch.Single(path: "/Articles/Coffee_processing_techniques")
  • Children – recursively retrieves all children of a specified parent page, excluding the parent page from the query. You can also specify a nesting level to limit the depth of recursion.
    • E.g., PathMatch.Children(path: "/Articles", nestingLevel: 3)
  • SkipChildren – recursively exclude all children of a specified parent page from the query, except for the parent page. You can also specify a nesting level to limit the depth of recursion.
    • E.g., PathMatch.SkipChildren(path: "/Articles/Coffee", nestingLevel: 3)
  • Section – recursively retrieves all children of a specified parent page, including the parent page in the query. You can also specify a nesting level to limit the depth of recursion.
    • E.g., PathMatch.Section(path: "/Articles", nestingLevel: 3)
  • SkipSection – recursively exclude all children and the specified parent page from the query. You can also specify a nesting level to limit the depth of recursion.
    • E.g., PathMatch.SkipSection(path: "Articles/Coffee", nestingLevel: 3)

Combine PathMatch expressions

If you need to combine multiple PathMatch expressions, use content item query and pass an array as the argument to the ForWebsite method.

C#
Example - Combine PathMatch expressions


var builder = new ContentItemQueryBuilder()
                    .ForContentType(
                        "My.ArticlePage",
                        config => config
                            .ForWebsite(
                                websiteChannelName: "MyWebsiteChannel",
                                pathMatches: new PathMatch[]{
                                    PathMatch.Children("/Articles"),
                                    PathMatch.SkipSection("/Articles/Coffee_processing_techniques")
                                }
                            )
                    );

Filter pages based on tags

You can limit the retrieval to only retrieve pages with the specified tags using the additionalQueryConfiguration parameter with the Where method and its WhereContainsTags condition:

C#
Example - Filter by tags


// Retrieves pages that contain both "coffee" and "processing" tags
var pages = await contentRetriever.RetrievePages<ArticlePage>(
    new RetrievePagesParameters 
    { 
        PathMatch = PathMatch.Children("/Articles") 
    },
    query => query.Where(where => where.WhereContainsTags("coffee", "processing")),
    new RetrievalCacheSettings(cacheItemNameSuffix:
        $"{nameof(WhereParameters.Where)}|{nameof(WhereParameters.WhereContainsTags)}|coffee|processing"));

See Retrieve content items for more information on working with tags.

Page security configuration

Pages can be secured using a three-tier content access model. Depending on the access settings configured for a page, the system determines whether the visitor is allowed to view the content:

  • Public – the page is accessible to all visitors without restrictions.
  • Secured – the page requires the visitor to be an authenticated member.
  • Secured with member roles – the page requires the visitor to be an authenticated member who belongs to at least one of the designated member roles.

By default, the IContentRetriever does not include secured pages in the query results. You can change this behavior by setting the IncludeSecuredItems property of the RetrievePagesParameters object to true:

C#
Example - Include secured pages


var pages = await contentRetriever.RetrievePages<ArticlePage>(
    new RetrievePagesParameters 
    { 
        IncludeSecuredItems = true // Includes secured pages in the results
    });

Check access with HasAccess

The HasAccess extension method on IContentItemFieldsSource is the recommended way to check whether a visitor has access to a retrieved content item. The method evaluates the page’s security state, the visitor’s authentication status, and the visitor’s member role assignments in a single call:

C#
Example - Check access using HasAccess


using Kentico.Content.Web.Mvc;

...

// Retrieves secured pages
var pages = await contentRetriever.RetrievePages<ArticlePage>(
    new RetrievePagesParameters 
    { 
        IncludeSecuredItems = true
    });

foreach (var page in pages)
{
    // Checks if the current visitor has access to the page
    bool canAccess = page.HasAccess(HttpContext.User);
}

HasAccess returns true if:

  • The page is not secured (public).
  • The page is secured and the visitor is authenticated (when no specific member roles are required).
  • The page is secured with member roles and the visitor is authenticated and belongs to at least one of the required roles.

You can use the result to conditionally display content in Razor views:

cshtml
Reflect page security in views


@using Kentico.Content.Web.Mvc

@if (!Model.Page.HasAccess(User))
{
    <p>
        Sign in or upgrade your membership to access this page.
    </p>
}

Additional security properties

The secured state of a retrieved page is available through page.SystemFields.ContentItemIsSecured. To see which member roles are required for a secured page, access page.SystemFields.ContentItemRequiredMemberRoleNames, which returns an IReadOnlyCollection<string> of role code names. For unsecured pages, the collection is empty.

Authentication and authorization responses

When a visitor requests a secured page that they are not allowed to view, the system distinguishes between two scenarios:

  • Not authenticated (HTTP 401) – the visitor is not signed in. The system issues a challenge that redirects the visitor to the sign-in page.
  • Forbidden (HTTP 403) – the visitor is signed in but does not have the required member role. The system redirects the visitor to the access denied page.

You can configure ASP.NET Identity cookie authentication to handle both scenarios. Set LoginPath for unauthenticated redirects and AccessDeniedPath for insufficient-role redirects:

C#
Program.cs


builder.Services.ConfigureApplicationCookie(options =>
{
    // Redirects unauthenticated visitors to the sign-in page
    options.LoginPath = new PathString("/account/signin");
    
    // Redirects authenticated visitors without the required role to the access denied page
    options.AccessDeniedPath = new PathString("/account/access-denied");
});

Work with retrieved page data

You can access various types of data from retrieved page objects:

  • Content type fields – the data that is editable in a page’s Content view mode. The set of available fields is configurable via the field editor.
  • System fields – available under the SystemFields property of the retrieved page objects. Access WebPage* fields for web page data and ContentItem* for data of the underlying content item.
  • Page URL – see Retrieve page URLs.
C#
Access page data


// Retrieves a page
var page = await contentRetriever.RetrievePages<ArticlePage>();

// Accesses the ID of the parent
var parentId = page.SystemFields.WebPageItemParentID;

// Accesses the code name of the page object
var pageName = page.SystemFields.WebPageItemName;

Access page field data

The fields available in a page’s Content view mode are specific to its content type. You can see the fields that each content type uses:

  • In Content types (application) → edit a content type → Fields tab
  • In the corresponding <namespace>_<content_type_name> database table

You can access specific fields of a content type directly using strongly typed properties when using generated content type classes:

C#
Access content type fields


// Retrieves a page
var page = await contentRetriever.RetrievePages<ArticlePage>();

// Accesses the 'Text' field of the page
var pageText = page.ArticlePageText;

// Accesses the 'Teaser' field of the page
var pageImage = page.ArticlePageTeaser.FirstOrDefault();

Resolving HTML tags and relative URLs

Fields which are populated by the Rich text editor form component may contain HTML tags and relative links. To ensure that the content is displayed correctly when rendered in Razor views, use the Html.Raw method, which disables HTML encoding for the values.

cshtml


@Html.Raw(Model.<RichTextFieldProperty>)

Automatic URL resolving

The system provides page output filtering functionality that automatically resolves all virtual relative URLs to their absolute form. This filter ensures that links added by content editors into page content work correctly, even if you do not explicitly handle URL resolving in your code.

Date and time fields

DateTime fields and system properties of retrieved pages 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 using the standard .NET API.

Access context of the current request

Xperience by Kentico provides interfaces that help you access information about the current context.

Access context of the current channel

To retrieve information about the website channel context of the current request, use an instance of the IWebsiteChannelContext interface (e.g., obtained via dependency injection) from the CMS.Websites.Routing namespace.

Access the following properties:

  • WebsiteChannelID – the ID of the current website channel.
  • WebsiteChannelName – code name of the current website channel.
  • IsPreview – a boolean value that, if true, signifies whether the current request is made in preview (Page Builder or the preview mode in a website channel application).

Access current preferred language

To retrieve the preferred language of the current request, use the Get method of the IPreferredLanguageRetriever interface (e.g., obtained via dependency injection).

Note that the preferred language of the request can be different from the actual language of the retrieved content. For example, if language variant of a page does not exist in the preferred language, fallback language variant is retrieved.

C#
Retrieve currently preferred language


// An instance of  IPreferredLanguageRetriever (e.g., obtained via dependency injection)
private readonly IPreferredLanguageRetriever preferredLanguageRetriever;

// Retrieves the code name of the preferred language
string languageName = preferredLanguageRetriever.Get();

Retrieve pages for preview

The ContentRetriever API automatically handles preview context, retrieving the appropriate page 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.

C#
Always retrieve latest data


var pages = await contentRetriever.RetrievePages<ArticlePage>(
    new RetrievePagesParameters 
    { 
        IsForPreview = true // Force retrieval of preview data
    });

Add preview context to URLs

You may encounter problems in Preview mode on pages that send requests to a custom API endpoint, which uses IWebsiteChannelContext to access the current channel in its implementation. To ensure that such endpoints work correctly in Preview mode, you need to add preview context data to the endpoint URL.

cshtml
Example


@using Kentico.Content.Web.Mvc

const endpointUrl = @Url.Kentico().ApplyPreviewContext("url");

The ApplyPreviewContext Razor extension method adds various parameters to the endpoint URL, which ensure that IWebsiteChannelContext is able to identify the channel, where the previewed page belongs, regardless of the domain used to access the admin UI.

Retrieve folders

To retrieve the folders from the content tree of a website channel (e.g., to create a page under the folder), use the Retrieve method of the IWebPageFolderRetriever interface (e.g., obtained via dependency injection).

C#
Retrieve folders


// Services obtained via dependency injection
private readonly IWebPageFolderRetriever folderRetriever;
private readonly IWebsiteChannelContext channelContext;

// Retrieves a folder from the specified path
WebPageFolder folder = (await folderRetriever.Retrieve(channelContext.WebsiteChannelName, PathMatch.Children("/Articles"))).FirstOrDefault();

// Use the WebPageFolder object to access information about the folder
int id = folder.ContentItemID;