Created
April 22, 2016 18:05
-
-
Save davidsekar/c82e8be66b371929ba1b094a8f1cf7bd to your computer and use it in GitHub Desktop.
Sitefinity – Create dynamic sitemap XML
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protected void Application_BeginRequest(object sender, EventArgs e) | |
{ | |
string strUrl = Request.Path.ToLowerInvariant(); | |
//Code block to redirect the generic request to the correct sitemap index and sitemap XML | |
if (new Regex(@"^/sitemap\.xml", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant).IsMatch(Request.Path)) | |
HttpContext.Current.RewritePath("/sitemap.ashx"); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%@ WebHandler Language="C#" Class="Sitemap" %> | |
using System; | |
using System.Text; | |
using System.Web; | |
using System.Xml; | |
using System.Linq; | |
using Telerik.Sitefinity; | |
using Telerik.Sitefinity.Modules.Pages; | |
using Telerik.Sitefinity.Multisite; | |
using Telerik.Sitefinity.Services; | |
using System.Globalization; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Web.Caching; | |
public class AltInfo | |
{ | |
public string LangName { get; set; } | |
public string Link { get; set; } | |
} | |
public class Sitemap : IHttpHandler | |
{ | |
// global properties | |
protected string host; | |
private const string sitemapKey = "customsitemap"; | |
/// <summary> | |
/// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler" /> interface. | |
/// </summary> | |
/// <param name="context">An <see cref="T:System.Web.HttpContext" /> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param> | |
public void ProcessRequest(HttpContext context) | |
{ | |
try | |
{ | |
// prepare response type | |
var response = context.Response; | |
response.ContentType = "text/xml"; | |
var multisiteContext = SystemManager.CurrentContext as MultisiteContext; | |
string currrentSitemapKey = sitemapKey + multisiteContext.CurrentSite.Id; | |
string sSitemap = string.Empty; | |
if (HttpRuntime.Cache[currrentSitemapKey] == null) | |
{ | |
lock (currrentSitemapKey) | |
{ | |
if (HttpRuntime.Cache[currrentSitemapKey] == null) | |
{ | |
using (MemoryStream memoryStream = new MemoryStream()) | |
{ | |
using (var writer = new XmlTextWriter(memoryStream, Encoding.UTF8){ Formatting = Formatting.Indented })// begin xml response | |
{ | |
writer.WriteStartDocument(); | |
writer.WriteStartElement("urlset"); | |
writer.WriteAttributeString("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); | |
writer.WriteAttributeString("xsi:schemaLocation", "http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"); | |
writer.WriteAttributeString("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9"); | |
writer.WriteAttributeString("xmlns:xhtml", "http://www.w3.org/1999/xhtml"); | |
var vars = HttpContext.Current.Request.ServerVariables; | |
string port; | |
// parse content | |
using (var api = App.WorkWith()) | |
{ | |
string defaultCultureName = multisiteContext.CurrentSite.DefaultCulture; | |
CultureInfo defCulture = new CultureInfo(defaultCultureName); | |
var allCultures = multisiteContext.CurrentSite.PublicContentCultures.Where(c => c.Name != defaultCultureName).ToList(); | |
allCultures.Insert(0, new CultureInfo(defaultCultureName)); | |
var rId = multisiteContext.CurrentSite.SiteMapRootNodeId; | |
// append pages | |
var pages = api.Pages().ThatArePublished().Where(p => p.ShowInNavigation == true && p.Crawlable && !p.IsBackend && p.NodeType == Telerik.Sitefinity.Pages.Model.NodeType.Standard && p.RootNodeId == rId).Get(); | |
foreach (var page in pages) | |
{ | |
string defaultUrl = null; | |
DateTime lastMod = DateTime.Now; | |
List<AltInfo> altInfo = new List<AltInfo>(); | |
{ | |
var pData = page.GetPageData(defCulture); | |
if (pData != null) | |
{ | |
// build host | |
var protocol = pData.NavigationNode.RequireSsl ? "https://" : "http://"; | |
// append port | |
port = pData.NavigationNode.RequireSsl ? "443" : vars["SERVER_PORT"]; | |
if (port == "80" || port == "443") | |
port = string.Empty; | |
else | |
port = string.Concat(":", port); | |
defaultUrl = string.Concat(protocol, vars["SERVER_NAME"], port, VirtualPathUtility.ToAbsolute(page.GetFullUrl())); | |
lastMod = pData.LastModified; | |
} | |
} | |
foreach (var culture in allCultures) | |
{ | |
if (page.AvailableCultures.Contains(culture)) | |
{ | |
var pData = page.GetPageData(culture); | |
if (pData != null) | |
{ | |
// build host | |
var protocol = pData.NavigationNode.RequireSsl ? "https://" : "http://"; | |
// append port | |
port = pData.NavigationNode.RequireSsl ? "443" : vars["SERVER_PORT"]; | |
if (port == "80" || port == "443") | |
port = string.Empty; | |
else | |
port = string.Concat(":", port); | |
var url = string.Concat(protocol, vars["SERVER_NAME"], port, VirtualPathUtility.ToAbsolute(page.GetFullUrl(culture, false))); | |
altInfo.Add(new AltInfo() { LangName = culture.Name, Link = url }); | |
} | |
} | |
} | |
// append page to sitemap | |
this.AppendUrl(writer, defaultUrl, lastMod, altInfo); | |
} | |
} | |
writer.WriteEndElement(); | |
writer.WriteEndDocument(); | |
writer.Flush(); | |
} | |
sSitemap = Encoding.UTF8.GetString(memoryStream.ToArray()); | |
HttpRuntime.Cache.Add(currrentSitemapKey, sSitemap, null, DateTime.Now.AddHours(12), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); | |
} | |
} | |
else | |
sSitemap = HttpRuntime.Cache[currrentSitemapKey] + ""; | |
} | |
} | |
else | |
sSitemap = HttpRuntime.Cache[currrentSitemapKey] + ""; | |
response.Write(sSitemap); | |
response.Flush(); | |
} | |
catch (Exception ex) | |
{ | |
Elmah.ErrorSignal.FromCurrentContext().Raise(ex); | |
} | |
} | |
private void AppendUrl(XmlTextWriter writer, string fullUrl, DateTime lastModified, List<AltInfo> altUrls) | |
{ | |
// calculate change frequency | |
string changeFreq = "monthly"; | |
var changeInterval = (DateTime.Now - lastModified).Days; | |
if (changeInterval <= 1) | |
changeFreq = "daily"; | |
else if (changeInterval <= 7 & changeInterval > 1) | |
changeFreq = "daily"; | |
else if (changeInterval <= 30 & changeInterval > 7) | |
changeFreq = "weekly"; | |
else if (changeInterval <= 30 & changeInterval > 365) | |
changeFreq = "weekly"; | |
// append to sitemap | |
writer.WriteStartElement("url"); | |
writer.WriteElementString("loc", fullUrl); | |
writer.WriteElementString("lastmod", lastModified.ToString("yyyy-MM-ddThh:mm:sszzzz")); | |
writer.WriteElementString("changefreq", changeFreq); | |
writer.WriteElementString("priority", "1"); | |
foreach (var xhtml in altUrls) | |
{ | |
writer.WriteStartElement("xhtml:link"); | |
writer.WriteAttributeString("rel", "alternate"); | |
writer.WriteAttributeString("hreflang", xhtml.LangName); | |
writer.WriteAttributeString("ref", xhtml.Link); | |
writer.WriteEndElement(); | |
} | |
writer.WriteEndElement(); | |
} | |
public bool IsReusable | |
{ | |
get { return true; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi,
Thanks for this, I have 2 additions to code:
Method can be then used even in singlesite configuration.
writer.WriteElementString("lastmod", lastModified**.ToLocalTime()**.ToString("yyyy-MM-ddThh:mm:sszzzz"));