EPiWiki.se  - EPiServer notes shared with others
 

Page provider initialization prototype for EPiServer CMS 5 R2

[Edit]
To initialize a page data object with a custom page provider you have to use a prototype pattern, otherwise will each page read from the database step the page folder once.
(On a CMS 6 version you will override AllocateUniquePageFolderId so it only updates the PageFolderId when a page are created)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using EPiServer;
using EPiServer.Core;
using EPiServer.Web;

namespace Development.PageProvider
{
    /// <summary>
    /// Page data prototype to initialize page data
    /// object without accessing the database.
    /// </summary>
    public class PageTypePrototype
    {
        private static Dictionary<string, object> _prototypeCache =
           new Dictionary<string, object>();

        private static readonly Regex regexFindInvalidUrlChars =
           new Regex(@"[^A-Za-z0-9\-_~]", RegexOptions.Compiled);

        /// <summary>
        /// Locking object for the initialize prototype.
        /// </summary>
        private static object _initializePrototypeLockObject =
           new object();

        /// <summary>
        /// Initialize a page data object using a prototype so the
        /// database isn't called for each fetching of pages from the
        /// database.
        /// </summary>
        /// <param name="pageData">The page data object to initialize.</param>
        /// <param name="entity">The entity object to create the PageData bojeck with.</param>
        /// <param name="pageLink">The link to the page.</param>
        /// <param name="parentLink">Link to the parent page.</param>
        public static void InitializePageData(
           PageProviderBase adapter,
           PageData pageData,
           string name,
           string pageTypeName,
           Guid guid,
           PageReference pageLink,
           PageReference parentLink)
        {
            if (!_prototypeCache.ContainsKey(pageTypeName))
            {
                lock (_initializePrototypeLockObject)
                {
                    if (!_prototypeCache.ContainsKey(pageTypeName))
                    {
                        PageData prototype = new PageData();
                        adapter.InitializePageData(
                                prototype,
                                       name,
                                       pageTypeName,
                                       guid,
                                       pageLink,
                                       parentLink,
                                       new List<string>());
                        
                        // This has to be done sense a page access
                        // can result in a get page
                        if (!_prototypeCache.ContainsKey(pageTypeName))
                        {
                            _prototypeCache.Add(pageTypeName, prototype);
                        }
                    }
                }
            }
            PageData initializePrototype =
                _prototypeCache[pageTypeName] as PageData;

            PropertyDataCollection extraProperties =
                pageData.Property.Copy();
            pageData.Property.Clear();
            for (int i = 0; i < initializePrototype.Property.Count; i++)
            {
                pageData.Property.Add(initializePrototype.Property[i].Copy());
            }

            foreach (PropertyData pd in extraProperties)
            {
                if (pageData.Property[pd.Name] == null)
                {
                    pageData.Property.Add(pd);
                }
                else
                {
                    pageData.Property[pd.Name] = pd;
                }
            }

            pageData[Const.Property.PageLink] =
               pageLink.CreateWritableClone();
            pageData[Const.Property.PageParentLink] =
               parentLink.CreateWritableClone();
            pageData[Const.Property.PageName] = name;
            pageData[Const.Property.PageGuid] = guid;
            pageData.StartPublish =
               EPiServer.BaseLibrary.Context.Current.RequestTime;
            pageData.URLSegment = SimpleUrlSegment(name);
            UrlBuilder urlBuilder =
               new UrlBuilder(initializePrototype.LinkURL);
            
            pageData.LinkURL = ParmanentLink.Create(guid, ".aspx");
            foreach (var acl in initializePrototype.ACL)
            {
                if (!pageData.ACL.Exists(acl.Value.Name))
                {
                    pageData.ACL.Add(acl.Value);
                }
            }
            pageData.ACL.Creator = initializePrototype.ACL.Creator;

            pageData.InitializeData(initializePrototype.PageLanguages.ToList());
        }

        /// <summary>
        /// Creates a URLSegment from a page name, without checking if the segment already exists.
        /// </summary>
        /// <param name="pagename">Page name to create URLSegment for</param>
        /// <returns>A (possible) URL Segment for a page.</returns>
        public static string SimpleUrlSegment(string pageName)
        {
            StringBuilder ret = new StringBuilder(pageName);
            MatchCollection coll =
               regexFindInvalidUrlChars.Matches(pageName);
            for (int i = 0; i < coll.Count; i++)
            {
                object newChar =
                   UrlSegment.URLCharacterMap[ret[coll[i].Index]];
                ret[coll[i].Index] = newChar != null ? (char)newChar : '?';
            }
            ret.Replace("?", String.Empty);

            return ret.ToString();
        }
    }
}


Version author:
Mattias Lövström

EPiServer version

'CMS 5 R2'