EPiServer Composer page is missing a Shadowpage, or a reason why you can’t create functions

by Fredrik Karlsson 22. March 2010 21:10

The problem

You drag a function onto your EPiServer composer page:
Drag

You drop the function in a content area and watch the spinning effect:
drop

The function just disappear!
Missing

Some background

As you probably know, each Composer page is actually a lot of EPiServer pages. Each function is an EPiServer page and each Function type is a EPiServer pagetype. So when you create a new function, you actually creates a new EPiServer page. That page is created in the EPiServer tree under a special page called a Shadow page. The shadow page is a container for each composer page and exists in order to make sure that all composer functions are not created on the same level, since that would have a serious performance impact.

Some debugging

The best way to start is to enable logging in Composer and you will probably see something like this:

2010-03-22 20:35:42,022 [23] ERROR Dropit.Extension.UI.Edit.CreateContentFunction [(null)] - Dropit.Extension.UI.Edit.CreateContentFunction: Page 737 was not found
EPiServer.Core.PageNotFoundException: Page 737 was not found
   at EPiServer.DataAccess.PageLoadDB.LoadPageInternal(PageReference pageLink, Int32 languageBranchId, IDataReader reader)
   at EPiServer.DataAccess.PageLoadDB.<>c__DisplayClass1.b__0()
   at EPiServer.DataAccess.DataAccessBase.<>c__DisplayClass1`1.b__0()
   at EPiServer.DataAccess.DatabaseFactory.Execute[TResult](Action`1 method)
   at EPiServer.DataAccess.DataAccessBase.Execute[TResult](Action`1 action)
   at EPiServer.Core.PageProviderBase.<>c__DisplayClass4.b__3()
   at EPiServer.Core.OptimisticCache`1.Read(String cacheKey, ReadAndCacheObject`1 readAndCacheObject)
   at EPiServer.Core.PageProviderBase.GetPageInternal(PageReference pageLink, ILanguageSelector selector)
   at EPiServer.Core.PageProviderBase.GetPage(PageReference pageLink, ILanguageSelector selector)
   at EPiServer.DataFactory.GetPage(PageReference pageLink, ILanguageSelector selector)
   at EPiServer.Core.PageLanguageSettingsTree.GetClosestSetting(PageReference pageLink)
   at EPiServer.Core.PageLanguageSettingsTree.Get(PageReference pageLink)
   at EPiServer.Core.PageLanguageSettingsTree.Get(PageReference pageLink, String languageBranch)
   at EPiServer.Core.LanguageSelector.LoadLanguage(LanguageSelectorContext context)
   at EPiServer.Core.CreatePageData.DefaultPageDataLanguage(Int32 pageTypeID, PageReference parentPageLink, ILanguageSelector selector, IList`1 existingLanguages)
   at EPiServer.Core.PageProviderBase.GetDefaultPageData(PageReference parentPageLink, Int32 pageTypeID, ILanguageSelector selector)
   at EPiServer.DataFactory.GetDefaultPageData(PageReference parentPageLink, Int32 pageTypeID, ILanguageSelector selector)
   at Dropit.Extension.Controllers.ContentFunctionDataManager.CreateContentFunctionData(PageReference extensionPageLink, Int32 contentFunctionTypeId, AccessLevel accessLevel)
   at Dropit.Extension.Controllers.ContentFunctionDataManager.CreateContentFunctionData(PageReference extensionPageLink, Int32 contentFunctionTypeId)
   at Dropit.Extension.Core.ContentFunctionData.Create(PageReference extensionPageLink, Int32 functionTypeId)
   at Dropit.Extension.UI.Edit.CreateContentFunction.Page_Load(Object sender, EventArgs e)

Ok, so page 737 is missing. A liitle bit up in the log file, we see this:

2010-03-22 20:35:41,960 [23] INFO  Dropit.Extension.Core.Serializer              [(null)] - Dropit.Extension.Core.Serializer: <?xml version="1.0" encoding="utf-8"?>
<specializedextensionpagedata>
  <pagestructure shadowguid="06ad9f3b-ea46-414a-b45d-198b03817a5b"
	guid="59b27f7d-c2dc-4a06-8251-2bb83e1967e9" 
	remotesite="" 
	wid="3326" 
	pid="2171" 
	sid="737">
    <ca id="SideContent" desc="SideContent content" />
    <ca id="TopContent" desc="The top content area" />
    <ca id="MainTopContent" desc="The main content top area" />
    <ca id="MainBottomContent" desc="The main content bottom area" />
    <ca id="SecondaryContent" desc="Secondary content" />
    <ca id="BottomContent" desc="The bottom content area" />
  </pagestructure>
  <content><!-- Empty -->
</specializedextensionpagedata>

As you can see, the sid attribute has the value 737. Sid stands for Shadow ID, or the page that will work as a shadow page for this composer page. And it is missing!

The fix

Just run this code to fix this:

var extensionpagetypes = Dropit.Extension.Global.ListExtensionPageTypes();
var pages = EPiServer.DataFactory.Instance.GetDescendents(PageReference.RootPage);
var composerpages = from p in pages
					from pt in extensionpagetypes
					where EPiServer.DataFactory.Instance.GetPage(p).PageTypeID == pt.ID // 10610
					select EPiServer.DataFactory.Instance.GetPage(p);

PageReference newShadowPage;
PageReference existingShadowPage;
foreach (var composerPage in composerpages)
{
	var composerPageData = Dropit.Extension.Core.ExtensionPageData.Load(composerPage.PageLink);

	// This is always true, bug in composer?
	//if (composerPageData.ShadowPageLink == PageReference.EmptyReference)
	if (composerPageData != null)
	{
		try
		{
			existingShadowPage = new PageReference(composerPageData.ShadowPageID);
			GetPage(existingShadowPage);
		}
		catch (PageNotFoundException ex)
		{
			// The shadowpage is missing
			// Lets create it
			newShadowPage = Dropit.Extension.Controllers.ShadowPageManager.Instance.NewShadowPage(composerPageData.PageLink);
			Dropit.Extension.Controllers.PageDataManager.UpdateShadowPageID(composerPage, newShadowPage);
		}
		catch (Exception)
		{
			// Something else is wrong
			// Lets skip it...
		}
	}
}

Why is this necessary?

Former versions of Composer had a bug when you copied a composer page. It didn’t generate a new shadowpage for the new page. And when you deleted the old page, the shadow page was deleted as well, simply leaving the newly copied page without a shadow page.

Tags: , , ,

Development

blog comments powered by Disqus

Creative Commons License
This work is licensed under a Creative Commons Attribution-Share Alike 2.5 Sweden License.


Welcome to the Dropit blog!

Here we, the people that work at Dropit, will write about stuff that interests us. For example web development, especially with .NET and EPiServer - but we'll also talk about other techniques that interest us, marketing on the web, social phenomenons, pop culture, games and software development in general.