Vulnerability in EPiServer.Forms

Try our conversational search powered by Generative AI!

Sanjay Kumar
Aug 2, 2020
  2242
(4 votes)

Exclusion of the partial routed folder/category from the Geta.Seo.Sitemaps

Purpose of the blog to exclude routed commerce catalog folder/category content Urls from the Geta.Seo.Sitemaps sitemap.xml before to it generates. This is out of box functionality in the current Geta.Seo.Sitemaps version thus we have customized it using the`CommerceSitemapXmlGenerator` or `CommerceAndStandardSitemapXmlGenerator` class in my current project for the solution.

Introduction:  This tool allows you to generate XML sitemaps for search engines to better index your EPiServer sites with some additional specific features.  

  • sitemap generation as a scheduled job
  • filtering pages by virtual directories
  • ability to include pages that are in a different branch than the one of the start page
  • ability to generate sitemaps for mobile pages
  • it also supports multi-site and multi-language environments

 

Problem: The Geta.Seo.Sitemaps is not able to avoid the 'Services' folder Urls from the sitemap.xml because the folder is partially routed using the IPartialRouter interface. And in the URLs, the folder name does not exist like https://www.xyz.com/services/laundry/dry-cleanhttps://www.xyz.com/service/laundary/normal-clean

However, the ServiceFolderPage is already inherited from IExcludeFromSitemap as below, but still not able to avoid/exclude content from the sitemap.xml.

public class ServiceFolderPage : NodeContent, IExcludeFromSitemap
{
}

Solution:  Avoid Urls e.g.  https://www.xyz.com/dry-cleanhttps://www.xyz.com/normal-clean

from the generated sitemap.xml because these are services folder content URLs.

1. Create a utility class like CustomCatalogUrlFilter and pass the current language content and avoid folders list into the IsUrlFiltered method.

   public class CustomCatalogUrlFilter
    {
        private readonly IContentLoader _contentLoader;

        public CustomCatalogUrlFilter(IContentLoader contentLoader)
        {
            _contentLoader = contentLoader ?? throw new ArgumentNullException(nameof(contentLoader));
        }

        /// <summary>
        /// Gets whether the current content should be filtered out of the Sitemap.
        /// </summary>
        public bool IsUrlFiltered(IContent page, IList<string> avoidPaths)
        {
            // If the inputs are bad, do nothing.
            if (page == null || avoidPaths?.Any() != true)
                return false;

            // Get the URL segments of the current page and all its ancestors.
            var ancestorsAndSelfRouteSegments =
                _contentLoader
                    .GetAncestorsAndSelf(page)
                    ?.OfType<IRoutable>()
                    .Select(x => x.RouteSegment)
                    .Where(x => string.IsNullOrWhiteSpace(x) == false)
                    .ToList();

            // If there are no route segments then something. Return false to be safe.
            if (ancestorsAndSelfRouteSegments?.Any() != true)
                return false;

            // Combine the route segments into a path:
            string pagePathUpper = string.Join("/", ancestorsAndSelfRouteSegments).ToUpperInvariant();

            // Check to see whether any path to avoid exists within the current page's path.
            foreach (string avoidPathUpper in avoidPaths)
            {
                if (string.IsNullOrWhiteSpace(avoidPathUpper))
                    continue;

                // If the page's path contains a path to avoid, then the page should be filtered out. Return true.
                if (pagePathUpper.Contains(avoidPathUpper.ToUpperInvariant()))
                    return true;
            }

            return false;
        }
    }

2. Create a custom sitemap XML generator class and derived from the`CommerceSitemapXmlGenerator` or `CommerceAndStandardSitemapXmlGenerator` and override `AddFilteredContentElement` method.

 public class CustomCommerceCatalogSitemapXmlGenerator : CommerceSitemapXmlGenerator
    {
        private readonly CustomCatalogUrlFilter _customCatalogUrlFilter;

        public CustomCommerceCatalogSitemapXmlGenerator(
            ISitemapRepository sitemapRepository,
            IContentRepository contentRepository,
            UrlResolver urlResolver,
            ISiteDefinitionRepository siteDefinitionRepository,
            ILanguageBranchRepository languageBranchRepository,
            ReferenceConverter referenceConverter,
            IContentFilter contentFilter,
            CustomUrlFilter customCatalogUrlFilter)
            : base(
                sitemapRepository,
                contentRepository,
                urlResolver,
                siteDefinitionRepository,
                languageBranchRepository,
                referenceConverter,
                contentFilter)
        {
            _customCatalogUrlFilter = customCatalogUrlFilter ?? throw new ArgumentNullException(nameof(customCatalogUrlFilter));
        }

        protected override void AddFilteredContentElement(CurrentLanguageContent languageContentInfo, IList<XElement> xmlElements)
        {
            if (ContentFilter.ShouldExcludeContent(languageContentInfo, SiteSettings, SitemapData))
            {
                return;
            }

            var content = languageContentInfo.Content;
            string url;

            var localizableContent = content as ILocalizable;

            if (localizableContent != null)
            {
                string language = string.IsNullOrWhiteSpace(this.SitemapData.Language)
                    ? languageContentInfo.CurrentLanguage.Name
                    : this.SitemapData.Language;

                url = this.UrlResolver.GetUrl(content.ContentLink, language);

                if (string.IsNullOrWhiteSpace(url))
                {
                    return;
                }

                // Make 100% sure we remove the language part in the URL if the sitemap host is mapped to the page's LanguageBranch.
                if (this.HostLanguageBranch != null && localizableContent.Language.Name.Equals(this.HostLanguageBranch, StringComparison.InvariantCultureIgnoreCase))
                {
                    url = url.Replace(string.Format("/{0}/", this.HostLanguageBranch), "/");
                }
            }
            else
            {
                url = this.UrlResolver.GetUrl(content.ContentLink);

                if (string.IsNullOrWhiteSpace(url))
                {
                    return;
                }
            }

            url = GetAbsoluteUrl(url);

            var fullContentUrl = new Uri(url);

            if (this.UrlSet.Contains(fullContentUrl.ToString()) || UrlFilter.IsUrlFiltered(fullContentUrl.AbsolutePath, this.SitemapData))
            {
                return;
            }

            // Custom code added to make sure Folder Pages are not ignored when handling paths to avoid:
            if (_customCatalogUrlFilter.IsUrlFiltered(content, this.SitemapData.PathsToAvoid))
                return;

            XElement contentElement = this.GenerateSiteElement(content, fullContentUrl.ToString());

            if (contentElement == null)
            {
                return;
            }

            xmlElements.Add(contentElement);
            this.UrlSet.Add(fullContentUrl.ToString());
        }
    }

Note: I am assuming the routing is already done for the folder/category content which you want to exclude from the sitemap.xml.

Enjoy!

Aug 02, 2020

Comments

Please login to comment.
Latest blogs
Stop Managing Humans in Your CMS

Too many times, a content management system becomes a people management system. Meaning, an organization uses the CMS to manage all the information...

Deane Barker | Nov 30, 2023

A day in the life of an Optimizely Developer - Optimizely CMS 12: The advantages and considerations when exploring an upgrade

GRAHAM CARR - LEAD .NET DEVELOPER, 28 Nov 2023 In 2022, Optimizely released CMS 12 as part of its ongoing evolution of the platform to help provide...

Graham Carr | Nov 28, 2023

A day in the life of an Optimizely Developer - OptiUKNorth Meetup January 2024

It's time for another UK North Optimizely meet up! After the success of the last one, Ibrar Hussain (26) and Paul Gruffydd (Kin + Carta) will be...

Graham Carr | Nov 28, 2023

Publish content to Optimizely CMS using a custom GPT from OpenAI 🤖

Do you find the traditional editor interface complicated and cluttered? Would you like an editorial AI assistant you can chat with? You can!

Tomas Hensrud Gulla | Nov 28, 2023 | Syndicated blog