Install EPiServer CMS 6
First of all we install a new EPiServer website using Deployment Manager:
We refrain from installing the Public Templates package, so after install this is our fancy start page:
The core install contains the following files (including default.htm which is the aforementioned fancy start page, but if you’re like me you’ll instantly delete it):
Set up the website project in Visual Studio
Create a project file for the EPiServer website
Next I want a Visual Studio solution for the project, so I create a new ASP.NET project in Visual Studio:
I only do this to quickly get my hands on a Visual Studio project file and assembly information file (AssemblyInfo.cs located in the Properties folder) to use for my EPiServer website (I delete the rest of the default files that come with setting up a new Web Application project):
Next we open up the new project file and remove the Default.aspx reference (since the file no longer exists in the project) and also the Scripts folder:
After deleting those we can toggle Show All Files to include the files that came with the EPiServer install:
Managing different build configurations
This doesn’t have anything to do with EPiServer Template Foundation, but I still think it’s important for EPiServer projects. We set up a separate [Configuration] folder with sub folders named according to the different build types in Visual Studio and then set up a pre-build event to copy files from the associated configuration folder to the root when compiling:
In ASP.NET 4 Visual Studio 2010 a new way of managing build-specific configuration files was introduced, but we’ll stick with our old proven way of accomplishing it this time. :)
Update: I just published a post explaining how config transforms can be used in Visual Studio 2010 to manage build-specific configurations, including EPiServer settings.
Add third-party assemblies
We put all third-party assemblies for EPiServer websites in a folder called [Library]. If you looked closely at the pre-build event above you noticed we copy these binaries to the bin folder before building:
Add MSBuild files
This isn’t required for EPiServer Template Foundation, but we put our MSBuild files in a folder called [MSBuild]. In it we put MSBuild configuration files and other resources such as libraries and executables required by the MSBuild scripts (for things such as minifying CSS and JavaScript files):
Add references to third-party assemblies
Next we’ll add references to required third-party assemblies, such as Page Type Builder. Note that we reference these assemblies from the [Library] folder:
Note though that we set Copy Local to false since we copy all our third-party assemblies through the pre-build event defined earlier:
We add references to the following assemblies:
- EPiServer Template Foundation (ETF)
- Page Type Builder (here’s an introduction to Page Type Builder)
- Castle.Core (required by PTB)
- Castle.DynamicProxy2 (required by PTB)
- EPiServer
- EPiServer.BaseLibrary
- EPiServer.Framework
- EPiServer.UI
- EPiServer.Web.WebControls
- System.ComponentModel.Composition (required by EPiServer.Framework)
- dotless.Core (if used for CSS parsing)
Add Template Foundation configuration elements
First we’ll add the DynamicImageProcessor section group to the <configSections> element:
<section name="DynamicImageProcessor" type="TemplateFoundation.Handlers.DynamicImageProcessor.ProcessorConfig" />
Next we’ll add the tag prefix for Template Foundation controls to the <controls> element:
<add tagPrefix="ETF" namespace="TemplateFoundation.WebControls" assembly="TemplateFoundation"/>
Next we’ll add some HTTP handlers that come with Template Foundation to the <handlers> element:
<add name="MetaWeblog" type="TemplateFoundation.MetaWeblog.MetaWeblogHandler" path="/metaweblog" verb="*" />
<add name="LiveWriterManifest" type="TemplateFoundation.MetaWeblog.ManifestHandler" path="/wlwmanifest.xml" verb="*" />
<add name="ReallySimpleDiscovery" type="TemplateFoundation.MetaWeblog.ReallySimpleDiscoveryHandler" path="/rsd.xml" verb="*" />
<add name="TemplateFoundationImagesLoader" type="TemplateFoundation.Handlers.EmbeddedImagesHandler" path="/TemplateFoundation/images/*" verb="GET"/>
<add name="TemplateFoundationHtmlLoader" type="TemplateFoundation.Handlers.EmbeddedHtmlHandler" path="/TemplateFoundation/*.html" verb="GET" />
<add name="PermanentLinksHandler" type="TemplateFoundation.Handlers.PermanentLinksHandler" path="/link/*" verb="*" />
Make sure you add these after any <clear/> element you might have in there!
We use the CSS parser in ETF (which utilizes dotLess) and we want a HTTP handler to manage CSS parsing while in development, but the pre-parsed minified CSS files when in production. So, we use these handlers for the Stylesheets folder where we keep all of our CSS files:
<location path="Templates/Stylesheets">
<system.webServer>
<handlers>
<!-- CSS parser used in development environment, production environment uses pre-parsed minified CSS files -->
<add name="CssParserProd" verb="GET,HEAD" path="*.min.css" type="EPiServer.Web.StaticFileHandler, EPiServer"/>
<add name="CssParserDev" verb="GET,HEAD" path="*.css" type="TemplateFoundation.Handlers.Css.CssParserHandler" />
<!-- End CSS parsed -->
</handlers>
</system.webServer>
</location>
The MasterPageBase renders different stylesheet and JavaScript links depending on the debug attribute in web.config:
When debug is set to true the non-minified versions are linked.
We want to use the DynamicImageProcessor for site graphics, so we add the handler for common graphics types:
<location path="Templates/Stylesheets/gfx">
<system.webServer>
<handlers>
<!-- Dynamic Image Processor -->
<add name="png" verb="GET,HEAD" path="*.png" type="TemplateFoundation.Handlers.DynamicImageProcessor.Processor" />
<add name="jpg" verb="GET,HEAD" path="*.jpg" type="TemplateFoundation.Handlers.DynamicImageProcessor.Processor" />
<add name="gif" verb="GET,HEAD" path="*.gif" type="TemplateFoundation.Handlers.DynamicImageProcessor.Processor" />
<!-- End of Dynamic Image Processor-->
</handlers>
</system.webServer>
</location>
Note: you could obviously add these handlers for other locations or paths, too. For example, you could add them to the “PageFiles” and “Global” locations to enable DynamicImageProcessor for images uploaded to the VPP.
Since DynamicImageProcessor used a file-based cache we need to specify which folder to use for the cache in web.config (note that we added the configuration section earlier):
<DynamicImageProcessor>
<Cache CacheDirectory="C:\Temp\dynamicimageprocessor-test" Enabled="true" />
</DynamicImageProcessor>
Create an EPiServer folder structure
We use a folder structure similar to that of the Public Templates package:
Setting the root as the start page
Because we didn’t install the Public Templates project we don’t have any content on our new EPiServer site. So, in order to be able to login we need to set the root page as the site’s start page inside episerver.config:
Oh, and while you’re in there, go ahead and change the display name so it doesn’t say PublicTemplates:
And finally, please replace the description so it doesn’t read “Example Site”! :)
Adjust the file paths for system page types
For some reason the file paths for the SysRoot and SysRecycleBin page types are incorrect after installing EPiServer. I manually edit these to include the /cms part of the path:
Adding master pages
All our master pages should inherit from MasterPageBase. So, we’ll create our master pages in the MasterPages folder…
…and make them inherit from MasterPageBase:
public partial class TwoColumns : MasterPageBase
{
}
Setting up basic EPiServer page types
If we go to admin mode we’ll see we only have the two basic system page types:
Next we’ll add Start Page and Standard Page page types using the Template Foundation base classes.
Create a base class for your templates
Before you start creating template pages you should create your own base class inheriting from TemplatePageBase and have your templates inherit that base class:
public class HemsoTemplatePage<T> : TemplatePageBase<T> where T : PageTypeBase
{
}
Note that the generic class has been fitted with a type constraint meaning the page templates need to be created for a page type class which derives from the PageTypeBase class in ETF.
Create the page type for the start page
We’ll create a new class called StartPage.cs:
We’ll make this class inherit the StartPageBase class, which is part of ETF:
[PageType]
public class StartPage : StartPageBase
{
}
If we reload admin mode we’ll see our new page type has appeared:
If we edit the StartPage page type we can see a number of page properties, including those used to specify the site settings required by ETF, such as these for specifying the page types used for person and RSS pages:
However, to have the page type map to the correct page template we’ll specify the Filename parameter of the PageType attribute:
[PageType(Filename = "/Templates/TemplatePages/StartPageTemplate.aspx")]
public class StartPage : StartPageBase
{
}
Next we’ll create a template page for the start page under the TemplatePages folder…
…and make it inherit from TemplatePageBase (or, preferably, the custom base class created for the project):
public partial class StartPageTemplate : TemplatePageBase<StartPage>
{
}
Note: we use the naming pattern PageTypeNameTemplate to avoid class name clashes between page types and their corresponding page templates.
Create the page type for standard pages
For the Standard Page page type we first create the page type definition under PageTypes…
…and we make it inherit from StandardPageBase (note that we’ve specified a few more parameters for the PageType attribute to make the page type appear nicer in edit mode):
[PageType(
Name = "Standard page",
Description = "Standard page template for editorial content",
Filename = "/Templates/TemplatePages/StandardPageTemplate.aspx")]
public class StandardPage : StandardPageBase
{
}
Next we’ll create its template page file under TemplatePages…
…and once again make the template inherit from TemplatePageBase, but this time for the StandardPage page type:
public partial class StandardPageTemplate : TemplatePageBase<StandardPage>
{
}
If we log in to admin mode we can see our StandardPage page type has a number of familiar page properties, such as Main body:
Configure language settings
Before creating any content, make sure you configure the language settings for the website:
Create start page
Create a start page under the root page:
Once you’ve published the start page make sure you set the pageStartId attribute in episerver.config to its page ID:
You’ll find the Page ID of the start page by hovering over it in the content tree:
Next we should specify some site settings by going to the Site settings tab of the start page, but before we do we need to create some additional page types.
Create page types for news
When publishing articles under the news container the pages are sorted into date folders. So, to create a news listing page we need the following page types:
- News container (our “News” page)
- Date listing (acts as date folders and also for listing articles for a given year or month)
- Tag listing (used for creating tag pages and also to list articles with a specific tag)
- Article
- RSS feed
We’ll create our page types and template much in the same way as we did before.
News container
The “News” page will be based on a page type called NewsListPage which in turn inherits ArticleContainerBase (the base class in ETF):
[PageType(
Name="News list",
Description = "Used to list the most recent news articles",
Filename = "/Templates/TemplatePages/NewsListPageTemplate.aspx")]
public class NewsListPage : ArticleContainerBase
{
}
Date listing
The page type used for date folders will be called ArticleDateListing and inherit the ETF base class ArticleDateListingBase:
[PageType(
Name="Date listing",
Description="Used to view a list of articles published in a specific year or month",
Filename = "/Templates/TemplatePages/ArticleDateListingTemplate.aspx")]
public class ArticleDateListing : ArticleDateListingBase
{
}
Tag listing
[PageType(
Name="Tag listing",
Description="Used to view a list of articles with a specific tag",
Filename = "/Templates/TemplatePages/ArticleTagListingTemplate.aspx")]
public class ArticleTagListing : ArticleTagListingBase
{
}
Article
The Article page type should inherit the ETF base class ArticleBase:
[PageType(
Name="Article",
Description = "Used to publish news articles",
Filename = "/Templates/TemplatePages/ArticlePageTemplate.aspx")]
public class ArticlePage : ArticleBase
{
}
RSS feed
We need a page type for RSS feeds, and we’ll create one called RssFeedPage inheriting RssPageBase:
[PageType(
Name="RSS feed",
Description = "Used to publish an RSS feed",
Filename = "/Templates/TemplatePages/RssFeedPageTemplate.aspx")]
public class RssFeedPage : RssPageBase
{
}
When we create the template page for the RSS page type we inherit the TemplateRssPageBase class:
public partial class RssFeedPageTemplate : TemplateRssPageBase { }
No markup is required in the code-front file, and no additional logic is required for an RSS feed listing articles.
Create a person page type
For features such as the Contact person property we need a page type for creating persons and specifying data such as name, e-mail address, phone number, etc.
We’ll create a page type called PersonPage and make it inherit PersonPageBase:
[PageType(
Name = "Person",
Description = "Used to store data about a contact person")]
public class PersonPage : PersonPageBase
{
}
We don’t specify the Filename parameter in this case since our person page won’t have any presentation – it’s simply used as a data container for person details.
Create the news container page
Using our NewsListPage page type we created earlier we’ll create a new page on the site (so we’ll have a page to specify as the news container among the site settings later).
Create the tags container page
We don’t have to use any specific page type for the tags container page, but we have to create a page under which all tag pages should be created.
Specify site settings
Now that we’ve created the page types and container pages we need we’ll specify some ETF settings through the Site settings tab by editing the start page:
Create some news articles
To create an article, simply right-click the news container page and create a new page of type Article:
When the new article page is created (or later published) it will be put in a date folder based on year and month (it looks at the StartPublish property):
Let’s create some additional articles for our upcoming news list:
Create a news list page
Now we can create a template for our NewsListPage page type. The template should list the most recent articles.
We’ll create a template called NewsListPageTemplate.aspx and insert a simple NewsList control:
<EPiServer:NewsList ID="news" runat="server">
<HeaderTemplate><div id="news-list"></HeaderTemplate>
<FooterTemplate></div></FooterTemplate>
<FirstNewsTemplate>
<div class="first">
<ETF:Property ID="Property1" PropertyName="PageStartPublish" DateFormat="d MMMM yyyy" ContainerElement="p" ContainerCssClass="date" runat="server" />
<ETF:Property ContainerElement="h2" PropertyName="Title" runat="server" />
<ETF:Property ContainerElement="p" ContainerCssClass="intro" PropertyName="Title" runat="server" />
</div>
</FirstNewsTemplate>
<NewsTemplate>
<ETF:Property PropertyName="PageStartPublish" DateFormat="d MMMM yyyy" ContainerElement="p" ContainerCssClass="date" runat="server" />
<ETF:Property ContainerElement="h2" PropertyName="Title" runat="server" />
<ETF:Property ContainerElement="p" ContainerCssClass="intro" PropertyName="Title" runat="server" />
</NewsTemplate>
</EPiServer:NewsList>
Note that we use the ETF version of the Property control which allows us to set which container element to use (instead of the standard <span>) and also to set the date format for DateTime-based properties.
In the code-behind file of our template we’ll simply bind the NewsList control to the 20 most recent articles by using the PageFactory class:
public partial class NewsListPageTemplate : TemplatePageBase<NewsListPage>
{
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
news.DataSource = PageFactory.Instance.GetArticles(20);
news.DataBind();
}
}
And that’s our basic news listing:
If we create a page on our site using the RSS feed page type we created earlier we’ll also have an RSS feed available.
I added some tags to one of the articles…
…and these are also included in the RSS feed:
Further reading
For an example where we add EPiServer Template Foundation to an existing website, see Introduction to EPiServer Template Foundation (which also covers how to publish posts and pages to your EPiServer site using Live Writer through the MetaWeblog API).
Upcoming blog posts
I’m working on a series of blog posts aimed at explaining additional features in EPiServer Template Foundation, such as:
- Publishing articles and pages using Windows Live Writer through the MetaWeblog API (there’s information
- Creating tag and date listings for articles
- Working with page tags
- Making use of the ETF Property control
- Overview of the PageFactory and Settings classes as well as available extension methods
- Using additional item templates with the ETF PageList control
- Creating rich UI custom properties using the UserControlPropertyBase class
- In-depth look at the MasterPageBase class
- Image resizing and cropping using DynamicImageProcessor
- Setting default page property values based on business logic (as opposed to constant default values set in page type definitions)
- Customizing RSS feeds
Feedback is much appreciated!
Feel free to post comments below or follow me on Twitter for any feedback or questions you might have!