Get ContentItemDataCommonDataID from Pages

2024/10/04 10:30 AM

I'm trying to get out the Page builder widget data via code using

private readonly IInfoProvider<ContentItemCommonDataInfo> _commonDataInfoProvider

I need to get this on a page by page basis, so I need a way of getting out the ContentItemDataCommonDataID for the current page.

I'm currently using

private readonly IWebPageDataContextRetriever _pageDataContextRetriever;

var currentPage = _pageDataContextRetriever.Retrieve().WebPage;

but this doesn't give access to the ContentItemDataCommonDataID field.

Looking in the database this value appears to be stored against the table for the specific content type as well but I need to be able to get this for any content type.

Is there another API I need to be using to get this value?


Environment

  • Xperience by Kentico version: 29.3.1
  • .NET version: [8]
  • Deployment environment: Azure

Answers

2024/10/04 2:26 PM

@alexbrom

What do you need the ContentItemDataCommonDataID for? That's an internal API and not meant to be used for content delivery.

2024/10/07 7:31 AM

Hi Sean

Sorry I probably should have been more specific. This is for an in page nav widget. The way we're building this widget means we need access to the PageBuilderWidget json from the ContentItemCommonDataPageBuilderWidgets field.

I need to get this field for the current page we're viewing the widget on.

Hope this clarifies things :)

2024/10/07 12:08 PM
Answer

If you are in the context of a widget or section, you can use the ComponentViewModel<T>.Page property and use its WebPageItemID to retrieve the web page using a ContentItemQueryBuilder().

(Using ComponentViewModel<T>.Page means you don't need to inject IWebPageDataContextRetriever).

Then execute the query and limit yourself to the fields you need.

var b = new ContentItemQueryBuilder()
    .ForContentTypes(q => q.ForWebsite([page.WebPageItemID]))
	.Parameters(q => q.Columns("...")); // limit columns as an optimization

var contentItem = (await Executor.GetMappedResult<IContentItemFieldsSource>(b).FirstOrDefault();

Finally, use the content item's fields to get the correct common data record.

var commonData = (await commonDataInfoProvider
	.Get()
	.WhereEquals(
	    nameof(ContentItemCommonDataInfo.ContentItemCommonDataContentItemID),
		contentItem.SystemFields.ContentItemID)
	.WhereEquals(
	    nameof(ContentItemCommonDataInfo.ContentItemCommonDataContentLanguageID),
		contentItem.SystemFields.ContentItemCommonDataContentLanguageID)
	.GetEnumerableTypedResultAsync())
	.FirstOrDefault();

Is your sidebar navigation dynamically built from the Widgets rendered on the page?


How will that work with personalization? Personalization will pick the variant of a Widget based on the contact details and the priority of variants of the widget but without replicating that logic, your sidebar navigation could display links that don't match the displayed content.

This almost seems to me to be an ok place to render something client side based on what is actually in the DOM (using vanilla JS, AlpineJS, or jQuery). If the navigation is outside of the main content flow you won't need to worry about cumulative layout shift from client-side rendering.

To answer this question, you have to login first.