I want to add a page to my site definition which is hidden ie. doesn't appear in the navigation, by default.
The page is provisioned in the onet.xml file as follows;
<File Url="SomePage.aspx" Type="GhostableInLibrary" Path="default.aspx"> <Property Name="Hidden" Value="TRUE" /> <Property Name="Title" Value="Some Page" /> <Property Name="ContentType" Value="$Resources:cmscore,contenttype_welcomepage_name;" /> <Property Name="PublishingPageLayout" Value="~SiteCollection/_catalogs/pagelayouts/mypagelayout.aspx, My Page Layout" /> </File>
As you can see I have tried setting a property of Hidden but this seems to have no effect. Is there any way to set the page to be created in the site but not shown int he navigation. I have relatively limited experience with site definitions so am probably approaching it wrong?
UPDATE: I decided to approach this a different way and "simply" hide the navigation item in a feature event receiver run when the site is provisioned. However this turns out to be far from simple.
At first I tried to access the Navigation of the SPWeb
But this is a null reference. So I created a PublishingWeb from the web and looked in there
PublishingWeb pw = PublishingWeb.GetPublishingWeb((SPWeb)properties.Feature.Parent); pw.Navigation.GlobalNavigationNodes;
But this is also a null reference. Some searching on Google turned up this article - http://blog.mastykarz.nl/programmatically-configuring-menu-items-sharepoint-2010/ - which explains that the navigation is not populated until it is first updated through the UI and provides a fairly low level powershell solution to populate this navigation by creating a fake SPContext, grabbing a PortalSiteMapProvider and getting the navigation from there. I rewrote this into my feature receiver and have code looking like this:
SPWeb web = (SPWeb) properties.Feature.Parent; PublishingWeb pw = PublishingWeb.GetPublishingWeb((SPWeb)properties.Feature.Parent); HttpRequest request = new HttpRequest("", web.Url, ""); StringWriter sw = new StringWriter(); HttpResponse response = new HttpResponse(sw); HttpContext.Current = new HttpContext(request, response); SPControl.SetContextWeb(HttpContext.Current, web); ProviderSettings ps = new ProviderSettings("CombinedNavSiteMapProvider", "Microsoft.SharePoint.Publishing.Navigation.PortalSiteMapProvider, Microsoft.SharePoint.Publishing, Version=184.108.40.206, Culture=neutral, PublicKeyToken=71e9bce111e9429c"); ps.Parameters["NavigationType"] = "Combined"; ps.Parameters["EncodeOutput"] = "true"; PortalSiteMapProvider psmp = (PortalSiteMapProvider) ProvidersHelper.InstantiateProvider(ps, typeof(Microsoft.SharePoint.Publishing.Navigation.PortalSiteMapProvider)); PortalSiteMapNode current = (PortalSiteMapNode) psmp.CurrentNode; SiteMapNodeCollection nodes = current.GetNavigationChildren(NodeTypes.Default, NodeTypes.Default, OrderingMethod.Manual, AutomaticSortingMethod.Title, true, -1);
Alas the nodes collection is empty. I have tried using the GlobalNavSiteMapProvider and the CombinedNavSiteMapProvider with the same results. However when the receiver finishes the site does indeed have navigation items.
This seems like such a basic requirement that nearly every SharePoint development would need; some deployable control of navigation.
Is this really the way we are supposed to do this? Is there not a simple solution? And if it is the recommended way does anybody know why the nodes collections are always empty for me?