Recently, I was working on a project that I needed to implement status code pages that had page builder enabled on them. Since these were status code pages, I needed custom routing and could not use Content Tree routing provided by Xperience by Kentico. Once I enabled page builder for this content type and added editable areas to the view, I quickly realized I was missing something.
When I ran the project and hit my newly created status code pages, I received the following error:
Missing web page context data. If required use IWebPageDataContextInitializer.Initialize method to initialize the context manually. For POST actions use HtmlHelper extension method Html.Kentico().PageData() to persist the page context.
When using custom routing, Xperience does not have context into which content tree page is connected to the custom route URL. Therefore, it cannot provide the page builder widgets associated with the page you are trying to reach.
To provide a little insight into the data behind the scenes: each web page item has a widget field where the page builder configuration is stored in. This can be found in the CMS_ContentItemCommonData database table, in the ContentItemCommonDataPageBuilderWidgets and ContentItemCommonDataPageTemplateConfiguration columns.
If Xperience doesn’t know which web page is associated with the request, then it cannot render the corresponding widgets.
With the information from above in mind, we can infer that we need two things. We need to retrieve the web page item associated with the request, and the page context, or in other words, the data associated with that page (page builder widgets).
We will use the ContentItemQueryBuilder and GetWebPageResult to retrieve the web page item. In order to grab the correct web page item, we need to limit the results by the WebPageItemId. We can do this by getting the page context using the IWebPageDataContextRetriever. The code below shows how we can build the query to retrieve the page.
var pageContext = webPageDataContextRetriever.Retrieve().WebPage;
var query = new ContentItemQueryBuilder().ForContentType(
StatusCodePage.CONTENT_TYPE_NAME,
config =>
config
.ForWebsite(XperienceConstants.WebsiteChannelName)
.Where(query =>
query.WhereEquals(nameof(StatusCodePage.SystemFields.WebPageItemID), pageContext.WebPageItemID)
)
.TopN(topN: 1)
);
We are limiting the result to only the web page item whose WebPageItemID matches the page context WebPageItemID.
The final step in retrieving the web page item is the execution of the query using GetWebPageResult. If you want to read more about Xperience’s Content item API and retrieving pages, you can reference their documentation here.
var page = (
await executor.GetWebPageResult(
builder: query,
options: queryOptions,
resultSelector: queryMapper.Map
)
).FirstOrDefault();
Finally, we need to pass the context of the web page item to Xperience. This can be accomplished by using the IWebPageDataContextInitializer interface, which provides an Initialize method that takes a RoutedWebPage item as an argument. We can construct the RoutedWebPage object from the page data that we retrieved.
var languageQuery = ContentLanguageInfo.Provider.Get()
.WhereEquals(columnName: "ContentLanguageID", page.SystemFields.ContentItemCommonDataContentLanguageID);
var language = languageQuery.ToList().FirstOrDefault();
var pageDataContext = new RoutedWebPage()
{
WebPageItemID = page.SystemFields.WebPageItemID,
WebPageItemGUID = page.SystemFields.WebPageItemGUID,
LanguageID = page.SystemFields.ContentItemCommonDataContentLanguageID,
LanguageName = language.ContentLanguageName,
ContentTypeID = page.SystemFields.ContentItemContentTypeID,
ContentTypeName = StatusCodePage.CONTENT_TYPE_NAME,
WebsiteChannelName = XperienceConstants.WebsiteChannelName
};
webPageDataContextInitializer.Initialize(pageDataContext);
To wrap it up, integrating page builder with custom routing in Xperience may require some extra steps, but the process is straightforward once you understand the underlying mechanics. By manually retrieving the page data and initializing the context, you can get your custom-routed pages working seamlessly with the page builder. This approach not only resolves the context issue but also keeps your custom-routed pages flexible and fully integrated with Xperience’s powerful content management features.
We love to make cool things with cool people. Have a project you’d like to collaborate on? Let’s chat!
Stay up to date on what BizStream is doing and keep in the loop on the latest in marketing & technology.