I recently performed another upgrade from SharePoint Portal Server 2003 to MOSS, and while the upgrade was executed without any major problems(I’ve earned bragging rights); we experienced a large number of calls due to broken links from other sites, and links that where saved as shortcuts or browser “favorites”. Most of them were due to a very large information re-architecture.

Some of the more important links where accounted for and redirected to the proper pages by adding URL mappings to the web.config file, a surprisingly easy though not very common technique. Undoubtedly many files would be left out, as its rather difficult (never say never) to find out what links and shortcuts people have saved. Ultimately they wanted a custom 404 page that would display a page with a friendly message using the portal look and feel.

Solution Overview

This is fairly easy to accomplish as SharePoint does provide an SPWebApplication property (FileNotFoundPage) to specify a custom 404 page. Unfortunately the property is only accessible via the API, and the file must be an HTML page located in \\Program Files\Common Files\Microsoft Shared\web server extensions\12\LAYOUTS\Locale_ID

Of course it would be easier if we could set this property from Central Administration, and why stop there, why not allow an administrator to specify a page in the portal, or anywhere else, and of any type for that matter. So I developed a SharePoint solution containing the following:

  • An HTML page to specify as the FileNotFoundPage of the web application. This page redirects all requests to custom application page where its easier to handle the request.
  • A settings page from where custom settings on how to handle the request can be specified for each web application.
  • A SharePoint application page that handles the request based on the custom settings specified for the web applicaiton
  • A feature that creates a menu item in “Central Administration > Application Management” for the settings page

 

I’ve made the WSP and Visual Studio Project available for download: (WSP, Project)

Solution Detail

The HTML file is simply a copy of the sps404.htm file that SharePoint installs by default in “c:\program files\common files\microsoft shared\web server extensions\12\template\layouts\1033”, I’ve simply replaced the path it uses to redirect requests to with that of my custom 404 handler aspx page.

The Custom404Settings.aspx page allows the user to select a web application and specify a custom 404 page. The value specified is saved to a custom property of the web application that can later be referenced by the Custom404Handler.aspx page.

The following code is used to update the FileNotFoundPage property of the web application and create a new property “Custom404Path” to store the specified custom 404 path value.



SPFarm farm = SPFarm.Local;
SPWebService service = farm.Services.GetValue("");
string webAppPropertyKey = "Custom404Path";

Guid webAppGuid = new Guid(lstWebApplications.SelectedValue);
SPWebApplication webApp = service.WebApplications[webAppGuid];

//create a web application property to store the
//path to the custom 404 page
if (webApp.Properties.ContainsKey(webAppPropertyKey))
{
webApp.Properties[webAppPropertyKey] = txtCustom404Path.Text;
}
else
{
webApp.Properties.Add(webAppPropertyKey, txtCustom404Path.Text);
}
lblMessage.Text = "Changes saved";

//update the FileNotFound property of the web application
//this needs to be an html page in the LAYOUTS/1033
webApp.FileNotFoundPage = "Custom404Page.htm";

//update the web application
webApp.Update();

The Custom404Handler.aspx page checks the value of the Custom404Path property of the web application and redirects the browser to that page. If the custom 404 path specified returns as the path not found (“oldUrl” querystring parameter) the page does not redirect the user and serves the custom 404 message itself (this is to avoid going into an endless redirect loop).

The following code is used to check the custom 404 path of the web application and perform the redirect.


using (SPSite thisSite = new SPSite(SPContext.Current.Site.Url))
{
string custom404Path = "";
string pageNotFound = Request.QueryString["oldUrl"];
SPWebApplication webApp = this.Site.WebApplication;

if (webApp.Properties.ContainsKey(webAppPropertyKey))
{
custom404Path = (string)webApp.Properties[webAppPropertyKey];
}

if ((custom404Path != "") && !(custom404Path.ToLower().Contains("custom404handler.aspx")) && !(pageNotFound.ToLower().Contains(custom404Path.ToLower())))
{
Response.Redirect(custom404Path);
}

}

The feature.xml and elements.xml files add a custom menu item to “Central Administration > Application Management” from where the users can specify the custom 404 settings.

feature.xml:

elements.xml:

Updated 7/28/2008 : Updated Samples, Project Files and WSP to include recommended changes for handling anonymous requests.

Advertisements