Chris's coding blog

Umbraco hacks for developers

May 05, 2010

A lot of the tips here are relevant for Umbraco 3.0, issues such as the debug builds have been resolved in 4.0

Sitemap XSLT

The XSL below is the source used for Sitemap on sloppycode.net. It’s taken from the Umbraco book, and modified to display the Dublin Core description alongside each page’s url.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp " ">
]>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library"
exclude-result-prefixes="msxml umbraco.library">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:param name="currentPage"/>
<!-- update this variable on how deep your site map should be -->
<xsl:variable name="maxLevelForSitemap" select="4"/>
<xsl:template match="/">
<div id="sitemap">
<xsl:call-template name="drawNodes">
<xsl:with-param name="parent" select="$currentPage/ancestor-or-self::node [@level=1]"/>
</xsl:call-template>
</div>
</xsl:template>
<xsl:template name="drawNodes">
<xsl:param name="parent"/>
<ul>
<xsl:for-each select="$parent/node [string(./data [@alias='umbracoNaviHide']) != '1' and @level"
<= $maxLevelForSitemap]">
<li>
<a href="{umbraco.library:NiceUrl(@id)}">
<xsl:value-of select="@nodeName"/>
</a> - <xsl:value-of select="./data[@alias='dcDescription']"/>
<xsl:if test="count(./node [string(./data [@alias='umbracoNaviHide']) != '1' and @level"
<= $maxLevelForSitemap]) > 0">
<xsl:call-template name="drawNodes">
<xsl:with-param name="parent" select="."/>
</xsl:call-template>
</xsl:if>
</li>
</xsl:for-each>
</ul>
</xsl:template>
</xsl:stylesheet>
view raw gistfile1.xslt hosted with ❤ by GitHub

Changing the content type of a document

I’ve had to do this quite often on sloppycode.net when I realised I’ve created something as a Textpage (a built in document type) but then need some code highlighting which comes from a different content type.
I haven’t got round to making a tool to do it, but it’s simple to do when access to SQL Enterprise Manager/Management Studio.

First of all, backup the content of the document you are going to change. This is important, as changing the content type wipes the content. I don’t know why, the developers will know the reason for that. But the bodyText and the properties dissapear. Changing the contentType is straight forward, simply run

UPDATE cmsContent SET contentType={Your ContentTypeID} WHERE nodeId={Your document ID}

in SQL Server Management studio. You can get a list of contentTypes from the contentType table. nodeId holds the ID (rather than the pk column).

Once you have done this, publish your document. It will probably show a null reference exception when you click on the node in the editor. This will go once it has been published.

Moving multiple documents

If you need to move a lot of documents at once to a new parent, it’s painful doing it inside the editor. A SQL Script for doing this is below, just change the @oldParentId and @ParentId accordingly. Make sure you backup your database first.

--drop table #temp
set nocount on
declare @OldParentId int
declare @ParentId int
declare @Id int
declare @Path nvarchar(150)
select @OldParentId = 1139 -- Set to the existing parent node
select @ParentId = 2457 -- Set to the new parent node
-- First update the parentid column
update umbracoNode set parentid=@ParentId where parentId=@OldParentId
-- Next update all the path columns for the children.
SELECT id,[path] into #temp FROM [umbracoNode] where parentid=@ParentId
while exists(select Id from #temp)
begin
select @Id=Id,@Path=[Path] from #temp
select @Path = REPLACE(@Path,@OldParentId,@ParentId)
update umbracoNode set path=@Path where id=@Id
print cast(@Id as varchar)+': ' +@Path
delete from #temp where Id=@Id
end
view raw gistfile1.sql hosted with ❤ by GitHub

Performance issues with Umbraco

Since installing Umbraco and running sloppycode.net on it since December 2006 I’ve noticed a few ways of making it go faster. Most of them are out of the box with Umbraco, like using the XML cache however there’s a few others worth a mention:

Truncate your umbracoLog table regularly

The table contains all exceptions and warnings plus a host of other information from the Umbraco system. Most of this you don’t need and can clog up the database. The table can grow very large quickly, particularly if you’re creating the website for the first time and testing. This image shows an example

umbraco tables

Before this the site was 500,000 records strong before I noticed. The backups become large too. So simply run truncate on it:

TRUNCATE TABLE [dbo].umbracoLog

There’s not point saving the deletes to the transcation log with DELETE FROM, as the data is never used by Umbraco except for your information.

Make sure tracing and debug is turned off

Find the following lines in your web.config file and make sure the attributes are set to false, it makes a noticeable difference:

<trace enabled="false" requestLimit="10" pageOutput="false" traceMode="SortByTime" localOnly="true" />
...
<compilation defaultLanguage="c#" debug="false">
...
<add key="umbracoDebugMode" value="false" />

GZip your HTML output

I’ve written a small HttpModule based on some code by Bart De Smet that’s very simple to install. It GZIP’s your HTML output, reducing the bandwidth your site uses and page load time. It’s aimed at people using shared hosting or pre-IIS 5 servers.

Changing templates on multiple documents

Like moving lots of documents at once, this is also a pain in the editor. The code below (for version 3.03) does this for you. You’ll need to turn it into a webservice and make a calling application to use it.

using System;
using System.Web;
using System.Web.Services;
using System.Collections;
using System.Web.Services.Protocols;
using umbraco.cms.businesslogic;
using umbraco.cms.businesslogic.web;
using umbraco.BusinessLogic;
using System.Xml.Serialization;
using umbraco.cms.businesslogic.property;
using umbraco.cms.businesslogic.macro;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class YourWebservice : System.Web.Services.WebService
{
[WebMethod]
public void UpdateDocumentParent(int docId, int parentId, bool deep, int templateId)
{
if (deep)
{
ArrayList list = this.GetDocumentChildren(docId);
for (int i = 0; i < list.Count; i++)
{
if (list[i] is Document)
{
int n;
int.TryParse(((Document)list[i]).Id.ToString(), out n);
if (n > 0)
{
try
{
Document d = new Document(n);
d.Publish(new User(0));
}
catch { }
}
}
}
}
else
{
Document d = new Document(docId);
d.Template = templateId;
d.Publish(new User(0));
}
}
private ArrayList GetDocumentChildren(int docId)
{
Document doc = new Document(docId);
Document[] children = doc.Children;
ArrayList list = new ArrayList();
if (children.Length > 0)
{
for (int i = 0; i < children.Length; i++)
{
if (children[i].HasChildren)
{
list.AddRange(GetDocumentChildren(children[i].Id));
}
list.Add(children[i]);
}
}
return list;
}
}
view raw gistfile1.cs hosted with ❤ by GitHub

Database schema

This shows the schema of the Umbraco database, imported into Visio and organised so the tables are grouped together.

umbraco schema

Download the original Visio file

Data export

This tool came from having troubles backing up an Umbraco database on gate.com - who didn’t allow user backups of SQL databases or remote SSIS packages. The host has now been switched but for users of similar hosts like godaddy.com the tool is useful. Find it here (it needs Visual Studio to compile it, which you can get for free).

Links

These links are included to supplement the ones on the Umbraco.org site.

umbraco

I'm Chris Small, a software engineer working in London. This is my tech blog. Find out more about me via GithubStackoverflowResume