When moving a database with backup/restore between different web farms the URL from the Publishing Pages to the PageLayout often contains the server name of the original farm.
For Example:
A customer creates a backup of a content database on one server farm (e.g. using STSADM -o backup or a DB backup in SQL) and restores the backup on a different farm and attaches the content database to a web application.
After this operation is done several operations (like variations and content deployment) fail to work with the following exception:
Be aware that backup/restore of MOSS content databases between server farms are not fully supported! Official documentation of this support limitation is currently in the works. The supported way to transfer content between server farms is to use STSADM -o export/import or content deployment. Backup/restore is only supported for the same server farm. In case that you have run into the above problem you have two options:
To build this tool you need to
- create a new C# console application project in VS.NET with name "FixPageLayout"
- replace the .cs file with the FixPageLayout.cs file included in this download
- add references to Microsoft.SharePoint.dll and Microsoft.SharePoint.Publishing.dll
- build the project
Syntax to use the tool:
FixPageLayout.exe [ url-to-sitecollection ]
Code:
///
/// This source code is freeware and is provided on an "as is" basis without warranties of any kind,
/// whether express or implied, including without limitation warranties that the code is free of defect,
/// fit for a particular purpose or non-infringing. The entire risk as to the quality and performance of
/// the code is with the end user.
///
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;
namespace FixLayouts
{
class FixPageLayout
{
const string USAGE = "Usage: FixPageLayout.exe";
const string MASTER_PAGE_LIB = "_catalogs/masterpage";
static void Main(string[] args)
{
if (args.Length < 1)
{
Console.WriteLine(USAGE);
return;
}
string SiteCollectionUrl = args[0];
if (!Uri.IsWellFormedUriString(SiteCollectionUrl, UriKind.Absolute))
{
Console.WriteLine(USAGE);
return;
}
try
{
// get the site collection
using (SPSite site = new SPSite(SiteCollectionUrl))
{
// get the servername from RootWeb as it should be
using (SPWeb RootWeb = site.RootWeb)
{
SiteCollectionUrl = RootWeb.Url.ToLower();
if (!SiteCollectionUrl.EndsWith("/"))
SiteCollectionUrl += "/";
}
// check each site in the site collection
foreach (SPWeb web in site.AllWebs)
{
try
{
// check if the site is a publishing site
if (PublishingWeb.IsPublishingWeb(web))
{
PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(web);
// check each Publishing page in the current publishing site
foreach (PublishingPage page in pubWeb.GetPublishingPages())
{
// retrieve the page layout of the publishing page
string pageLayout = page.ListItem.Properties["PublishingPageLayout"] as string;
// check for correct syntax of the page layout URL
if (pageLayout != null)
pageLayout = pageLayout.ToLower();
if (String.IsNullOrEmpty(pageLayout))
{
Console.WriteLine("Error: Page \"{0}\" does not have a Page Layout assigned.\n", page.Uri);
}
else if (!pageLayout.Contains(MASTER_PAGE_LIB))
{
Console.WriteLine("Error: The Page Layout {0} for Page \"{1}\" does not point to the masterpage document library.\n",
pageLayout, page.Uri);
}
else if (!pageLayout.StartsWith(SiteCollectionUrl) && pageLayout.StartsWith("http"))
{
// here we have a page which has a page layout with different URL which we have to fix
Console.WriteLine("Page {0} has incorrect PageLayout Url", page.Uri);
Console.WriteLine("Old URL: {0}", pageLayout);
string pageLayoutWithoutPrefix = pageLayout.Substring(pageLayout.IndexOf(MASTER_PAGE_LIB));
string newPageLayout = SiteCollectionUrl + pageLayoutWithoutPrefix;
// perform the update in a try/catch block to cover problems
try
{
int version = page.ListItem.File.MinorVersion;
page.CheckOut();
page.ListItem.Properties["PublishingPageLayout"] = newPageLayout;
page.ListItem.File.Properties["PublishingPageLayout"] = newPageLayout;
page.ListItem.Update();
page.CheckIn("PublishingPageLayout corrected");
//major version means that the item was published. Lets publish it again.
if (version == 0)
page.ListItem.File.Publish("PublishingPageLayout corrected");
Console.WriteLine("Fixed URL: {0}\n", newPageLayout);
}
catch (Exception e)
{
Console.WriteLine("An error occurred while trying to fix the URL to the page layout:\n{0}", e);
}
}
}
}//if Publishing web
}
finally
{
// don't forget to dispose the SPWeb object
web.Dispose();
}
}
}//using SPSite
}
catch (System.IO.FileNotFoundException ex)
{
Console.WriteLine("{0}", ex.Message);
}
catch (Exception ex)
{
Console.WriteLine("An error has occured: {0}", ex.Message);
}
}
}
}
For Example:
A customer creates a backup of a content database on one server farm (e.g. using STSADM -o backup or a DB backup in SQL) and restores the backup on a different farm and attaches the content database to a web application.
After this operation is done several operations (like variations and content deployment) fail to work with the following exception:
System.ArgumentException. Value does not fall within the expected range.The reason for this problem is that backup/restore does not adjust the references from the publishing page objects in the Pages library to their Page Layouts. These URLs are sometimes stored as absolute URLs including the server name. And this server name is the server name of the old server farm which cannot be resolved on the new farm.
at Microsoft.SharePoint.Library.SPRequestInternalClass.GetMetadataForUrl(String bstrUrl, Int32 METADATAFLAGS, Guid& pgListId, Int32& plItemId, Int32& plType, Object& pvarFileOrFolder)
at Microsoft.SharePoint.Library.SPRequest.GetMetadataForUrl(String bstrUrl, Int32 METADATAFLAGS, Guid& pgListId, Int32& plItemId, Int32& plType, Object& pvarFileOrFolder)
at Microsoft.SharePoint.SPWeb.GetMetadataForUrl(String relUrl, Int32 mondoProcHint, Guid& listId, Int32& itemId, Int32& typeOfObject, Object& fileOrFolder)
at Microsoft.SharePoint.SPWeb.GetFileOrFolderObject(String strUrl)
at Microsoft.SharePoint.Publishing.CommonUtilities.GetFileFromUrl(String url, SPWeb web)
...
Be aware that backup/restore of MOSS content databases between server farms are not fully supported! Official documentation of this support limitation is currently in the works. The supported way to transfer content between server farms is to use STSADM -o export/import or content deployment. Backup/restore is only supported for the same server farm. In case that you have run into the above problem you have two options:
- Throw away the database and transfer it correctly using STSADM -o export/import or content deployment
- Fix the incorrect links manually using the following steps
- Open the web in SharePoint Designer
- On the “task panes” window, pick hyperlinks.
- For the “hyperlink” heading, click the arrow and pick (custom…)
- In the dialog, ask to show rows where the hyperlink begins with a URLs which are not valid on the current server farm
- For each of the files, right click and say “Edit hyperlink…” and Replace hyperlink with the hyper link that is valid on the current server farm
To build this tool you need to
- create a new C# console application project in VS.NET with name "FixPageLayout"
- replace the .cs file with the FixPageLayout.cs file included in this download
- add references to Microsoft.SharePoint.dll and Microsoft.SharePoint.Publishing.dll
- build the project
Syntax to use the tool:
FixPageLayout.exe
Code:
///
/// This source code is freeware and is provided on an "as is" basis without warranties of any kind,
/// whether express or implied, including without limitation warranties that the code is free of defect,
/// fit for a particular purpose or non-infringing. The entire risk as to the quality and performance of
/// the code is with the end user.
///
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;
namespace FixLayouts
{
class FixPageLayout
{
const string USAGE = "Usage: FixPageLayout.exe
const string MASTER_PAGE_LIB = "_catalogs/masterpage";
static void Main(string[] args)
{
if (args.Length < 1)
{
Console.WriteLine(USAGE);
return;
}
string SiteCollectionUrl = args[0];
if (!Uri.IsWellFormedUriString(SiteCollectionUrl, UriKind.Absolute))
{
Console.WriteLine(USAGE);
return;
}
try
{
// get the site collection
using (SPSite site = new SPSite(SiteCollectionUrl))
{
// get the servername from RootWeb as it should be
using (SPWeb RootWeb = site.RootWeb)
{
SiteCollectionUrl = RootWeb.Url.ToLower();
if (!SiteCollectionUrl.EndsWith("/"))
SiteCollectionUrl += "/";
}
// check each site in the site collection
foreach (SPWeb web in site.AllWebs)
{
try
{
// check if the site is a publishing site
if (PublishingWeb.IsPublishingWeb(web))
{
PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(web);
// check each Publishing page in the current publishing site
foreach (PublishingPage page in pubWeb.GetPublishingPages())
{
// retrieve the page layout of the publishing page
string pageLayout = page.ListItem.Properties["PublishingPageLayout"] as string;
// check for correct syntax of the page layout URL
if (pageLayout != null)
pageLayout = pageLayout.ToLower();
if (String.IsNullOrEmpty(pageLayout))
{
Console.WriteLine("Error: Page \"{0}\" does not have a Page Layout assigned.\n", page.Uri);
}
else if (!pageLayout.Contains(MASTER_PAGE_LIB))
{
Console.WriteLine("Error: The Page Layout {0} for Page \"{1}\" does not point to the masterpage document library.\n",
pageLayout, page.Uri);
}
else if (!pageLayout.StartsWith(SiteCollectionUrl) && pageLayout.StartsWith("http"))
{
// here we have a page which has a page layout with different URL which we have to fix
Console.WriteLine("Page {0} has incorrect PageLayout Url", page.Uri);
Console.WriteLine("Old URL: {0}", pageLayout);
string pageLayoutWithoutPrefix = pageLayout.Substring(pageLayout.IndexOf(MASTER_PAGE_LIB));
string newPageLayout = SiteCollectionUrl + pageLayoutWithoutPrefix;
// perform the update in a try/catch block to cover problems
try
{
int version = page.ListItem.File.MinorVersion;
page.CheckOut();
page.ListItem.Properties["PublishingPageLayout"] = newPageLayout;
page.ListItem.File.Properties["PublishingPageLayout"] = newPageLayout;
page.ListItem.Update();
page.CheckIn("PublishingPageLayout corrected");
//major version means that the item was published. Lets publish it again.
if (version == 0)
page.ListItem.File.Publish("PublishingPageLayout corrected");
Console.WriteLine("Fixed URL: {0}\n", newPageLayout);
}
catch (Exception e)
{
Console.WriteLine("An error occurred while trying to fix the URL to the page layout:\n{0}", e);
}
}
}
}//if Publishing web
}
finally
{
// don't forget to dispose the SPWeb object
web.Dispose();
}
}
}//using SPSite
}
catch (System.IO.FileNotFoundException ex)
{
Console.WriteLine("{0}", ex.Message);
}
catch (Exception ex)
{
Console.WriteLine("An error has occured: {0}", ex.Message);
}
}
}
}
0 comments:
Post a Comment