Creating an Xml Sitemap in Umbraco

How I built an XML sitemap for Umbraco using XML serialisation.


I found that all the pages in my website were not being indexed by Google so I thought it's about time I added an xml sitemap to my site.

So firstly I created a new document type in Umbraco called Xml Sitemap (alias = xmlSitemap), and then created a new content item for the site based on the document type.

Note that you do not need a template for this as the xml sitemap is returned as xml from the controller.

The Sitemap Model

I wanted to make sure I followed the standard sitemap protocol: http://www.sitemaps.org/protocol.html so I created my model to match this by creating 2 model classes - Sitemap and SitemapUrl.

I am using the XmlElement attributes so that when the models are serialised that they will have the correct element names.

using System.Collections.Generic;
using System.Xml.Serialization;

namespace Website.Models
{
    [XmlRoot("urlset", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
    public class Sitemap
    {
        [XmlElement("url", Type = typeof(SitemapUrl))]
        public List<SitemapUrl> SiteMapItems { get; set; }
    }

    public class SitemapUrl
    {
        [XmlElement("loc")]
        public string Url { get; set; }

        [XmlElement("lastmod")]
        public string LastModified { get; set; }

        [XmlElement("changefreq")]
        public string ChangeFreq { get; set; }

        [XmlElement("priority")]
        public string Priority { get; set; }
    }
}

The Controller

The controller calls GetSiteMap which gets the root item of the site and then recursively adds each item to the list ensuring it only adds pages that are visible (umbraconavihide is false) and have a template set.

The sitemap is then serialised to XML and returned as string content with the content type set to "text/xml".

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Xml.Serialization;
using Website.Models;
using Umbraco.Core.Models;
using Umbraco.Web;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;

namespace Website.Controllers
{
    public class XmlSitemapController : RenderMvcController
    {
        public override ActionResult Index(RenderModel model)
        {
            var sitemap = GetSitemap();
            return Content(SitemapToXml(sitemap), "text/xml");
        }

        private Sitemap GetSitemap()
        {
            var sitemap = new Sitemap { SiteMapItems = new List<SitemapUrl>() };
            var rootItem = Umbraco.TypedContentAtRoot().FirstOrDefault();
            AddItemToList(sitemap.SiteMapItems, rootItem);

            return sitemap;
        }

        private static void AddItemToList(ICollection<SitemapUrl> urlList, IPublishedContent item)
        {
            if (item.IsVisible() && item.TemplateId != 0)
            {
                urlList.Add(new SitemapUrl
                {
                    Url = item.UrlWithDomain(),
                    LastModified = item.UpdateDate.ToString("yyyy-MM-dd")
                });
            }

            foreach (var childItem in item.Children())
            {
                AddItemToList(urlList, childItem);
            }
        }

        private static string SitemapToXml(Sitemap sitemap)
        {
            string xml;
            var xmlSerialiser = new XmlSerializer(sitemap.GetType());

            using (var stringWriter = new Utf8StringWriter())
            {
                xmlSerialiser.Serialize(stringWriter, sitemap);
                xml = stringWriter.ToString();
            }

            return xml;
        }

        public class Utf8StringWriter : StringWriter
        {
            public override Encoding Encoding => Encoding.UTF8;
        }
    }
}

Submitting Your Sitemap

Once your sitemap is built you can submit it to Google using either the webmaster tools: https://www.google.com/webmasters/tools/

or you can add it to your robots.txt:

Sitemap: http://programystic.com/sitemap-xml/

Comments

Pete's Code Library

Peter Edney at a wedding

My code library is where I keep all my useful bits of code that I refer to over and again. They are generally incomplete and are a quick tool to remind me of how to resolve an issue.

Categories