Part 2: Creating a foundation – Create an EPiServer site from scratch

Posted on December 7, 2009 by Frederik Vig in EPiServer

In this part we’re going to build our sites foundation. The first thing we’re going to do is take a look at the ready made template that we’re tasked with implementing. This is the template that we’re going to implement: Jungleland. Go over and take a look at it, click a little around, and make yourself familiar with it.

This is where Firebug comes in. It allows us to easily inspect any element, and see where in the HTML structure we are. I usually start out with this on a new project, to get a feeling of how the HTML is structured, which will help is when we’re implementing it later on.

Getting started

Let’s download the files, unzip, and open the folder. Also make sure that you have your Visual Studio project open (see the Part 1: Setting up the development environment for more information). We’re now going to drag the CSS files into our Styles folder in Visual Studio.

Next up are the images. Open up the images folder and drag all the files into your Images folder.

Masterpage

Create a new masterpage by right-clicking the MasterPages folder, and choosing Add Item. Choose MasterPage and give it a name of Site.master.

Create a new Master Page

Lets delete all the HTML code, and instead copy all the code from the file style.html.

In the masterpage we’re placing everything that is common in most of our page templates. Lets delete all the code inside <div id=”main”>. You should now have something like this:

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="Jungle.Templates.Jungle.MasterPages.Site" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 
<head>
 
<title>Jungleland</title>
 
<meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8" />
<meta name="author" content="Erwin Aligam - styleshout.com" />
<meta name="description" content="Site Description Here" />
<meta name="keywords" content="keywords, here" />
<meta name="robots" content="index, follow, noarchive" />
<meta name="googlebot" content="noarchive" />
 
<link rel="stylesheet" type="text/css" media="screen" href="css/screen.css" />
<!--[if IE 6]><link rel="stylesheet" type="text/css" href="css/ie6.css" media="screen" /><![endif]-->
 
</head>
 
<body>
 
<!-- wrap -->
<div id="wrap">
 
	<!-- header -->
	<div id="header">			
 
		<a name="top"></a>
 
		<h1 id="logo-text"><a href="index.html" title="">jungleland</a></h1>		
		<p id="slogan">Just Another Styleshout CSS Template... </p>					
 
		<div  id="nav">
			<ul>
				<li><a href="index.html">Home</a></li>
				<li id="current"><a href="style.html">Style Demo</a></li>
				<li><a href="blog.html">Blog</a></li>
				<li><a href="archives.html">Archives</a></li>
				<li><a href="index.html">Support</a></li>
				<li><a href="index.html">About</a></li>		
			</ul>		
		</div>		
 
		<p id="rss-feed"><a href="index.html" class="feed">Grab the RSS FEEd</a></p>	
 
		<form id="quick-search" action="index.html" method="get" >
			<p>
			<label for="qsearch">Search:</label>
			<input class="tbox" id="qsearch" type="text" name="qsearch" value="Search..." title="Start typing and hit ENTER" />
			<input class="btn" alt="Search" type="image" name="searchsubmit" title="Search" src="images/search.png" />
			</p>
		</form>	
 
	<!-- /header -->					
	</div>
 
	<!-- content -->
	<div id="content-wrap" class="clear">
 
		<div id="content">		
 
			<!-- main -->
			<div id="main">	
 
			<!-- /main -->	
			</div>
 
			<!-- sidebar -->
			<div id="sidebar">
 
				<div class="sidemenu">	
					<h3>Sidebar Menu</h3>
					<ul>				
						<li><a href="index.html">Home</a></li>
						<li><a href="index.html#TemplateInfo">TemplateInfo</a></li>
						<li><a href="style.html">Style Demo</a></li>
						<li><a href="blog.html">Blog</a></li>
						<li><a href="archives.html">Archives</a></li>
						<li><a href="http://www.styleshout.com/">More Free Templates</a></li>	
						<li><a href="http://www.4templates.com/?aff=ealigam">Premium Templates</a></li>	
					</ul>	
				</div>
 
				<div class="sidemenu">
					<h3>Sponsors</h3>
					<ul>
						<li><a href="http://themeforest.net?ref=ealigam">ThemeForest</a><span>Your Choice for Site Templates, Wordpress, Joomla and CMS Themes</span></li>
						<li><a href="http://www.4templates.com/?aff=ealigam">4templates</a><span>Low Cost Hi-Quality Templates</span></li>
						<li><a href="http://store.templatemonster.com?aff=ealigam">TemplateMonster</a><span>Delivering the Best Templates on the Net!</span></li>
						<li><a href="http://tinyurl.com/3cgv2m">Text Link Ads</a><span>Monetized your website</span></li>
						<li><a href="http://www.fotolia.com/partner/114283">Fotolia</a><span>Free stock images or from $1</span></li>
						<li><a href="http://www.dreamhost.com/r.cgi?287326">Dreamhost</a><span>Premium webhosting</span></li>
					</ul>
				</div>		
 
				<h3>Image Gallery </h3>					
 
				<p class="thumbs">
					<a href="index.html"><img src="images/thumb.jpg" width="40" height="40" alt="thumbnail" /></a>
					<a href="index.html"><img src="images/thumb.jpg" width="40" height="40" alt="thumbnail" /></a>
					<a href="index.html"><img src="images/thumb.jpg" width="40" height="40" alt="thumbnail" /></a>
					<a href="index.html"><img src="images/thumb.jpg" width="40" height="40" alt="thumbnail" /></a>
					<a href="index.html"><img src="images/thumb.jpg" width="40" height="40" alt="thumbnail" /></a>
					<a href="index.html"><img src="images/thumb.jpg" width="40" height="40" alt="thumbnail" /></a>	
					<a href="index.html"><img src="images/thumb.jpg" width="40" height="40" alt="thumbnail" /></a>
					<a href="index.html"><img src="images/thumb.jpg" width="40" height="40" alt="thumbnail" /></a>				
				</p>					
 
			<!-- /sidebar -->				
			</div>		
 
		<!-- /content -->	
		</div>				
	<!-- /content-wrap -->	
	</div>	
<!-- /wrap -->
</div>
 
<!-- footer -->	
<div id="footer">	
 
	<!-- footer-outer -->	
	<div id="footer-outer" class="clear"><div id="footer-wrap">
 
		<div class="col-a">
 
			<h3>Contact Info</h3>
 
			<p>
			<strong>Phone: </strong>+1234567<br/>
			<strong>Fax: </strong>+123456789
			</p>
 
			<p><strong>Address: </strong>123 Put Your Address Here</p>
 
			<p><strong>E-mail: </strong>me@jungleland.com</p>
			<p>Want more info - go to our <a href="#">contact page</a></p>			
 
			<h3>Follow Us</h3>
 
			<div class="footer-list">
				<ul>				
					<li><a href="index.html" class="rssfeed">RSS Feed</a></li>
					<li><a href="index.html" class="email">Email</a></li>
					<li><a href="index.html" class="twitter">Twitter</a></li>									
				</ul>
			</div>					
 
		</div>
 
		<div class="col-a">			
 
			<h3>Site Links</h3>
 
			<div class="footer-list">
				<ul>				
					<li><a href="index.html">Home</a></li>
					<li><a href="index.html">Style Demo</a></li>
					<li><a href="index.html">Blog</a></li>
					<li><a href="index.html">Archive</a></li>
					<li><a href="index.html">About</a></li>		
					<li><a href="index.html">Template Info</a></li>		
					<li><a href="index.html">Site Map</a></li>					
				</ul>
			</div>					
 
		</div>
 
		<div class="col-a">
 
			<h3>Web Resource</h3>
 
			<p>Morbi tincidunt, orci ac convallis aliquam, lectus turpis varius lorem, eu 
			posuere nunc justo tempus leo. </p>
 
			<div class="footer-list">
				<ul>				
					<li><a href="http://net.tutsplus.com/">NetTuts</a></li>
					<li><a href="http://www.smashingmagazine.com/">Smashing Magazine</a></li>
					<li><a href="http://psd.tutsplus.com/">PSDTuts</a></li>
					<li><a href="http://www.tutorial9.net/">Tutorial9</a></li>
					<li><a href="http://www.webdesignerwall.com/">Web Designer Wall</a></li>		
					<li><a href="http://bestwebgallery.com/">Best Web Gallery</a></li>		
					<li><a href="http://webcreme.com/">Web Creme</a></li>	
					<li><a href="http://cssmania.com/">CSS Mania</a></li>	
				</ul>
			</div>			
 
		</div>		
 
		<div class="col-b">
 
			<h3>About</h3>			
 
			<p>
			<a href="index.html"><img src="images/gravatar.jpg" width="40" height="40" alt="firefox" class="float-left" /></a>
			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec libero. Suspendisse bibendum. 
			Cras id urna. Morbi tincidunt, orci ac convallis aliquam, lectus turpis varius lorem, eu 
			posuere nunc justo tempus leo. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec libero. Suspendisse bibendum. 
			Cras id urna. <a href="index.html">Learn more...</a></p>			
 
		</div>		
 
		<div class="fix"></div>
 
		<!-- footer-bottom -->		
		<div id="footer-bottom">
 
			<div class="bottom-left">
				<p>
				&copy; 2009 <strong>Copyright Info Here</strong>&nbsp; &nbsp; &nbsp;
				Design by: <a href="http://www.styleshout.com/">styleshout</a> 			
				</p>
			</div>		
 
			<div class="bottom-right">
				<p>		
					<a href="http://jigsaw.w3.org/css-validator/check/referer">CSS</a> | 
		   		<a href="http://validator.w3.org/check/referer">XHTML</a>	|			
					<a href="index.html">Home</a> |
					<strong><a href="#top" class="back-to-top">Back to Top</a></strong>								
				</p>
			</div>
 
		<!-- /footer-bottom -->		
		</div>
 
	<!-- /footer-outer -->		
	</div></div>		
 
<!-- /footer -->
</div>
 
</body>
</html>

That’s better! I usually start at the top and work my way down. Lets do that now. The doctype is XHTML strict, that’s fine, but we have to add a few configuration settings to our web.config file to make the ASP.NET controls render in that mode (default is transitional). Open up web.config and add this code right inside system.web:

<system.web>
      <xhtmlConformance mode="Strict" />
      <browserCaps>
          <case match="W3C_Validator*">
            TagWriter = System.Web.UI.HtmlTextWriter
            W3CDomVersion = 1.0
          </case>
      </browserCaps>
...

Lets continue with Site.master by adding a server side form tag right inside <body> and before </body>.

...
<body>
<form runat="server">
...
</form>
</body>
</html>

Create a new user control, by right-clicking Units and choosing Add Item. Name it Header.ascx and cut/paste the meta and link code from the head section of Site.master into Header.ascx. Register Header.ascx in Site.master and add it inside the head element.

...
<%@ Register TagPrefix="Jungle" TagName="Header" Src="~/Templates/Jungle/Units/Header.ascx" %>
...
<head>
    <title>Jungleland</title>
 
    <Jungle:Header runat="server" />
</head>
...

Now add the runat=”server” attribute to the head and title elements, and remove the title text. Last thing now is to add runat=”server to the html element and give it an id of HtmlElement.

You should have something like this now.

...
<html xmlns="http://www.w3.org/1999/xhtml" runat="server" id="HtmlElement">
 
<head runat="server">
    <title runat="server"></title>
 
    <Jungle:Header runat="server" />
</head>
...

Go to Site.masters code-behind file and add this code.

using System;
using System.Web.UI;
using EPiServer;
 
namespace Jungle.Templates.Jungle.MasterPages
{
    public partial class Site : MasterPage
    {
        private const string _title = "{0}{1}{2}";
        private string _titleSeparator = " - ";
 
        /// <summary>
        /// Gets or sets the title separator.
        /// </summary>
        public string TitleSeparator
        {
            get { return _titleSeparator; }
            set { _titleSeparator = value; }
        }
 
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
 
            var page = (PageBase)Page;
            Page.Title = string.Format(_title, page.CurrentPage.Property["PageName"].ToWebString(), TitleSeparator, EPiServer.Configuration.Settings.Instance.SiteDisplayName);
 
            this.HtmlElement.Attributes["lang"] = page.CurrentPage.LanguageBranch;
        }
    }
}

Create a new user control called PageHeader.ascx (inside Units), cut/paste the <div id=”header”> from Site.master, and everything inside it. Register and add it to Site.master (same as we did with Header.ascx). Now do the same with the footer, name it PageFooter.ascx and cut/paste <div id=”footer”>…</div>.

Your Site.master file should now look like this:

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="Jungle.Templates.Jungle.MasterPages.Site" %>
<%@ Register TagPrefix="Jungle" TagName="Header" Src="~/Templates/Jungle/Units/Header.ascx" %>
<%@ Register TagPrefix="Jungle" TagName="PageHeader" Src="~/Templates/Jungle/Units/PageHeader.ascx" %>
<%@ Register TagPrefix="Jungle" TagName="PageFooter" Src="~/Templates/Jungle/Units/PageFooter.ascx" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" runat="server" id="HtmlElement">
 
<head runat="server">
    <title runat="server"></title>
 
    <Jungle:Header runat="server" />
</head>
 
<body>
<form runat="server">
<!-- wrap -->
<div id="wrap">
 
	<!-- header -->
	<Jungle:PageHeader runat="server" />
 
	<!-- content -->
	<div id="content-wrap" class="clear">
 
		<div id="content">		
 
			<!-- main -->
			<div id="main">	
 
			<!-- /main -->	
			</div>
 
			<!-- sidebar -->
			<div id="sidebar">
 
				<div class="sidemenu">	
					<h3>Sidebar Menu</h3>
					<ul>				
						<li><a href="index.html">Home</a></li>
						<li><a href="index.html#TemplateInfo">TemplateInfo</a></li>
						<li><a href="style.html">Style Demo</a></li>
						<li><a href="blog.html">Blog</a></li>
						<li><a href="archives.html">Archives</a></li>
						<li><a href="http://www.styleshout.com/">More Free Templates</a></li>	
						<li><a href="http://www.4templates.com/?aff=ealigam">Premium Templates</a></li>	
					</ul>	
				</div>
 
				<div class="sidemenu">
					<h3>Sponsors</h3>
					<ul>
						<li><a href="http://themeforest.net?ref=ealigam">ThemeForest</a><span>Your Choice for Site Templates, Wordpress, Joomla and CMS Themes</span></li>
						<li><a href="http://www.4templates.com/?aff=ealigam">4templates</a><span>Low Cost Hi-Quality Templates</span></li>
						<li><a href="http://store.templatemonster.com?aff=ealigam">TemplateMonster</a><span>Delivering the Best Templates on the Net!</span></li>
						<li><a href="http://tinyurl.com/3cgv2m">Text Link Ads</a><span>Monetized your website</span></li>
						<li><a href="http://www.fotolia.com/partner/114283">Fotolia</a><span>Free stock images or from $1</span></li>
						<li><a href="http://www.dreamhost.com/r.cgi?287326">Dreamhost</a><span>Premium webhosting</span></li>
					</ul>
				</div>		
 
				<h3>Image Gallery </h3>					
 
				<p class="thumbs">
					<a href="index.html"><img src="images/thumb.jpg" width="40" height="40" alt="thumbnail" /></a>
					<a href="index.html"><img src="images/thumb.jpg" width="40" height="40" alt="thumbnail" /></a>
					<a href="index.html"><img src="images/thumb.jpg" width="40" height="40" alt="thumbnail" /></a>
					<a href="index.html"><img src="images/thumb.jpg" width="40" height="40" alt="thumbnail" /></a>
					<a href="index.html"><img src="images/thumb.jpg" width="40" height="40" alt="thumbnail" /></a>
					<a href="index.html"><img src="images/thumb.jpg" width="40" height="40" alt="thumbnail" /></a>	
					<a href="index.html"><img src="images/thumb.jpg" width="40" height="40" alt="thumbnail" /></a>
					<a href="index.html"><img src="images/thumb.jpg" width="40" height="40" alt="thumbnail" /></a>				
				</p>					
 
			<!-- /sidebar -->				
			</div>		
 
		<!-- /content -->	
		</div>				
	<!-- /content-wrap -->	
	</div>	
<!-- /wrap -->
</div>
 
<!-- footer -->	
<Jungle:PageFooter runat="server" />
</form>
</body>
</html>

Much smaller, cleaner and more manageable :).

External projects

We need to add two external projects to our project. EPiCode.Extensions and PageTypeBuilder. EPiCode.Extensions consists of a set of extension methods that’ll help us code. Page Type Builder is a project that helps us with strongly typed EPiServer property access and more. For more information about EPiCode.Extensions see my blog post: EPiCode.Extensions new EPiCode Community Project, for more information on the Page Type Builder project see the projects home page. Especially be sure to read through the introduction posts on the Page Type Builder project. We’re going to use both projects throughout this series.

We have a problem though, since our projects root folder is also the sites root folder, everything we add will be accessible through our web application (not what we want!).

Lets clean up a little by placing everything except JungleSite.sln into a new folder called wwwroot (placed inside the JungleSite folder).

Update IIS to point to wwwroot instead, by right clicking the JungleSite in IIS, choosing Manage Web Site, and Advanced Settings (for IIS 7), update the physical path by adding wwwroot.

Back in our JungleSite folder we can now create two new folders: References and External. References will have all the compiled assemblies (.dll files) that we use, and External will have the external projects that we use (their source code).

If you have your code in a subversion repository, add both of these folders to the repository, and then right click the External folder, TortoiseSVN, and Properties. Choose New and svn:externals from the drop down list.

Type this in Property Value:

https://PageTypeBuilder.svn.codeplex.com/svn PageTypeBuilder
https://www.coderesort.com/svn/epicode/EPiCode.Extensions/trunk/ EPiCode.Extensions

After you’ve added these settings, you can do a SVN update to retrieve these projects.

If you don’t have your code in a Subversion repository, just to a SVN Checkout for both of these projects inside the External folder instead.

After downloading both of these projects we can open them up in Visual Studio and add references to the EPiServer version that we’re using (6.0.382.1). To do that expand References inside Visual Studio, and delete everything that is from EPiServer, then right-click References, and choose Add Reference, navigate to our sites bin folder and choose the same EPiServer dlls you just deleted (though now in the correct version). After you’ve done that you can build everything (make sure to build in release mode, by going to the Build menu, Configuration Manager, and choose Release).

Do the same for both projects and copy all the .dll files to the References folder.

Before we can open up our project in Visual Studio, we need to edit our solution file with the new path to JungleSite.csproj.

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JungleSite", "wwwroot/JungleSite.csproj", "{86592C94-5E09-417B-B1E2-AFDB757B24D4}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Release|Any CPU = Release|Any CPU
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{86592C94-5E09-417B-B1E2-AFDB757B24D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{86592C94-5E09-417B-B1E2-AFDB757B24D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{86592C94-5E09-417B-B1E2-AFDB757B24D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{86592C94-5E09-417B-B1E2-AFDB757B24D4}.Release|Any CPU.Build.0 = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal

We should now be able to open up the project again. Before we can use EPiCode.Extensions and PageTypeBuilder, we need to add a reference to it in our project. Right-click references and choose Add reference, navigate to our References folder and choose all the .dlls in the References folder.

Great! We can now use both projects in our code.

Header.ascx

Lets start with Header.ascx, delete all the meta information. Next use the ResolveUrl method to link to the stylesheets.

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Header.ascx.cs" Inherits="Jungle.Templates.Jungle.Units.Header" %>
<asp:PlaceHolder ID="plhMetaDataArea" runat="server" />
 
<link rel="stylesheet" type="text/css" media="screen" href="<%= ResolveUrl("~/Templates/Jungle/Styles/screen.css") %>" />
<!--[if IE 6]><link rel="stylesheet" type="text/css" href="<%= ResolveUrl("~/Templates/Jungle/Styles/ie6.css") %>" media="screen" /><![endif]-->
<EPiServer:PageList ID="RssList" PageLinkProperty="RssContainer" runat="server">
    <ItemTemplate>
        <%#GetRss(Container.CurrentPage)%>
    </ItemTemplate>
</EPiServer:PageList>

I’ve also added a PageList for the RSS feeds (see Templates/Public/Units/Static/Header.ascx).

Lets now create a BasePageData for our page types. Create a new folder under Templates and Jungle, and give it a name of PageTypes. Inside PageTypes create a new class and name it BasePageData, make it derive from TypedPageData from the PageTypeBuilder project.

using PageTypeBuilder;
 
namespace Jungle.Templates.Jungle.PageTypes
{
    public abstract class BasePageData : TypedPageData
    {
    }
}

I’m assuming that you have worked with the Page Type Builder project before. If not be sure to at least read the introduction posts by Joel Abrahamsson, and my A Developer’s guide to PageTypeBuilder post.

When we created this EPiServer site we added the Public Templates with some standard content. Lets go to admin mode (http://jungle/cms/UI/admin/default.aspx), login with your local administrator account. Go to Page Type, and Dynamic Properties. Here you’ll see a bunch of standard dynamic properties that the Public Templates created for us. Delete the MainMenuContainer and LoginPage properties, since we don’t need them. Edit each property and copy its name into BasePageData.

using PageTypeBuilder;
 
namespace Jungle.Templates.Jungle.PageTypes
{
    public abstract class BasePageData : TypedPageData
    {
        /*
         * MetaAuthor
         * MetaDescription
         * MetaKeywords
         * SearchPage
         * UIEditorCssPaths
         */
    }
}

Standard code for accessing dynamic properties with PageTypeBuilder looks like this:

public virtual string MetaAuthor
{
    get
    {
        return this.GetPropertyValue(page => page.MetaAuthor, true);
    }
}

For more information be sure to take a look at Working with Dynamic Properties and Page Type Builder.

using EPiServer.Core;
using PageTypeBuilder;
 
namespace Jungle.Templates.Jungle.PageTypes
{
    public abstract class BasePageData : TypedPageData
    {
        public virtual string MetaAuthor
        {
            get
            {
                return this.GetPropertyValue(page => page.MetaAuthor, true);
            }
        }
 
        public virtual string MetaDescription
        {
            get
            {
                return this.GetPropertyValue(page => page.MetaDescription, true);
            }
        }
 
        public virtual string MetaKeywords
        {
            get
            {
                return this.GetPropertyValue(page => page.MetaKeywords, true);
            }
        }
 
 
 
        public virtual PageReference SearchPage
        {
            get
            {
                return this.GetPropertyValue(page => page.SearchPage, true);
            }
        }
 
        public virtual string UIEditorCssPaths
        {
            get
            {
                return this.GetPropertyValue(page => page.UIEditorCssPaths, true);
            }
        }
    }
}

We can now update all the code-behind files for Header, PageHeader, and PageFooter to derive from PageTypeBuilders generic UserControlBase and setting the type to BasePageData. Which gives us access to the dynamic properties we added to BasePageData.

using System;
using System.Web.UI.HtmlControls;
using EPiCode.Extensions;
using EPiServer.Core;
using EPiServer.Core.Html;
using Jungle.Templates.Jungle.PageTypes;
using PageTypeBuilder.UI;
 
namespace Jungle.Templates.Jungle.Units
{
    /// <summary>
    /// The header of the website. Generates metadata tags, rss and css links.
    /// </summary>
    public partial class Header : UserControlBase<BasePageData>
    {
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
 
            CreateMetaData();
        }
 
        /// <summary>
        /// Gets the link to a RSS source page
        /// </summary>
        /// <param name="page">The RSS source page</param>
        /// <returns>A string representation of a link</returns>
        protected string GetRss(PageData page)
        {
            string rssLinkTag = "<link rel=\"alternate\" type=\"application/rss+xml\" href=\"{0}\" title=\"{1}\" />";
            return string.Format(rssLinkTag, Server.HtmlEncode(page.LinkURL), page.PageName.ToWebString());
        }
 
 
        /// <summary>
        /// Creates the metadata tags for the website
        /// </summary>
        private void CreateMetaData()
        {
            string metaDescription = CurrentPage.MetaDescription;
            if (string.IsNullOrEmpty(metaDescription))
            {
                metaDescription = CurrentPage["MainIntro"] as string ?? string.Empty;
                if (!string.IsNullOrEmpty(metaDescription))
                {
                    metaDescription = TextIndexer.StripHtml(metaDescription, 0);
                    if (metaDescription.Length > 255)
                    {
                        metaDescription = metaDescription.Substring(0, 252) + "...";
                    }
                }
            }
            if (!string.IsNullOrEmpty(metaDescription))
            {
                CreateMetaTag("description", metaDescription, false);
            }
 
            // Keywords
            CreateMetaTag("keywords", CurrentPage.MetaKeywords, false);
 
            // Author
            CreateMetaTag("author", CurrentPage.MetaAuthor, false);
 
            // Rating
            CreateMetaTag("rating", "General", false);
 
            // Revisit each month
            CreateMetaTag("revisit-after", "4 weeks", false);
 
            // Generator
            CreateMetaTag("generator", "EPiServer", false);
 
            // Robots
            CreateMetaTag("robots", "all", false);
 
            // Charset
            CreateMetaTag("Content-Type", string.Format("text/html; charset={0}", "UTF-8"), true);
 
            // Created - GMT format
            if (CurrentPage.Created != DateTime.MinValue)
            {
                CreateMetaTag("creation_date", CurrentPage.Created.ToString("R"), false);
            }
            // Last modified data, in GMT format - Note, same as revised
            if (CurrentPage.Changed != DateTime.MinValue)
            {
                CreateMetaTag("last-modified", CurrentPage.Changed.ToString("R"), false);
            }
            // Revised - GMT format
            if (CurrentPage.Changed != DateTime.MinValue)
            {
                CreateMetaTag("revised", CurrentPage.Changed.ToString("R"), false);
            }
            CreateMetaTag("Content-Language", CurrentPage.LanguageBranch, true);
        }
 
        /// <summary>
        /// Adds a meta tag control to the page header
        /// </summary>
        /// <param name="name">The name of the meta tag</param>
        /// <param name="content">The content of the meta tag</param>
        /// <param name="httpEquiv">True if the meta tag should be HTTP-EQUIV</param>
        private void CreateMetaTag(string name, string content, bool httpEquiv)
        {
            var tag = new HtmlMeta();
            if (httpEquiv)
            {
                tag.HttpEquiv = name;
            }
            else
            {
                tag.Name = name;
            }
            tag.Content = content;
            plhMetaDataArea.Controls.Add(tag);
        }
    }
}

PageHeader

I’ve split the code into separate user controls, MainMenu and QuickSearch. If you like to learn more about some of the techniques used in this code, I recommend checking out my blog posts: EPiServer web controls: Property and EPiServer web controls: MenuList and PageTree.

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="PageHeader.ascx.cs" Inherits="Jungle.Templates.Jungle.Units.PageHeader" %>
<%@ Register TagPrefix="Jungle" TagName="MainMenu" Src="~/Templates/Jungle/Units/MainMenu.ascx" %>
<%@ Register TagPrefix="Jungle" TagName="QuickSearch" Src="~/Templates/Jungle/Units/QuickSearch.ascx" %>
 
<div id="header">			
 
	<a name="top"></a>
 
	<h1 id="logo-text"><asp:HyperLink accesskey="1" ID="lnkLogotype" runat="server" /></h1>					
 
	<Jungle:MainMenu runat="server" />	
 
	<p id="rss-feed"><EPiServer:Property runat="server" ID="RssFeed" PropertyName="RssContainer" /></p>	
 
	<Jungle:QuickSearch runat="server" />
 
<!-- /header -->					
</div>
using System;
using EPiServer;
using EPiServer.Core;
using Jungle.Templates.Jungle.PageTypes;
using PageTypeBuilder.UI;
 
namespace Jungle.Templates.Jungle.Units
{
    public partial class PageHeader : UserControlBase<BasePageData>
    {
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
 
            var startPage = DataFactory.Instance.GetPage(PageReference.StartPage);
 
            lnkLogotype.NavigateUrl = startPage.LinkURL;
            lnkLogotype.ToolTip = Translate("/navigation/startpagelinktitle");
            lnkLogotype.Text = Translate("/navigation/startpagelinktitle");
 
            this.RssFeed.PageLink = startPage.PageLink;
        }
    }
}

That’s it for this part! :). All the code is also available on EPiCode. See Part 1: Setting up the development environment, for details on how to connect.

The next post – Part 3: Creating the start page.

Related Posts: