Frederik Vig – ASP.NET developer

Follow me

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

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

Lets 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:

Share:
  • Twitter
  • DotNetKicks
  • DZone
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • StumbleUpon
  • Digg

27 Comments

  1. [...] « Introduction – Create an EPiServer site from scratch Part 2: Creating a foundation – Create an EPiServer site from scratch [...]

  2. Shahid says:

    I have checkedout the code for PageTypeBuilder in external folder. Now when I try to check out the code for EPiCode.Extensions in same folder “External” I get two options now i.e: “SVN update” & “SVN Commit”. How do I check out code for “EPiCode.Extensions” now? What I am missing here ?

  3. Frederik Vig says:

    Hi Shahid
    I’m guessing you’ve checked out the Page Type Builder project directly into the External folder. Right-click inside the External folder and choose checkout. That way we can use the External folder as a root folder for all our external projects.

  4. Shahid says:

    Hi again,

    I deleted the External folder , re-created it and did Right-Click inside the External folder for checkout. No problems with first checkout. When I RightClick again inside the external folder, I can’t see “SVN checkout” now instead I can see “Svn Update” & “Svn commit”. Do I need to do something before checkingout the 2nd project?

  5. Frederik Vig says:

    Could be that when you do a checkout it adds everything directly inside External. When you have the SVN Checkout dialog open, make sure to update the Checkout directory path to yourpath\External\ProjectName – replace ProjectName with either PageTypeBuilder or EPiCode.Extensions.

  6. Shahid says:

    Yes, it worked now.

  7. Olle Hellman says:

    Good article again!
    I will recomend it to all the EPiServer developers i know.

    btw fix the reference so the “Add Reference” image.

  8. Frederik Vig says:

    @Shahid – Great! I’ll try and update the post with better information when I have the time :) .
    @Olle – Thanks! Updated the image reference now.

  9. [...] In this post we’ll start on the foundation, adding the resources (images, JavaScript, CSS etc), creating the master page, and other common areas. Second part is out. [...]

  10. Christine says:

    Hi Frederik, great article! Also, I noticed you misspelled the “Mastepage” heading. I’m looking forward to reading the complete articles.

  11. Frederik Vig says:

    Ah thanks Christine! Corrected now :) . Glad you liked it!

  12. Alan Ramos says:

    Hello Frederik,

    I am a bit confuse with the part that describes the Referencing of the projects rigth after the code has been download from the SVN site. Could you please be a bit more descriptive or rephrase it because I have spent some time but I have not manage to work it out.

    Thanks very much.

  13. Frederik Vig says:

    Hi Alan!
    Where are you having problems? What version of EPiServer are you using? Did you build both EPiCode.Extensions and PageTypeBuilder with Visual Studio to create the dll files?

    Frederik

  14. Fugazi says:

    You could have mentioned that getting the source code for EPiCode.Extensions requires signing up and getting approved on EPiCode. Ridiculous move, if you ask me. Or am I missing something?

  15. Steve says:

    What is so ridiculous about that?

    /Steve (EPiCode administrator)

  16. Fugazi says:

    Well what’s the point, really? Why not allow at least read only access for everyone? Why do I need to be an “approved” member to get access to the code?

    Mind you, I applaud the effort of projects like EPiCode and the whole idea of sharing code. But members-only access just to read the code? That’s ridiculous.

    But I guess there’s something there I just miss, and I’m sure there’s a perfectly valid explanation.

  17. Fugazi says:

    A guess from the lack of response that there is no valid explanation to the ridiculousness of forcing membership to get read access, but merely a lack of interest in being “open” in the words truest sense.

    Nice. You’re doing a disservice to the open community, but I guess you don’t even realize that.

  18. Frederik Vig says:

    @Fugazi I know Steve has some very valid reason for having members sign up before being able to do a checkout. I’m sure he just forgot to answer your comment, and will do so when he has some more time :) .

  19. Steve says:

    Hi Fugazi,
    I never checked for a response to my comment. I apologize for that, I should have checked since I asked you a question. From your latest response, I see that it really did not matter.

    /Steve (EPiCode Administrator)

  20. Rob says:

    Hi, I could not see the Junglesite on epicode even though I have signed up. Am I doing something wrong or has it been taken off?

  21. Alan Allard says:

    Hi thanks for some great blogs, Frederik. Wondering though, extensions is now 2k10 only, shouldn’t there be a branch for 2k8? Getting older version in the meantime…
    Cheers,
    Alan

  22. Frederik Vig says:

    Hi Alan, you only need Visual Studio 2010 to compile the code. You can download the .dll file from EPiCode.Extensions’s project page (https://www.coderesort.com/p/epicode/wiki/Extensions), download link at the bottom.

  23. Bhavana says:

    Hi Frederik,

    I am not able to download EPiCode.Extensions project. Its givig the following error.

    Error: Server sent unexpected return value (403 Forbidden) in response to OPTIONS
    Error: request for ‘https://www.coderesort.com/svn/epicode/EPiCode.Extensions/trunk’

  24. Frederik Vig says:

    Hi Bhavana, you need to register on EPiCode to get access: https://www.coderesort.com/p/epicode

  25. Bhavana says:

    Hi Frederik,

    Thanks for your reply.I have already registered with this site. Do I need to request for project membership also.

    Regards,
    Bhavana

  26. Frederik Vig says:

    Hi Bhavana, correct, you also need to apply for membership.

Leave a Reply

Spam Protection by WP-SpamFree

© Copyright Frederik Vig. Based on Fluid Blue theme