---
title: Displaying page content
related:
  - https://docs.kentico.com/13/developing-websites/retrieving-content/displaying-page-attachments.md
  - https://docs.kentico.com/13/custom-development/working-with-pages-in-the-api.md
  - https://docs.kentico.com/13/managing-users/configuring-permissions/configuring-page-permissions/implementing-page-permission-checks.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).

Page content is stored in the database and [edited](https://docs.kentico.com/13/managing-website-content/working-with-pages.md) through the administration interface using the content tree in the **Pages** application. To display the content on your site, you need to retrieve the data in the code of your MVC application.

The implementation and complexity of the code depends on your preferences and project requirements, ranging from simple method calls within controller actions to custom solutions utilizing repository and service patterns. You can then use the retrieved page content to populate prepared view models and display them in your views.

## Retrieving page data

To retrieve page content, use the **IPageRetriever** service, together with [generated classes](https://docs.kentico.com/13/developing-websites/generating-classes-for-xperience-objects.md) representing specific page types. The generated page type classes allow you to work with strongly typed page objects and easily access their fields. The following example demonstrates the retrieval of a sample _Article_ page type:

```csharp

private readonly IPageRetriever pageRetriever;

// Gets an instance of the IPageRetriever service using dependency injection
public ExampleController(IPageRetriever pageRetriever)
{
    this.pageRetriever = pageRetriever;
}

public ActionResult Index()
{
    // Retrieves pages of 'Article' page type that are in the '/Articles/May' section of the content tree
    var articles = pageRetriever.Retrieve<Article>( query => query
                    .Path("/Articles/May", PathTypeEnum.Children));
}

```

To filter the retrieved pages, use the methods listed in [Reference - DocumentQuery methods](https://docs.kentico.com/13/custom-development/working-with-pages-in-the-api/reference-documentquery-methods.md).

> **Tip:** **Tip**: Optimize the performance of your website by [caching the retrieved page data](https://docs.kentico.com/13/configuring-xperience/configuring-caching/caching-on-mvc-sites.md).

### Selecting content based on page taxonomy

Pages on Xperience websites can be categorized and organized in several different ways. The code that you use to retrieve content from specific "categories" depends on the taxonomy approach used by the given pages:

- **Content tree structure** – for pages categorized using the parent-child structure of the content tree, select the content using [DocumentQuery methods](https://docs.kentico.com/13/custom-development/working-with-pages-in-the-api/reference-documentquery-methods.md) such as _Path_ and _NestingLevel_. You can filter out [linked pages](https://docs.kentico.com/13/managing-website-content/working-with-pages/copying-and-moving-pages-creating-linked-pages.md) from the data by adding the _FilterDuplicates_ method.

  ```csharp

  // Gets the articles contained directly under the '/Articles/Featured' section of the content tree
  var articles = pageRetriever.Retrieve<Article>( query => query
                      .Path("/Articles/Featured/", PathTypeEnum.Children)
                      .NestingLevel(1));

  ```
- **Categories** – for pages organized by [assigning categories](https://docs.kentico.com/13/managing-website-content/working-with-pages/categorizing-pages/assigning-pages-to-categories.md), select the content using the _InCategories_ DocumentQuery method:

  ```csharp

  // Gets the article pages assigned to the 'Featured' category
  var articles = pageRetriever.Retrieve<Article>( query => query
                      .InCategories("Featured"));

  ```
- **Tags** – for pages marked by [tags](https://docs.kentico.com/13/managing-website-content/working-with-pages/categorizing-pages/tagging-pages.md), select the content using the _WithTag_ DocumentQuery method:

  ```csharp

  // Gets the articles marked with the 'Coffee' tag from the 'Beverages' tag group
  var articles = pageRetriever.Retrieve<Article>( query => query
                      .WithTag("Coffee", "Beverages"));

  ```

## Working with retrieved page data

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

- Page fields – the data that is editable on a page's _Content_ tab.
- General page data – properties available for all pages (via the _TreeNode_ class). For example identifiers, values indicating the position in the content tree, etc.
- Page URL – the URL under which the page is available on the live site. See [Getting page URLs](#getting-page-urls).
- Metadata – SEO-related data like the _page title_ and _page description_. See [Working with page metadata](#working-with-page-metadata).
- Page attachments – for information about retrieving page attachments, see [Displaying page attachments](https://docs.kentico.com/13/developing-websites/retrieving-content/displaying-page-attachments.md).

```csharp title="Example"

// Retrieves a specific page
var article = pageRetriever.Retrieve<Article>(query => query
                        .WithGuid(nodeGuid))
                        .FirstOrDefault();

// Accesses the ID of the page's parent node in the content tree
int parentNodeId = article.NodeParentID;

// Accesses the 'DocumentName' data field
string pageName = article.DocumentName;


```

### Accessing page field data

The fields available on a page's _Content_ tab are specific to its [Page type](https://docs.kentico.com/13/developing-websites/defining-website-content-structure/managing-page-types.md). You can see the fields that each page type uses:

- In **Page types** (application)\*->_edit page type_->\***Fields** tab
- In the corresponding _\__ database table

We recommend accessing specific fields of a page type via the _Fields_ property:

```csharp

// Retrieves a specific page
var article = pageRetriever.Retrieve<Article>(query => query
                        .WithGuid(nodeGuid))
                        .FirstOrDefault();

// Accesses the 'Title' field
string title = article.Fields.Title;

// Accesses the 'Text' field
string text = article.Fields.Text;

```

> **Note:** **Resolving HTML tags and relative URLs**
>
> Fields which are populated by the **Rich text editor** form control may contain HTML tags and relative links. To ensure that the content is displayed correctly, use one of the following methods in your views:
>
> - The standard **Html.Raw** method, which disables HTML encoding for the values.
> - The **Html.Kentico().ResolveUrls** extension method, which disables HTML encoding for the values and additionally resolves relative URLs to their absolute format. By default, relative URLs are automatically resolved by a filter that processes the output of all pages. You can use the _ResolveUrls_ method to minimize the output filtering requirements or if you wish to disable the filter completely (via the _CMSMVCResolveRelativeUrls_ web.config key).
>
> ```csharp
>
> @Html.Raw(Model.<Rich text field content>)
> @Html.Kentico().ResolveUrls(Model.<Rich text field content>)
>
> ```

> **Info:** **Automatic URL resolving**
>
> The system provides page output filtering functionality that automatically resolves all virtual relative URLs to their absolute form. The URLs are processed on the side of the MVC application, based on the environment where the site is actually running.
>
> 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.

## Getting page URLs

Pages in the content tree of Xperience websites can have their live site URLs generated by the system, either through [content tree-based routing](https://docs.kentico.com/13/developing-websites/implementing-routing/content-tree-based-routing.md) or according to [URL patterns](https://docs.kentico.com/13/developing-websites/implementing-routing/custom-routing-using-url-patterns.md) set for page types. This allows content editors to create new pages or adjust the URLs of existing ones in the administration interface, without the need to update and redeploy the code of the MVC application.

You may need to get the URLs of retrieved pages in various scenarios, such as rendering [navigation menus](https://docs.kentico.com/13/developing-websites/building-website-navigation.md) or other page links, performing redirects, etc.

To get the URL of a page in general code:

1. Obtain an instance of the **IPageUrlRetriever** service (for example through [dependency injection](https://docs.kentico.com/13/developing-websites/initializing-xperience-services-with-dependency-injection.md) in your controller constructor).
2. Call the service's **Retrieve** method, and use one of the following parameter types to specify the page:
   - **TreeNode** object representing the page (or a specific page type class inheriting from _TreeNode_).
   - _string_ containing a _node alias path_ value, representing the page's location in the Xperience content tree

The _IPageUrlRetriever.Retrieve_ method returns a **PageUrl** object, with properties containing the given page's URL:

- **RelativePath** – the virtual path of the specified page, which you can resolve to an application absolute path at runtime (for example using the [UrlHelper.Content](https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.urlhelper.content) method).
- **AbsoluteURL** – the page's absolute URL, including the scheme and domain name.

The URL is automatically adjusted for the current culture, i.e. any language prefixes in the URL path or the domain in the absolute URL (see [Configuring URLs for multilingual websites](https://docs.kentico.com/13/multilingual-websites/setting-up-multilingual-websites/configuring-urls-for-multilingual-websites.md) to learn more).

```csharp title="Example"

using System.Web.Mvc;

using CMS.DocumentEngine;

using Kentico.Content.Web.Mvc;

public class PageController : Controller
{
    private readonly IPageUrlRetriever pageUrlRetriever;

    // Controller constructor that receives an IPageUrlRetriever instance using dependency injection
    public PageController(IPageUrlRetriever pageUrlRetriever)
    {
        this.pageUrlRetriever = pageUrlRetriever;
    }

    ...

    // Gets the relative URL of a specified page (TreeNode object or inheriting page type class)
    string relativePageUrl = pageUrlRetriever.Retrieve(page).RelativePath;

    ...
}

```

### Page URL extension methods

In addition to the _IPageUrlRetriever_ API, the system provides [UrlHelper](https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.urlhelper) extension methods for getting page URLs.

- **Kentico().PageUrl(string nodeAliasPath)** – returns the URL of a page identified by a _node alias path_ value (representing the page's location in the Xperience content tree). You can provide the following optional parameters:

  - string cultureCode – the culture code of the desired language variant.
  - string siteName – the code name of the site from which to retrieve the page.
-

```xml title="Example"

@using System.Web.Mvc

@using Kentico.Content.Web.Mvc
@using Kentico.Web.Mvc

...

@* Renders a link to the page under the '/Home' alias path in the site's content tree *@
@Html.HtmlLink(Url.Kentico().PageUrl("/Home"), "Home page"))

```

- **Kentico().CurrentPageUrl()** – returns the URL of the currently displayed page. Requires the context of the current page to be available and initialized (automatic for pages on sites using [content-tree based routing](https://docs.kentico.com/13/developing-websites/implementing-routing/content-tree-based-routing.md), requires manual initialization of the [page data context](https://docs.kentico.com/13/developing-websites/implementing-routing/custom-routing-using-url-patterns.md#initializing-the-page-data-context) for pages handled by custom routes based on page type URL patterns).

The methods return the page's **application absolute URL path**, as a **PageUrlString** object. The object automatically converts to a string within views. You can call the _PageUrlString_ object's **ToAbsolute()** method to get the page's absolute URL, including the schema and domain name.

> **Tip:** **Tip**
>
> For methods that accept node alias path parameters, you can use a helper class to store the paths to frequently targeted pages as constants. For example:
>
> ```csharp
>
> public static class ContentItemIdentifiers
> {
>     public const string HOME = "/Home";
>     public const string ARTICLES = "/Articles";
> }
>
> ```

> **Info:** **Canonical URLs**
>
> The API also provides the **Kentico().PageCanonicalUrl()** extension method, which returns page URLs suitable for [Canonical link elements](https://en.wikipedia.org/wiki/Canonical_link_element). Rendering canonical links is recommended to improve SEO on websites where pages are available under multiple URLs, typically when using [alternative URLs](https://docs.kentico.com/13/developing-websites/implementing-routing/enabling-alternative-urls-for-pages.md) or [linked pages](https://docs.kentico.com/13/managing-website-content/working-with-pages/copying-and-moving-pages-creating-linked-pages.md).
>
> For detailed information, see [Providing canonical URLs for pages](https://docs.kentico.com/13/developing-websites/implementing-routing/enabling-alternative-urls-for-pages.md#providing-canonical-urls-for-pages).

## Working with page metadata

The standard way of configuring SEO-related parameters for a website's pages is to add [ elements](https://www.w3schools.com/tags/tag_meta.asp) into the __ section of the page HTML code. To utilize the [metadata entered for pages in the administration interface](https://docs.kentico.com/13/managing-website-content/working-with-pages/editing-metadata-of-pages.md), such as the page title and description, you can use the following [HtmlHelper](https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.htmlhelper) extension methods provided by the Xperience API:

- **Kentico().PageDescription**
- **Kentico().PageKeywords**
- **Kentico().PageTitle**

The methods render the corresponding HTML  elements for the **currently displayed page**. Before rendering the elements, all methods transform the metadata based on the [settings for metadata format and prefixes](https://docs.kentico.com/13/configuring-xperience/managing-sites/configuring-settings-for-sites/settings-content.md) (i.e. add a prefix or resolve macros in the content of the metadata).

To work, the methods must have the context of the current page available:

- For pages on sites that use [content-tree based routing](https://docs.kentico.com/13/developing-websites/implementing-routing/content-tree-based-routing.md) the methods work automatically.
- For pages [handled by custom routes](https://docs.kentico.com/13/developing-websites/implementing-routing/custom-routing-using-url-patterns.md) based on page type URL patterns the methods require manual initialization of the [page data context](https://docs.kentico.com/13/developing-websites/implementing-routing/custom-routing-using-url-patterns.md#initializing-the-page-data-context).

For the **PageTitle** method, you can optionally set the _alternateTitle_ parameter, which is then used for pages where the title and context of the current page is not available (e.g. completely custom pages that are not represented in the Xperience content tree). For example, you can get the _alternateTitle_ value from a _ViewBag_ property used inside the view layout.

The following example of view code uses the extension methods to render metadata tags for the current page (such code can be added to the site's main layout):

```xml

@using Kentico.Content.Web.Mvc
@using Kentico.Web.Mvc

...

<html>
<head id="head">
    ...
    @Html.Kentico().PageDescription()
    @Html.Kentico().PageKeywords()
    @Html.Kentico().PageTitle(ViewBag.Title as string)
    ...
</head>

```

> **Info:** **General API for retrieving page metadata**
>
> You can also access the metadata for specific pages through the properties of **IPageMetadata** instances. To get the _IPageMetadata_ instance for a page, use one of the following approaches (depending on your scenario and context):
>
> - Call the **Retrieve** method of the **IPageMetadataRetriever** service, with the page's _TreeNode_ object as the parameter.
> - Access the **Metadata** property of an **IPageDataContext** instance. The data context for the current page can be retrieved using the _IPageDataContextRetriever_ service (requires manual initialization of the [page data context](https://docs.kentico.com/13/developing-websites/implementing-routing/custom-routing-using-url-patterns.md#initializing-the-page-data-context) for pages handled by custom routes based on page type URL patterns).
> - Access the **Metadata** property of an **IPageViewModel** instance – available as the model in the views of pages handled by [basic content tree-based routing](https://docs.kentico.com/13/developing-websites/implementing-routing/content-tree-based-routing/setting-up-content-tree-based-routing.md).
