At EPiServer Day 2009 I had the pleasure of entertaining a crowded room filled with the best developer brains in the community of developers working with EPiServer CMS. As promissed, I will use a couple of blog posts on providing the code we showed at the event.
First, I showed how to use the DCPlugin to make easy Dynamic Content out of User Controls. I already blogged about that, so I’ll let that be for now.
Later, it was time to turn geeky with some crazy page providers.
I based all my page providers on the MappedPageProvider.
Here’s the File System Provider:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using EPiServer.Core;
using EPiServer.Research.PageProviders;
namespace EPiServer.Templates.PageProvider
{
public class FileProvider : MappedPageProvider
{
private string rootFolder;
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
base.Initialize(name, config);
rootFolder = config["rootFolder"];
}
protected override List<string> GetRootChildren()
{
return Directory.GetFileSystemEntries(rootFolder).ToList();
}
protected override List<string> GetChildren(string Key)
{
if (Directory.Exists(Key))
{
return Directory.GetFileSystemEntries(Key).ToList();
}
else return new List<string>();
}
protected override EPiServer.Core.PageData GetPage(string Key)
{
PageData pd = new PageData();
string parentK = Path.GetDirectoryName(Key);
if (parentK == rootFolder) parentK = null;
FileSystemInfo fsi;
if (Directory.Exists(Key)) fsi = new DirectoryInfo(Key);
else fsi = new FileInfo(Key);
base.InitializePageData(pd, Key, Path.GetFileName(Key), parentK);
SetPageStatus(pd, VersionStatus.Published);
if (File.Exists(Key) && (Path.GetExtension(Key).ToLower().EndsWith("txt")))
{
StreamReader sr = File.OpenText(Key);
string s = sr.ReadToEnd();
pd.SetValue("MainBody","<pre>"+ s+"</pre>");
sr.Close();
} else pd.SetValue("MainBody", "Creation time: " + fsi.CreationTime.ToString() + "<br/>Last Access Time: " + fsi.LastAccessTime.ToString());
return pd;
}
public override string SaveNew(PageData page, string ParentKey, EPiServer.DataAccess.SaveAction action)
{
if (action == EPiServer.DataAccess.SaveAction.Publish)
{
string ParentDir = ParentKey;
if (ParentDir == null) ParentDir = rootFolder;
if (!Directory.Exists(ParentDir)) throw (new EPiServerException("Can't create this file"));
string filePath = ParentDir.TrimEnd('\\') + "\\" + page.PageName;
StreamWriter sw = File.CreateText(filePath);
sw.Write(page["MainBody"].ToString());
sw.Close();
return filePath;
}
return null;
}
protected override string GetPageType(string Key)
{
return "[Public] Standard page";
}
}
}
It’s set up in web.config like this:
<pageProvider>
<providers>
<add name="File" type="EPiServer.Templates.PageProvider.FileProvider,EPiServer.Templates.Public" entryPoint="28" rootFolder="d:\temp\" capabilities="Edit,Create" />
It works by using the path to the files as the unique key for the mappings. Make sure that the ASPNET / Network Service has read/write access to your root folder. Also, it uses the Standard page type from the default site – change that if needed.
After that part, I turned really geeky with the Page Provider To Admin mode…A page provider that exposes PageTypes, Categories and Tabs from Admin mode as page in edit-mode. Somewhat funny to work with a PageType that describes a PageType.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using EPiServer.Research.PageProviders;
using EPiServer.DataAbstraction;
using EPiServer.Core;
namespace EPiServer.Templates.PageProvider
{
public class CoreProvider : MappedPageProvider
{
protected override List<string> GetRootChildren()
{
return new List<string>() {"[PageTypes]","[Categories]","[Tabs]"};
}
protected override List<string> GetChildren(string Key)
{
List<string> rt = new List<string>();
switch (Key)
{
case "[PageTypes]":
rt.AddRange(PageType.List().Select(pt => "pt_" + pt.ID).ToArray());
break;
case "[Categories]":
rt.Add("ca_"+Category.GetRoot().ID.ToString());
break;
case "[Tabs]" :
rt.AddRange(TabDefinition.List().Select(td => "ta_" + td.ID).ToArray());
break;
}
if (Key.StartsWith("pt_"))
{
//List properties for a page
rt.AddRange(PageDefinition.List(int.Parse(Key.Substring(3))).Select(pd => "pd_" + pd.ID).ToArray());
}
else if (Key.StartsWith("ca_"))
{
Category c = Category.Find(int.Parse(Key.Substring(3)));
foreach (Category subC in c.Categories)
{
rt.Add("ca_" + subC.ID.ToString());
}
}
return rt;
}
protected override EPiServer.Core.PageData GetPage(string Key)
{
PageData pd = new PageData();
if (Key.StartsWith("["))
{
base.InitializePageData(pd, Key, Key, null);
}
else if (Key.StartsWith("pt_"))
{
//We have a page type
PageType pt=PageType.Load(int.Parse(Key.Substring(3)));
base.InitializePageData(pd, Key, pt.Name, "[PageTypes]");
pd["PageTypeDescription"] = pt.Description;
pd["Filename"] = pt.FileName;
}
else if (Key.StartsWith("pd_"))
{
//We have a page definition (property)
PageDefinition pdef = PageDefinition.Load(int.Parse(Key.Substring(3)));
base.InitializePageData(pd, Key,pdef.Name, "pt_"+pdef.PageTypeID.ToString());
pd["EditHeading"] = pdef.EditCaption;
pd["HelpText"] = pdef.HelpText;
pd["Tab"] = pdef.Tab.Name;
pd["Type"] = pdef.Type.Name;
}
else if (Key.StartsWith("ca_"))
{
Category c = Category.Find(int.Parse(Key.Substring(3)));
base.InitializePageData(pd, Key, c.Name, (c.Parent ==null)? "[Categories]":"ca_" + c.Parent.ID.ToString());
pd["Description"] = c.Description;
}
else if (Key.StartsWith("ta_"))
{
TabDefinition td = TabDefinition.Load(int.Parse(Key.Substring(3)));
base.InitializePageData(pd, Key, td.Name, "[Tabs]");
pd["MainBody"] = td.RequiredAccess.ToString();
}
pd.StartPublish = DateTime.Now;
base.SetPageStatus(pd, VersionStatus.Published);
//pd.ACL.Add(new EPiServer.Security.AccessControlEntry("Allan", EPiServer.Security.AccessLevel.FullAccess));
return pd;
}
protected override void SetCacheSettings(PageData page, CacheSettings cacheSettings)
{
base.SetCacheSettings(page, cacheSettings);
cacheSettings.CancelCaching = true;
}
protected override void SetCacheSettings(PageReference pageLink, PageReferenceCollection childrenReferences, CacheSettings cacheSettings)
{
base.SetCacheSettings(pageLink, childrenReferences, cacheSettings);
cacheSettings.CancelCaching = true;
}
public override void Save(PageData page, string Key, EPiServer.DataAccess.SaveAction action)
{
if (action == EPiServer.DataAccess.SaveAction.Publish)
{
PageType pt = PageType.Load(int.Parse(Key.Substring(3)));
pt.Description = page["PageTypeDescription"].ToString();
pt.Save();
}
}
protected override string GetPageType(string Key)
{
if (Key.StartsWith("pt_"))
{
return "[Core] PageType";
}
else if (Key.StartsWith("pd_"))
{
return "[Core] Property";
}
else if (Key.StartsWith("ca_"))
{
return "[Core] Category";
}
return "[Public] Standard page";
}
}
}
This needs to have a couple of new PageTypes defined.
Also, register it in web.config like this:
<add name="Core" type="EPiServer.Templates.PageProvider.CoreProvider,EPiServer.Templates.Public" entryPoint="30" capabilities="Edit,Create" />
Since it doesn’t really make sense to see “preview” of any pages of this type, you might want to disable preview entirely for them and instead show the edit-tab. This is done by this plugin:
using System;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Linq;
using EPiServer.Core; // addref: EPiServer.dll
using EPiServer.PlugIn; // addref: EPiServer.dll
using EPiServer.DataAbstraction;// addref: EPiServer.dll
using EPiServer.UI.Edit; // addref: EPiServer.UI.dll
using EPiServer.UI.WebControls; // addref: EPiServer.UI.dll
namespace EPiServer.CoreProvider
{
[GuiPlugIn(Area = PlugInArea.EditPanel)]
public class RemoveViewTab : ICustomPlugInLoader
{
public PlugInDescriptor[] List()
{
// hook LoadComplete-event on EditPanel page
EditPanel editPanel = HttpContext.Current.Handler as EditPanel;
if (null != editPanel)
{
//Only modify tabs when the page selected is of a specific type - in this case the types name starts with "[Core]".
if ((editPanel as PageBase).CurrentPage.PageTypeName.StartsWith("[Core]"))
{
editPanel.LoadComplete += new EventHandler(editPanel_LoadComplete);
}
}
//Never return a plugin - we don't want to add tabs.
return new PlugInDescriptor[0] { };
}
protected void editPanel_LoadComplete(object sender, EventArgs e)
{
// find the TabStrip with id = "actionTab"
TabStrip actionTabStrip = this.FindControl<TabStrip>(sender as Control, "actionTab");
//THIS IS WHERE YOU CAN DO WHATEVER YOU WANT TO THE TABS!
// remove View-tab and set active tab to Edit.
if(actionTabStrip.SelectedTab==0) actionTabStrip.SetSelectedTab(1);
((Tab)actionTabStrip.Controls[0]).Visible = false;
}
// try to locate control of type T with ID==id
// recurses into each childcontrol until first match is found
protected T FindControl<T>(Control control, string id) where T : Control
{
T controlTest = control as T;
if (null != controlTest && (null == id || controlTest.ID.Equals(id)))
return controlTest;
foreach (Control c in control.Controls)
{
controlTest = FindControl<T>(c, id);
if (null != controlTest)
return controlTest;
}
return null;
}
protected T FindControl<T>(Control control) where T : Control
{
return FindControl<T>(control, null);
}
}
}
Enjoy!
Recent posts