How to use an ASP.NET SiteMapProvider to produce a XML SiteMap for Google, Yahoo, Bing, etc

More often I’m being asked to provide “SiteMap.xml”s for sites we work on, and up until recently we had been hand rolling the xml and placing them in static documents on our sites. This is fine but seemed a little silly because ASP.NET has a built in SiteMap mechanism. So we decided to do something about using it for auto generating the SiteMap.xml.

My example is using Maarten Balliauw’s awesome MvcSiteMap available at http://mvcsitemap.codeplex.com/ but the conversion code works perfectly fine with the built in SiteMapProvider in ASP.NET.

Using the following class we can generate the XML object representing the SiteMap.

  public class SiteMapXMLNode
  {
    public enum enChangeFrequency
    {
      NoneGiven,
      Always,
      Hourly,
      Daily,
      Weekly,
      Monthly,
      Yearly,
      Never
    }

    [System.Xml.Serialization.XmlElement(ElementName = "loc")]
    public string URL;

    #region Last Modified
    [System.Xml.Serialization.XmlIgnore]
    public DateTime LastModified;
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    [System.Xml.Serialization.XmlElement(ElementName = "lastmod")]
    public string __LastModified
    {
      get { return (LastModified == DateTime.MinValue ? null : string.Format("{0:yyyy-MM-dd}", LastModified)); }
      set { LastModified = DateTime.MinValue; } //Note: This property will never be deserialized
    }
    #endregion

    #region Change Frequency
    [System.Xml.Serialization.XmlIgnore]
    public enChangeFrequency ChangeFrequency;
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    [System.Xml.Serialization.XmlElement(ElementName = "changefreq")]
    public string __ChangeFrequency
    {
      get { return (ChangeFrequency == enChangeFrequency.NoneGiven ? null : ChangeFrequency.ToString().ToLower()); }
      set { ChangeFrequency = enChangeFrequency.NoneGiven; } //Note: This property will never be deserialized
    }
    #endregion

    #region Priority
    [System.Xml.Serialization.XmlIgnore]
    public decimal? Priority;
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    [System.Xml.Serialization.XmlElement(ElementName = "priority")]
    public string __Priority
    {
      get { return (!Priority.HasValue ? null : string.Format("{0:0.0}", Priority)); }
      set { Priority = null; } //Note: This property will never be deserialized
    }
    #endregion

    public SiteMapXMLNode()
    {
      URL = null;
      LastModified = DateTime.MinValue;
      ChangeFrequency = enChangeFrequency.NoneGiven;
      Priority = null;
    }

    public SiteMapXMLNode(System.Web.SiteMapNode node)
      : this()
    {
      UriBuilder uriBuilder = new UriBuilder(System.Web.HttpContext.Current.Request.Url);
      uriBuilder.Path = node.Url;
      URL = uriBuilder.ToString();
    }
  }

  [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9", IsNullable = false, ElementName = "urlset")]
  public class SiteMapXML
  {
    private List<SiteMapXMLNode> Nodes;

    #region "urls"
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    [System.Xml.Serialization.XmlElementAttribute("url")]
    public SiteMapXMLNode[] __Nodes
    {
      get
      {
        return Nodes.ToArray();
      }
      set
      {
        Nodes.Clear();
        Nodes.AddRange(value);
      }
    }
    #endregion

    public SiteMapXML()
    {
      Nodes = new List<SiteMapXMLNode>();
    }

    public SiteMapXML(System.Web.SiteMapNode rootNode)
      : this()
    {
      Add(rootNode);
    }

    public void Add(System.Web.SiteMapNode rootNode)
    {
      Nodes.Add(new SiteMapXMLNode(rootNode));

      if (rootNode.HasChildNodes)
      {
        foreach (System.Web.SiteMapNode node in rootNode.ChildNodes)
        {
          if (node.IsAccessibleToUser(System.Web.HttpContext.Current)) Add(node);
        }
      }
    }
  }

Then we use this action for MVC

    public ActionResult SiteMapXML()
    {
      ActionResult result = null;

      SiteMapXML siteMapXML = new SiteMapXML(System.Web.SiteMap.RootNode);

      using (System.IO.MemoryStream oStream = new System.IO.MemoryStream())
      {
        System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(typeof(SiteMapXML));
        xmlSerializer.Serialize(oStream, siteMapXML);
        oStream.Flush();
        xmlSerializer = null;

        System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding(false);

        result = new ContentResult() { ContentType = "text/xml", Content = UTF8.GetString(oStream.ToArray()), ContentEncoding = UTF8 };
      }

      return result;
    }

Or this code behind for ASP.NET

    protected void Page_Load(object sender, EventArgs e)
    {
      Response.Clear();

      Response.ContentType = "text/xml";

      SiteMapXML siteMapXML = new SiteMapXML(System.Web.SiteMap.RootNode);

      System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(typeof(SiteMapXML));
      xmlSerializer.Serialize(Response.OutputStream, siteMapXML);
      xmlSerializer = null;

      Response.Flush();

      Response.End();
    }

It’s really that simple

 

ToDo: add Attributes and elements to the SiteMap definition so we can take advantage of the additional Attributes in the SiteMap XSD (“lastmod”, “changefreq” and “priority”)

Published 10/16/2009 15:47:54 (UTC) by Ron Muth

kick it on DotNetKicks.com  Shout it  vote it on WebDevVote.com

Comments

DotNetKicks.com How to use an ASP.NET SiteMapProvider to produce a XML SiteMap

10/16/2009 15:56:51 by DotNetKicks.com
You've been kicked (a good thing) - Trackback from DotNetKicks.com

DotNetBurner - ASP.net How to use an ASP.NET SiteMapProvider to produce a XML SiteMap for Google, Yahoo, Bing, etc

10/16/2009 15:57:37 by DotNetBurner - ASP.net
DotNetBurner - burning hot .net content

DotNetShoutout How to use an ASP.NET SiteMapProvider to produce a XML SiteMap for Google, Yahoo, Bing, etc

10/16/2009 16:04:08 by DotNetShoutout
Thank you for submitting this cool story - Trackback from DotNetShoutout

WebDevVote.com How to use an ASP.NET SiteMapProvider to produce a XML SiteMap

10/28/2009 02:57:21 by WebDevVote.com
You are voted (great) - Trackback from WebDevVote.com

Anthony  re: How to use an ASP.NET SiteMapProvider to produce a XML SiteMap for Google, Yahoo, Bing, etc
10/17/2009 17:32:01 by Anthony
You can use the new IIS SEO Toolkit to generate the sitemaps for you: http://weblogs.asp.net/gunnarpeipman/archive/2009/06/10/iis-seo-toolkit-sitemaps-overview.aspx

AK  re: How to use an ASP.NET SiteMapProvider to produce a XML SiteMap for Google, Yahoo, Bing, etc
05/05/2010 12:37:00 by AK
where am I supposed to put the asp.net code behind?

Leave a Comment

(required)
(required)
(optional, never published)
(optional)
(required)