Showing posts with label PageLayout. Show all posts
Showing posts with label PageLayout. Show all posts

Tuesday, May 3, 2016

Tip: Steps to resolve from parallel safe-conflict on provisioning a PageLayout

We’ve constructed our SharePoint 2013 based intranet cloud-ready, utilizing the AddIn-model. This for runtime functionalities, examples are Company News, My Favorites, My Tasks, Yammer AddIn's. And conform the Office 365 best-practice also for provisioning of SharePoint branding entities: masterpage(s), PageLayouts, content types. Yesterday I needed to reactivate a (new) version of a provisioning AddIn to update a PageLayout. However, exactly the update of that PageLayout failed at the App activation, with the message: Save Conflict – Your changes conflict with those made concurrently by another user.
The origin of this can be diverse. In my case it was for sure not due an actual parallel safe conflict. I suspect that as side-effect of a previous action, the safe-administration in SharePoint is no longer in sync with the state as original provisioned by the AddIn. But as SharePoint content database is a black box, almost impossible to analyze what caused the safe conflict. However, that is even not that interesting here. What counts is how to resolve such that the updated version of the PageLayout is successful provisioned by the AddIn. Well, this comprises of multiple steps that I outline below.

Approach to resolve from the safe-conflict

In concept this is simple: avoid the occurrence of safe-conflict by removal of the existing PageLayout, and next the new version can be provisioned without errors. However, this is easier said then done as the PageLayout typically is already in-use. And SharePoint is aware of that, and blocks the deletion as long as in use. So a prerequisite is to also and first remove the ‘used-by’ occurrences.

Steps to resolve from the safe-conflicts

  1. Open ‘Content and Structure’ from ‘Site Settings’, and navigate to the ‘Master Page Gallery’
  2. Select the PageLayout that gives the SafeConflict, and click in the top menubar on ‘Show Related Resources’
  3. This will expose whether and by which publishing pages the PageLayout is ‘Used-By’
  4. For each of these pages, edit them and temporarily associate with another PageLayout
  5. After all relevant pages are deassociated from this PageLayout [you can verify this by refreshing ‘Show Related Resources’], you can delete the PageLayout from the masterpage catalog
  6. And now activation of the provisioning AddIn will no longer give a safe-conflict
  7. Afterwards, reassociate all the relevant pages with the (new version of the) PageLayout.

Tuesday, January 26, 2010

AllUsersWebPart and SPWebApplication.ApplyWebConfigModifications don't match

  • In a Feature, I apply the AllUsersWebPart construct to automatically add default webparts to all publishing pages based on the PageLayout File.
  • In a Feature, I utilize the SPWebConfigModification class to add web.config modifications
When done in separate Features, both constructs operate successfully. However, when included within the same Feature activation, the invocation of ApplyWebConfigModifications method results in a SecurityException:
Access Denied
at Microsoft.SharePoint.Administration.SPPersistedObject.Update()
at Microsoft.SharePoint.Administration.SPWebApplication.ApplyWebConfigModifications()
at Microsoft.SharePoint.Administration.SPWebService.ApplyWebConfigModifications()
It looks as if internally SharePoint somehow puts a lock on the Administration persistent object. I tried to verify my suspicion via Reflector, but not surprisingly this internal code is obfuscated. The runtime error only manifests itself when the Feature is (re)activated via the GUI. The Feature activation via stsadm reports no problem, and successfully performs the deployment work.
Still, I want to hold on to the idea of one single self-contained Feature to deploy all the required parts. And I want to be able to turn the Feature on and off interactively via the SharePoint GUI (so that I can also operate the feature remote, without access to the deployment server). A resolution is to apply another approach to provision the default webparts on the pagelayouts. Besides the usage of AllUsersWebPart, it is also possible to directly include the webpart specifications in the PageLayout file itself:
With this construction, the invocation of SPWebApplication.ApplyWebConfigModifications method is done successfully. And as a bonus, also another problem is prevented; that of magically duplicating the default webparts provisioned via AllUsersWebPart upon Feature re-activation.
A final word of caution. With this approach I at first encountered another problem. When editing on a created publishing page the properties of the default WebPart provisioned via the PageLayout file, SharePoint displayed an error warning in the edit toolpane, "a web part you attempted to change is either invalid or has been removed by another user". Although the net effect of the WebPart settings is simple done, this is not very trustwordy towards the Web Content Manager. Hard to explain that they can just ignore this warning. Before deciding to then have to abandon the approach, I re-examed the default WebPart specification in the PageLayout file to see if anything there could be causing SharePoint to suspect a concurrent update. And yes there was, 'thanx' to the automatic editing behaviour of Visual Studio. When you add a control within an .aspx file, Visual Studio automatically add a default 'ID' property to the control. For the default WebPart however this is not needed, the property is actually set when creating a publishing page off this PageLayout. But the mere presence of it in the default part results in SharePoint detecting a concurrent update. So remember to don't include the 'ID' property within WebPart specifications included within PageLayout files.

Friday, July 10, 2009

Tip – Provision custom publishing masterpage, pagelayouts and webparts always via a Feature with Site-scope, not Web-scope

The masterpage and webpart galleries for publishing sites live at the top level site (rootWeb) in a sitecollection, not at individual sites. This can be misleading, since every subsite get its own ‘_catalog/masterpage’ and ‘_catalog/wp’ folders. The Publishing functionality however only goes to the gallery at the top level site; for the masterpages (Site and System), pagelayouts as well as for building up the list of selectable webparts.
A best practice is to provision your custom masterpage, pagelayouts and .webpart definition files via a Feature. Thereby you must specify the level at which the feature is applied. For MasterPage, PageLayouts and .webpart files the appropriate level appears thus to be ‘Scope=Site’. However, it is also allowed to set ‘Scope=Web’, as long as you’re activating the web-scoped feature in the rootweb. But when you activate such a feature in a subsite, the results are less. It appears as if the SharePoint feature mechanism simple ignores the request to provision masterpage and pagelayouts into ‘_catalog/masterpage’, and .webpart files into ‘_catalog/wp’. They are simple not added anywhere. Not at the indicated subsite level, which would also be useless given the publishing behaviour. But also not at the rootweb level. Annoying is that no signal of this is given, no error reporting but simple ignored to provision the SharePoint files at the incorrect subsite level. Ok that stsadm doesn’t signal it, but I would have expected an error indication when activating the feature via the GUI. And at the least I expected to find some information about it in the extensive SharePoint logs in the 12hive. In reality none, instead the feature framework just silently ignores the feature specifications which are logically incorrect when activated at subsite level.
So, what then to do when you what to provision content to a publishing site at subsite level ? I recommend the following 2-steps approach:
  1. Provision your masterpage, pagelayouts, and .webpart files to the catalog gallery at rootlevel; apply a Feature with scope = Site.
  2. Provision your site structure (libraries, lists) and content via a Web-scoped Feature; and activate this against your specific site, the root or a child subsite. E.g. http:<root-entry>/Intranet