Using custom web templates and PowerShell
So custom site definitions have have pretty much been my stock in trade for SharePoint site deployments for years now. I’m comfortable with them, and I’m aware of the best way to use them – were basically talking about an approach that takes an empty or blank definition, and provisions all the functionality and site artefacts in features that get deployed whenever the site is created.
However I’m always looking at new ways of doing things, and decided to use the Web Template functionality in a current site deployment project. I find the process to be not much different from my existing approach of using a blank site definition and adding custom features to it. In my scenario, I needed to create a nested site hierarchy based on the web template, and so PowerShell was employed to build out that site structure in a scripted, repeatable manner. However I did hit a couple of snags along the way, some old, and some new, so the purpose of this post is to collect these gotchas together in one place for future reference so I don’t have to go through them again!
(As an aside – the use of PowerShell for this deployment task is a real godsend – in the old days I was using a custom feature receiver to iterate a nested XML structure and create upon feature activation. This was clunky and hard to update – requiring a WSP upgrade no less – and led to other unforeseen consequences that had to be overcome, such as the feature activation timeout issue).
1. Unable to modify navigation in a site created from the template. Make sure the following is present in the onet.xml file of your web template, otherwise you will be unable to manage navigation via the Area navigation settings of you custom publishing site:
<NavBar Name="SharePoint Top Navbar" ID="1002"/>
2. “This page is not using a valid page layout” issue. This one has been around for ages, but I still managed to get burned by it more than once! When provisioning files as part of the custom web template (such as default.aspx), make sure the Type=”GhostableInLibrary” attribute is present:
<File Path="TeamSiteDefault\default.aspx" Url="Home.aspx" Type="GhostableInLibrary">
3. When creating new sites based on a web template via PowerShell, if the template is deployed as a site scoped feature, the command New-SPWeb will fail with the error: “Warning – Template is not found and is not applied”. In normal circumstances, the template is specified as an argument of the New-SPWeb cmdlet; for web templates, the template is specified in a two part notation as in the following example:
New-SPWeb $url –template “{GUID}#WebTemplateName”
This will fail however for site scoped web templates, and the site must first be created and then the template applied once it has been created. I therefore use a utility function to get the web template based on it’s title, and then apply it to the newly created web, as in this example:
# ==================================================================================== # Func: GetWebTemplate # Desc: Returns WebTemplate based on match in Title field # ==================================================================================== Function GetWebTemplate([string]$url, [string]$in) { $web = Get-SPWeb -Identity $url Write-Host -ForegroundColor White " - Getting web template for: " $in $template = $web.GetAvailableWebTemplates(1033) | ? { $_.Title -eq $in } Write-Host -ForegroundColor White " - Template Id: " $template.Name $web.Dispose() return $template } $newWeb = New-SPWeb -Url $WebURL -Name $Name -Language $LCID $WebSiteDef = GetWebTemplate $WebUrl $template $newWeb.ApplyWebTemplate($WebSiteDef.Name)
4. If creating default associated groups with each site, be sure to set the associated visitor id property correctly. This refers to having the default Owners, Members and Visitors groups created with the site. Calling the method CreateDefaultAssociatedGroups will not create a Visitors group correctly (it will not be available in the UI), unless you first set the AssociatedVisitorGroup property to null, and then set the vti_associatevisitorgroup property after the call to CreateDefaultAssociatedGroups. The issue has been documented here:
http://blog.ray1.net/2010/03/bug-in-spweb-createdefaultassociatedgro.html
Beware the custom document library…
So it’s pretty much one of the stock-in-trade SharePoint dev tasks – there is a requirement to have a custom document library in the solution to extend the capabilities of the OOTB one. Maybe it wraps up a custom event receiver when it is created, sets custom properties or contains particular metadata or document templates, the whole thing is packaged up in your Visual Studio 2010 solution – with a list definition and list instance if required, and activated via a feature. So far so good – we can see it all documented in the how-to articles on MSDN.
If you are going to do this however, be aware of a couple of major gotchas, which of course, I have learned about through painful experience!
1. There is an issue with the List definition SharePoint Project Item (SPI) template in Visual Studio 2010. Simply put, the CAML that is generated by Visual Studio for the custom list definition in the schema.xml, is incomplete for the custom document library. If you are creating a custom list definition based on the Document content type, the section in the schema.xml relating to the view of the “Save As” dialog – the one that begins with:
<View BaseViewID=“2” Type=“HTML” FileDialog=“TRUE” TabularView=“FALSE” DisplayName=“$Resources:core,File_Dialog_View;” Hidden=“TRUE” Path=“filedlg.htm” ModerationType=“Moderator”>
This mark-up for this view is insufficient, and leads to the file dialog not displaying a view of existing documents in the library, which leads to confusion from end users. The issue is documented here, and can be relatively straightforward to fix, provided the problem is spotted during the development cycle. I was not so fortunate, and the fix will require a WSP deployment in production. Thankfully I have tested this and it will fix all existing document libraries.
2. If you create a custom document library, you will break the ability to email-enable that library using OOTB methods. I find this a particularly galling discovery. Go ahead and try it – in Visual Studio, Add New Item –> List Definition. Type: Document Library. Besides that – no changes. Deploy it, browse the new document library, and view the list settings. Note there is no link available for “Incoming email changes”…great.
So what’s the reason for this? Apparently, SharePoint hard-codes (ugh!) the Incoming Email settings link for OOTB lists of type Announcements, Event, Document Library, Picture Library, XML Form, Discussion Board, and Posts. So you create a custom document library and even though it is based on the template of document library (ID of 101), it still doesn’t work? Correct – and the reason is that the custom document library has its own custom ID – something normally assigned as greater than 10000 (as we were told to do in the best practices). We can’t use 101 for our ID, as it is already reserved by the Document Library template!
So what does Microsoft suggest we do about this? Apparently you need to create your own custom email event handler and attach to your list. In this EmailReceived event handler, you will need to write all the functionality you just lost by choosing to create a custom document library. From my perspective, that is a really crappy scenario that speaks volumes about SharePoint in microcosm. On the one hand, we’re told how wonderful SharePoint is as a development platform, and on the other, our actions in developing the product can remove some of the things that were available in the box. First it gives, and then it taketh away…
Lets not get started on other bewildering features, such as the fact that the email enabled document library option is also not available for OOTB document libraries created using the meeting workspace templates – try telling end users why that one happens (I’ve been asked, and I don’t know)!
My conclusion – don’t use a custom document library in SharePoint development, it’s that simple…
Co-Authoring with Office 2010 and SharePoint 2010
The whole point of implementing SharePoint 2010 in the Enterprise is that is supposed to make workers more productive, by introducing new and better ways of doing their day-to-day tasks, and thereby bringing about ROI savings to the organisation as a whole. That typically is the type of things that are presented in IT business cases for moving to a SharePoint platform. Wouldn’t it be great if that were true in reality!
Co-authoring is a shining case in point – I don’t really need to go into the details of how this can supposedly enable new levels of collaboration between co-workers – it’s all part of the SharePoint/Office integration sell that you’ve no doubt heard before. But looking at the small print, you find that (yet again) it appears to be another unfinished piece of functionality, with the following major annoyances:
- For some reason co-authoring is implemented in the client versions of Office 2010 for Word, PowerPoint and OneNote, but not in Excel
- You can only co-author Excel workbooks in Office Web Apps. However that has a reduced set of functionality, and adding something as seemingly trivial as a comment box into an Excel spread sheet, will break it entirely (See the following link to explain what is available in Excel web app:http://office.microsoft.com/en-us/excel-help/differences-between-using-a-workbook-in-the-browser-and-in-excel-HA010369179.aspx
- When you place an Excel workbook into a SharePoint library, you lose the ability to share the workbook over a network location, something that may have been in place prior to moving to the SharePoint platform, and something which to end users works much better than SharePoint co-authoring for Excel!
However, this blog post is not going to dwell on these shortcomings, but rather document the rather bizarre scenario that was encountered in setting up co-authoring in the first place. Documentation out there states that setting up co-authoring is relatively straight-forward, however in my case it did not work as expected. I went through the checklist of issues preventing co-authoring found here, and eventually pinpointed the issue down to specific Microsoft Office 2010 group policy settings implemented by the organisation. The documentation mentions the following GP settings:
- Disable Automerge Client Policy
- Disable Co-Authoring Server Policy
- Disable Co-Authoring Client Policy
These were all enabled ok however. It was only by trawling a little further that the following was discovered:
Based on the official Microsoft Group Policy description, the following policy setting should prevent co-authoring if it is disabled. However it appears to be the complete opposite, considering co-authoring was not working when the policy was set to “enabled” (as shown in the below screenshot), and co-authoring starts working once I manually disabled the policy setting on my test machines.
Once the setting was manually disabled, I was then able to successfully co-author Word docx and PowerPoint pptx files with Word 2010 and PowerPoint 2010 client software respectively.
Now I’m not sure if this is a quirk of the group policy setup or network settings in the organisation itself, or points to a genuine problem (has anyone else out there encountered this issue?) – however, it was THE single factor that allowed co-authoring to work in my scenario.
Introducing the struggle
The clue is in the title of this blog, the purpose of which is to document the trials and tribulations of working almost exclusively with Microsoft SharePoint products and technologies for the past 6 years.
I work for a global business and IT consultancy and have been placed in many UK based SharePoint projects in my time. During that period the size and complexity of projects has varied, but they are united by a common theme – when implementing SharePoint be prepared for a lot of hard lessons and no small measure of pain!
It has taken me a long time, but now I feel the time has come to document many of the problems and issues and “gotchas” that I have encountered over the years, and all the tricks, tips and hacks that have been employed to overcome them.
When I try to sum up SharePoint for IT implementations, a different sort of 80/20 rule springs to mind. Not the Pareto derived rule, which would state for example that in a SharePoint deployment efforts should be focused to deliver functionality to the 20% of an organization who will be doing 80% of the workload; rather it is to another type of rule, where 80% of the requirements can easily be implemented using out of the box components, and 20% require customisations or development work to occur. And in my view, it’s delivering that final 20% that can kill you on a SharePoint implementation.
Another recurring theme that will emerge from the forthcoming posts is the frustration with finding that SharePoint will frequently introduce multiple ways of achieving the same result, and in each case it will fail to provide a complete solution to the problem at hand. The overriding conclusion is that if SharePoint was only able to do something one way, and do it properly, it would be a much better product!