Blog Archives

Migrating Master Pages from MOSS 2007 to SharePoint 2010

I’ve mentioned before that I am doing a complex migration from MOSS 2007 to SharePoint 2010 and I came across an absolute doozy of an issue over the last couple of days. I doubt anyone else will come across this, but it worth noting, if not just for my sanity, but also in case it crops up somewhere else.

The source 2007 site was a publishing site with a heavily customised Master Page. The Master Page containing some controls in it for navigation and so on – unfortunately the source code for these controls were written in Visual Studio 2005 and deployed, well, somehow. I rebuilt the controls in VS2010 and a nice WSP for deployment.

There remains the problem of getting it to work in the new environment. The old control would not work, giving the SharePoint Screen of Death. No problem, I don’t need it anyway. I copied the old 2007 Master Page, uploaded it into 2010 and worked on it with SharePoint Designer to run the new control. All is hunky dory.

Until we come to roll out. Plan was to do a migration via Attach Database, then put my new Master Page into the system, flip over to it and all is well.

The migration goes OK, the site pops up with the expected Master Page error, I go into SPD to upload the new custom MP, check it in, requires Approval so open the page in the browser and…

Error. The Approval page still uses the old, failing, MP.

I can change the MP using the GUI but I can’t flip it to the new Master page because it hasn’t been Approved and I can’t Approve it because that relies on a Master Page that fails.

OK, so off to Powershell I go and Approve the page in the back end. Back to the Change Master Page page and my custom MP either does not appear in the dropdown or gives me a warning that it is set for SharePoint v4 (2010) and not the v3 (2007) UI that we are keeping.

The problem is this. If you upload a Master Page to the Master Page Gallery, the UI Version is automatically set to v4 – SharePoint 2010. This is a problem if you are using the v3 GUI – either the new MP will not appear for selection and if it does, it is set to v4. You can’t change this because your Master Page is faulty and you can’t get to the List through the browser. The value is not available in SPD to change.

After a lot of faffing, the solution I found is this.

1. Using Powershell, change the MasterPage Url to default.master (or something other than your current MP, but still v3).
2. Go into the Master Page Gallery and edit the new custom Master Page item you added and set the UI Version to 3 (not both 3 and 4, but 3).
3. Back into Powershell and change the MasterPage Url to your new custom Master Page.

It will all work now.

The key fact to take away is that by default in SharePoint 2010, any Master Page uploaded to the Gallery is set to v4 even if your site is running as v3.

Extracting WSPs from MOSS

Currently in the middle of a MOSS 2007 -> SharePoint 2010 migration and there is a lot of cruft in the existing configuration.  I think that a lot of it can be removed, but you never actually know until you have migrated successfully.  Since time is of the essence and I could waste of lot it rewriting WSP files and solutions that aren’t needed, it is much more useful to try extracting the existing solutions out of SharePoint.  I had done this many moons ago as part of an upgrade from SP1, but it required a Console App and some custom code.  Thankfully, the MOSS farm was on SP2 and the server had Powershell installed.  A swift Googling led me to the following Powershell script:

Start-Transcript "c:\wsp\transcript.txt"
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
$solutions = [Microsoft.SharePoint.Administration.SPFarm]::Local.Solutions;
foreach ($solution in $solutions) {
   $solution.SolutionFile.SaveAs("c:\wsp\" + $solution.Name);
}
Stop-Transcript

 

Which works perfectly.  So massive hat tip to Ben Leach.

PowerShell is swiftly becoming one of the best things Microsoft ever did.

Programmatically getting the Site Collection Name

Just was sorting out a quick console app that audited all the details of a MOSS 2007 farm, all Web Applications, down through Site Collections, Sites, Webs and down to list level.  When presenting this to the end user, I wanted to use a cascading drop down, where the user selected the Web Application and then had a nice list of Site Collections to choose from.

The problem I hit was how on earth to get the Site Collection Title and Description.  These are displayed in Central Administration | Application Management | Site Collection List but are not included in the SPSiteCollection object, nor the WebApplication object (which holds stuff like the Content Database which is included on that page).

Answer: the Title and Description that appears on the Site Collection List page is the Title and Description of the root Site in the Site Collection.

Try it!  Check the Title and Description in Central Admin, then change them on the root Site using Site Settings | Title, Description and Icon.

Took me a while to find that one…

Individual MySite Quotas

Had a request from a user who had run out of space for storing documents in their MySite.  One of the fun side effects of this in MOSS 2007 is that you can’t use the GUI to change the quota allocated – it throws the standard SharePoint error.

Because the MySite is a Site Collection, you can change the quota on an individual basis.  I knocked together a short console app in Visual Studio 2008.

Build and run it from the Command Line using the syntax:

SiteQuotaChange.exe -url %URL% -quotaname %QUOTANAME%

Notes:
1. Because %QUOTANAME may be something like “Personal Site”, you need to put the quota name in ” marks if it contains a space.
2. If you get %QUOTANAME% wrong, MOSS 2007 will default back to “Individual Quota” with no space allocated.

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
namespace SiteQuotaChange
{
class Program
{
private static string url = String.Empty;
private static string quotaName = String.Empty;

static void Main(string[] args)
{
try {
GetArgs(args);
if (url == String.Empty || quotaName == String.Empty || args.Length > 4)
{
Console.WriteLine("Usage: sitequotachange -url %URL% -quotaname %QUOTANAME%");
}
else
{
using (SPSite site = new SPSite(url))
{
SPWeb web = site.OpenWeb();
Console.WriteLine("Before: " + site.Quota.StorageMaximumLevel);
web.AllowUnsafeUpdates = true;
web.Update();
site.Quota = SPWebService.ContentService.QuotaTemplates[quotaName];
web.Update();
Console.WriteLine("After: " + site.Quota.StorageMaximumLevel);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Exception thrown: {0}, {1}", ex.GetType(), ex.Message);
}
Console.WriteLine();
Console.WriteLine("Finished, press any key");
Console.ReadKey();
}

private static void GetArgs(string[] args)
{
for (int i = 0; i < args.Length; i++)
{
switch (args[i])
{
case "-url":
url = args[i+1];
break;
case "-quotaname":
quotaName = args[i + 1].Replace("\"", "");
break;
}
}
}
}
}