Главная > ASP.NET > Редактирование карты сайта Web.sitemap. How to edit Web.sitemap.

Редактирование карты сайта Web.sitemap. How to edit Web.sitemap.

Любой разработчик ASP.NET, причем не важно, будь то MVC или WebForms, знает про такой класс как SiteMap. Этот класс предоставляет большие возможности для навигации по сайту, он может быть использован как DataSource к TreeView или Menu. Я не буду рассказывать про то, как этим классом пользоваться, как, где, куда создавать и что записывать в Web.sitemap — об этом информации полно, лучше расскажу я про редактирование. В дальнейшем, говоря о карте сайта, я буду говорить про стандартный функционал ASP.NET, а не про что-либо еще.


По умолчанию карта сайта создается как обычный XML-файл, который называется Web.sitemap. В него заносятся ноды, соответствующие существующим урлам сайта, используя свойства и методы класса SiteMap, можно без проблем узнать свое текущее положение, дочерние и родительские ноды текущего узла и много другое. Все это очень удобно и очень просто, однако, рано или поздно появляется желание редактировать карту сайта программно, но оказывается, что такого функционала майкрософт не предоставил. Сейчас поясню. При старте приложения, среда из Web.sitemap строит карту сайта, происходит это единожды и только при старте приложения, это значит, что любые изменения, произведенные с файлом Web.sitemap вступят в силу лишь при перезагрузке сервера! Понятное дело, что создавая динамическую систему, такую карту сайта использовать нельзя. Пока я представляю себе два возможных решения этой проблемы: первый — создать свой собственный провайдер карты сайта, второй вариант — расковырять стандатный функционал. В отсутствие времени и желания изобретать велосипед, я расширю стандартный провайдер. Итак, поехали!

Созданная во время старта приложения карта сайта хранится в памяти. Становится очевидно, что необходимо каким-то образом установить зависимость между файлом Web.sitemap и кэшем, в этом нам поможет класс CacheDependency. Если поискать информацию, о том, как создать свой собственный провайдер карты сайта, то везде вы увидите, что нужно унаследоваться от абстрактного класса StaticSiteMapProvider, у которого придется переопределить несколько методов, среди которых нам интересны метод Initialize и метод BuildSiteMap. Метод Initialize вызывается единожды и загружает карту сайта в кэш, потому что повторная инициализация при каждом обращении слишком дорога в отношении ресурсов, метод BuildSiteMap вызывается при каждом обращении к карте сайта. Логично предположить, что в первом методе нам нужно установить зависимость, а во втором отслеживать изменения и предпринимать некие действия. Ниже я приведу кодину, но не полностью, там будут показаны только вышеназванные методы, потому что все остальное к редактированию карты сайта отношения не имеет.

    public class CustomSiteMapProvider : StaticSiteMapProvider
    {
        private CacheDependency cacheDependency;
        private SiteMapNode rootNode;
        private XElement rootSiteMapNode;
        private string siteMapFileName;
        private XDocument xmlSitemapXDoc;

        public override void Initialize(string name, NameValueCollection attributes)
        {
            base.Initialize(name, attributes);

            siteMapFileName = attributes["siteMapFileName"] ?? "~/Web.sitemap";

            InitSiteMap();

            HttpContext.Current.Cache.Insert("SiteMapFile", xmlSitemapXDoc, cacheDependency);
        }

        ... //Здесь оставшийся за кадром код.
        ...

        public override SiteMapNode BuildSiteMap()
        {
            lock (this)
            {
                if (!cacheDependency.HasChanged)
                {
                    return rootNode;
                }

                Clear();

                InitSiteMap();

                return rootNode;
            }
        }

        private void InitSiteMap()
        {
            xmlSitemapXDoc = XDocument.Load(HostingEnvironment.MapPath(siteMapFileName));
            cacheDependency = new CacheDependency(HostingEnvironment.MapPath(siteMapFileName), DateTime.Now);
            rootSiteMapNode = GetAllSiteMapNodesAfterMainParentNode();
            rootNode = AddNodeRecursive(rootSiteMapNode.GetXmlNode(), null);
        }
    }

Код, как мне кажется, в дополнительных комментариях не нуждается. Единственное, что он написан «на коленке», в появившиеся двадцать свободных минут, посему я с радостью приму в дар отреффакторенный вариант:).

Следует отметить, что для реализации подобного функционала на SQL-карте сайта можно использовать SqlDependency.

Жду комментариев.

Categories: ASP.NET Tags: , ,
  1. Пока что нет комментариев.
  1. Пока что нет уведомлений.