Allan Thraen
Jul 4, 2011
  6620
(2 votes)

Summer of Code: Update to the Mapped Page Provider

A lesson I’ve learned the hard way is that being product manager for a product like EPiServer CMS with thousands of dedicated developers and editors, your life tend to get rather busy. At least mine does. Dozens of meetings, presentations, customer interviews,  conferences, requirement docs and an obscene amount of travel days. And although it can be both rewarding and fun it’s not always as glamorous as it sounds Smile. This means that it’s been difficult to do all my usual “fun stuff” like coding open source projects and blogging about it – and I’ve sadly had to watch my status on the “Top Bloggers” board on EPiServer World go down. Obviously, I can’t have that – so in the hope that July means “Swedes are out of the office on strangely long vacations and I won’t be all that busy product manager’ing” I’ll now declare it the “Summer of Code” and start pushing out a series of blog posts with a lot of small goodies that I’ve had in mind for a long time. If you like me find yourself with a little time on your hand this July, bring your laptop out into the sun, fire up Visual Studio and join the Summer of Code. I’ll buy a cold beer to anyone who launches a cool, useful – and easily installable – module for EPiServer CMS this July. Don’t make me drink all the beers myself.

Todays’ effort included upgrading the Mapped Page Provider project to take advantage of the Dynamic Data Store – and wrap it in a nice little NuGet Package.
As you might recall, the Mapped Page Provider is a new base class to use when creating custom page providers, that makes it a lot easier to expose an existing data source as pages in the CMS. With the Mapped provider you don’t need to deal with all the nitty-gritty of Guids, ID’s, Urls, etc yourself – but rather just connect string-keys with home-brewed page-data objects.

A little while ago I was playing around trying to make a little source-code-browser (which might eventually be available if I manage to get the right political buy-in for it) and it seemed natural to expose the source-code copied to a VPP through a PageProvider in order to get nice looking urls – and easy navigation through the source. Using the Mapped Provider it didn’t take long to turn a VPP with source files into a PageTree in the CMS:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using EPiServer.Core;
using EPiServer.Research.PageProviders;
using EPiServer.Web.Hosting;
using System.Web.Hosting;
using System.IO;
 
namespace SourceCodeBrowser.PageProvider
{
    //A read-only page provider for source code - Browse either by file or by classes
    public class CodePageProvider : MappedPageProvider
    {
        protected static string rootpath = "/SourceCodeBrowser/Source/";
        protected static string[] allowedext = {".cs",".aspx",".ascx",".config",".js",".css" };
 
        protected override List<string> GetRootChildren()
        {
            //List Vpp root folder
            return GetChildren(rootpath);
        }
 
        protected override List<string> GetChildren(string Key)
        {
            //List children under a given VPP root
 
            //Leaf or not
            if (Key.EndsWith("/"))
            {
                var dir=VirtualPathHandler.Instance.GetDirectory(Key, true);
                var rt = dir.Directories.Cast<VirtualFileBase>().Select(vfb => vfb.VirtualPath).ToList();
                rt.AddRange(dir.Files.Cast<VirtualFileBase>()
                    .Where(vfb => allowedext.Contains(
                        VirtualPathUtility.GetExtension(vfb.VirtualPath.ToLower()))).Select(vfb => vfb.VirtualPath).ToList());
                return rt;
            }
            else return new List<string>();
 
        }
 
        protected override PageData GetPage(string Key)
        {
            PageData pd = new PageData();
            //Identify parent
 
            string parent = null;
            if(Key!=rootpath)  parent=VirtualPathUtility.GetDirectory(Key.TrimEnd('/'));
            if (parent == rootpath) parent = null;
            string nm=VirtualPathUtility.GetFileName(Key);
            InitializePageData(pd, Key, nm ?? Key, parent);
 
            if (Key.EndsWith("/"))
            {
                //Folder    
            }
            else
            {
                //File
                //Load file contents into property
                var f=VirtualPathHandler.Instance.GetFile(Key, true) as NativeFile;
                StreamReader read = new StreamReader(f.Open(System.IO.FileMode.Open, System.IO.FileAccess.Read));
                pd.SetValue("Code", read.ReadToEnd().Replace("<","&lt;").Replace(">","&gt;"));
                pd.SetValue("CodeType", VirtualPathUtility.GetExtension(Key).TrimStart('.'));
                read.Close();
                pd.SetValue("PageStartPublish", f.Changed);
            }
            return pd;
            
        }
 
        protected override string GetPageType(string Key)
        {
            return (Key.EndsWith("/")) ? "FolderPageType" : "CodePageType";
        }
    }
}

 

Summer of code

Other things lined up for this month (if time permits):

  • New NuGet version of the QuickWatchGadget (with dynamic code-execution)
  • A bunch of new Criteria for the CriteriaPack – including an XForms Criterion
  • Update to the MobilePack – maybe it’s time for v.1.0
  • Sharing some of the code I demoed at the US Partner Summit – like the Twitter Integration
  • A few new gadgets might also find their way to this blog
  • And a bunch of ‘secret’ stuff that I don’t want to share just yet Smile

 

Happy summer everybody!

Jul 04, 2011

Comments

Fredrik Josefsson
Fredrik Josefsson Jul 5, 2011 10:02 AM

Looking forward to your new blog posts :)

Please login to comment.
Latest blogs
CMS 13: The New Core Element of Your AI-First Optimizely Platform

CMS 13 is out and already brings solid AI-first foundations. With impressive features already shipped and an exciting roadmap ahead, this is the...

Michał Mitas | Apr 11, 2026 |

Deploying to Linux in SaaS (Configured) Commerce

With Optimizely SaaS (Configured) Commere now suporting net8.0 extensions dll, you will need to make a small tweak to how you distribute you...

Mark Hall | Apr 10, 2026 |

Optimizely CMS 13 and the Alloy demo site

The Alloy demo site now runs on Optimizely CMS 13. Here’s a quick guide to getting it up and running locally.

Tomas Hensrud Gulla | Apr 10, 2026 |

A day in the life of an Optimizely OMVP: Getting Up to Speed with Optimizely CMS 13 — A Free Learning Path

If you're working with Optimizely and haven't started exploring CMS 13 yet, now's the time. I've put together a dedicated CMS 13 course within the...

Graham Carr | Apr 10, 2026