How do I get an EPiServer page of a specific page type builder type with all its strongly typed properties correctly populated? Could I do this in a single method call?
I have tried using:
ContentPageType pageAsContentPageType =
DataFactory.Instance.GetPage<ContentPageType>(page.PageLink);
However, this does not work. It populates the PageData properties but nothing else, despite that I am specifying its target as a ContentPageType.
I have included the offending code below, which I have extensively commented:
public static IList<ContentPageType> GetMapEnabledPages()
{
// Get the content pages
IList<PageData> pages = PageFactory.GetPages(
PageReference.StartPage.ID,
BaseSettings.Constants.EPiServer.PageTypeNames.ContentPage
);
// Some content pages will be map enabled pages. So, we need to extract the ones that are put them in this variable.
IList<ContentPageType> mapEnabledPages = new List<ContentPageType>();
// walk pages to extract only map enabled pages
foreach (PageData page in pages)
{
// get the page as a ContentPageType.
// unfortunately, this method only populates the PageData information and none of the additional strongly types properties that a ContentPageType has.
// we would expect this happen because EPiServer uses IoC elsewhere but does not do it here.
ContentPageType pageAsContentPageType =
DataFactory.Instance.GetPage<ContentPageType>(page.PageLink);
// So, we fudge it - we know that the PageData weakly type properties has IsMapEnabled correctly populated.
// So, we put that value in the strongly typed ContentPageType property.
if (pageAsContentPageType != null && pageAsContentPageType["IsMapEnabled"] != null)
{
// put that the weakly typed property for "IsMapEnabled" into the strongly typed ContentPageType IsMapEnabled property
pageAsContentPageType.IsMapEnabled =
TypeHelper.ConvertToBoolean(pageAsContentPageType["IsMapEnabled"].ToString());
// check if it is map enabled
if (pageAsContentPageType.IsMapEnabled)
{
// it is a map enabled page. So, add it to the mapEnabledPages list.
mapEnabledPages.Add(pageAsContentPageType);
}
}
}
return mapEnabledPages;
}
EDIT:
Previously, I tried the following but it does not work either:
ContentPageType pageAsContentPageType =
DataFactory.Instance.GetPage(page.PageLink) as ContentPageType
SOLUTION FOR CMS5R2SP2:
It turned out that there was a missing virtual keyword on the IsMapEnabled page type property. The IoC container was, therefore, not overriding this property from its default value. Here is the final implementation:
IList<PageData> pages = PageFactory.GetPages(
PageReference.StartPage.ID,
BaseSettings.Constants.EPiServer.PageTypeNames.ContentPage
);
// Some content pages will be map enabled pages.
// So, we need to extract the ones that are put them in this variable.
IEnumerable<ContentPageType> mapEnabledPages =
from page in pages.OfType<ContentPageType>()
where page.IsMapEnabled
select page;
// return map enabled pages.
return mapEnabledPages.ToList();
SOLUTION FOR CMS6:
OfType<ContentPageType>()
does not work. So, regetting each page works as Joel said.
The GetPage method with the type parameter was introduced in the last version of EPiServer CMS 5 and removed in version 6. So, assuming that you are using version 5 and not a custom extension method the answer is simply to not use the method with the type parameter and instead just cast the result of the call to GetPage (assuming you know the type). In other words, the below code should work fine:
ContentPageType pageAsContentPageType = (ContentPageType) DataFactory.Instance.GetPage(page.PageLink);
Page Type Builder intercepts calls to GetPage and replaces the returned PageData object with a proxy of the correct type. This proxy intercepts calls to properties and returns the values. In other words, instances of PTB classes are never actually populated but it's vital that PTB can intercept the calls.
The GetPage method with the type parameter was somewhat experimental and while it did allow pages to be returned as a specific type it didn't allow external parties (such as PTB) to replace the object being returned. It was later removed per request to allow us to create extension methods with the same signature.
Some history here.