9. A few problems Wespend a lot of time not writingcode Wedefine ”templates” for objects in a webbased UI There’s no inheritancebetween page types Synchronizing different environments is a pain ObjectOrientation? Weuse a lot of ”magic strings” Weplacelogic in the presentation layer that doesn’tnecessarilybelongthere WedistinguishPageDataobjects by the ID of their Page Type
10. Whatif… Article Decideswhich template to use Actually is an instance of ArticlePage Page<Article> (.ASPX) Renderscontent from, knowing the type
11. Page TypeBuilder An opensourceproject Creates and updates page typesbased on classes Ensures that DataFactoryreturnsinstances of your classes
12. By using Page TypeBuilderwe get Less switchingbetween Visual Studio and Admin Inheritancebetween page types Stronglytyped access to properties The ability to placelogic in pages Polymorphism Faster and easier releases Bettertestability
13. Getting started Download from pagetypebuilder.codeplex.com ReferencePageTypeBuilder.dll CopyCastle.Core.dll and Castle.DynamicProxy2.dll to your bin folder
14. Creating a page type usingPageTypeBuilder; namespaceMySite.PageTypes { [PageType] public classArticle : TypedPageData { } }
17. Specifyingproperty settings [PageType] public classArticle : TypedPageData { [PageTypeProperty( EditCaption ="Main body", HelpText = "Will be shown in the main content area of the page", Type = typeof(PropertyXhtmlString))] public virtual stringMainBody { get; set; } }
18. Creating a template usingPageTypeBuilder.UI; namespaceMySite.Templates { public partialclassArticle : TemplatePage<PageTypes.Article> { } }
Three of the mostimportantcomponentswhendeveloping with EPiServer is Page Types, PageDataobjects and templates.A PageDataobject is sort of an instance of a PageType. A PageType is sort of like class, but not quite. Let’stake a look at whatimplications this has for oureveryday work.
Wecreate page types in EPiServer’sadmin mode.
Weaddproperties to page types, again in EPiServer’sadmin mode.
Weaddmarkup to pages and usercontrols, oftenusingwebcontrols that ship with EPiServer, to display the properties.
Whenweneedsomecustombehaviorweadd it to pages,customcontrols or some sort of utilityclasses.
Althoughweuse a staticallytypedlanguageweuse a lot of magic strings and therebybypass the checks performed by the compiler.It can be discussed, but I personallydon’tthink that determiningwhat to display as a heading for a page is the presentation layer’sjob, it’s the page’s.Since all pages are just instance of PageDatawehave to rely on filtering by numericalID’swhenwewant to find pages of a certain page type. This is extra problematicwhenwewant pages that may be of several different page typessincethere’s no inheritancebetween page types and theycan’timplement interfaces.
What if each page type was actually a class? And whatifeachPageDataobjectwas an instance of that class? And whatif the templateknewwhichtype, or basetype, it was rendering?If that was the casewewouldhaveinheritancebetween page types. Wecouldstrongly access propertyvalues. And wecouldeasily filter pages not only by typebutalso by whetherit’stypeimplements an interface or not.
Page TypeBuildersolves this (the previousslide).Page TypeBuilderdoesquite a lot of things, but the twomostimportantthings is that it creates and updates page typebased on classes that we, or third party products, candefine and that it interceptsrequests for PageDataobjects to DataFactory’smethods and replaces the objects that theyreturn with instances of the class that defines the page’s page type.
As wedefine page types in code all wehave to do to add or update page types, properties and tabs is writecode, compile and go to the site.As classes are used to define page typesweeffectively get inheritancebetween page types.SinceDataFactorynowreturnsinstances of ourclasseswe get stronglytyped access to propertyvalues.Another benefit of DataFactoryreturninginstances of ourclassesinstead of just PageData is that wecanplacelogic in theseclasses. I’llsoon show a couple of example of how this can work.Aseach page is an instance of a class that canhaveit’sownspecificbehaviour and alsoimplement interfaces wecanusepolymorphism. That is several page typescanhave the same method with the same signature that is implemented in different ways. Wecanthenusecode that is uses this methodbutdoesn’tknowaboutit’simplementation.Since Page TypeBuilderadds and updates page types, properties and tabs all wehave to dowhenwewantneed to do a release that involves page typechanges is to deployourassemblies.The moreobjectorientedway of working with Page TypeBuildercan a cornerstone in writingcode that it’spossible to writeunit tests for. Page TypeBuilderalso offers a moreconcreteadvantagewhen it comes to testing. Sincewecanmovesomelogic from the hard-to-test presentation layerintoour page typeclasses, and Page TypeBuilder has a feature for injectingdependenciesintoPageDataobjectswecanputquiteeasily test it.
I’veputsomeeffortintomaking it as easy as possible to get started with Page TypeBuilder. This meansthere’s no configuration or installationrequired. All you have to do is download it and put the assemblies that the Zipfilecontainsinto your bin folder and add a reference to PageTypeBuilder.dll.Of course, in a realistic scenario you wouldprobablywant to putthird party libraries like this somewhereelse and havethemautomaticallycopied to your bin folder when you compile. In that case you need to ensure that the two Castle assemblies are copied to the bin folder as Page TypeBuilder is dependent on them.PageTypeBuilderrequires EPiServer CMS 5 R2 SP2 or EPiServer CMS 6.
To create a page type all you have to do is add a new class in your project that inherits from TypedPageData and has a PageTypeattribute. Given thesefewlines of code Page TypeBuilderwillcreate a new page typenamedArticle as soon as you compile and browse the site.Normallywhenwecreate a page typewehave to specify a fewthingssuch as a path to the template that shouldrender the page type. Page TypeBuilderdoesn’t force us to do this and instead has a fewconventions. For instance, ifwedon’tspecify a path to the template it willautomatically be set to default.aspx.
By setting properties on the PageTypeattributewecanspecifyevery setting for a page type that wecanspecify in EPiServer’sadmin mode.By default the name of the page typewill be the class’ namebutwecanspecify that as wellusing the PageTypeproperty. Be awarethough that the name is used to identify the page type.
Tocreateproperties all wehave to do is add a codeproperty to a page typeclass and add a PageTypePropertyattribute to it.Again Page TypeBuilderwilluseit’s default conventions for mandatory settings. For instance, codeproperties of type string willautomatically be created as XHTML string properties.
Just as for page typeswecanuseproperties of the PageTypePropertyattribute to specifyeverything that wecanspecify in admin mode. However, it does not handle the new property settings that wasintroduced in EPiServer CMS 6. At least not yet.
Oncewehave a page typewewillprobablywant to render it using a template. Creating templateswhenusing Page TypeBuilder is verysimillar to how you do it when you aren’tusing Page TypeBuilder. The onlydifference, which is optional, is that you inherit from Page TypeBuilder’sgenericTemplatePage, or UserControllBase, instead of the EPiServer equivalents. These in turninherit from EPiServer’sclasses with the same name so no functionality is lost.
By inheriting from Page TypeBuildersgenericbaseclasses for pages or usercontrols the CurrentPagepropertywill be of the specifiedtype, enablingstronglytyped access to the currentpage’sproperties.
Previouslywesaw a verybasicimplementation of a propertyusingautomatic getters and setters. Wecanalsoimplementpropertiesusing an extension method for PageDatanamedGetPropertyValue. This waywecancreateproperties with logic in them. In this casewe check if the headingproperty is set and return it if it is. If it isn’twereturn the page’sname. This waywhenwewant to display a heading for the page wedon’thave to createanyconditionallogic, just display the page’sHeadingcodeproperty. This wayweencapsulate data where it belong and we get less code repetition.
AsDataFactorynowreturnsinstances of ourclasseswecan not just addlogic to properties. Wecanalsoaddregularmethods to our page types.This exampleillustratestwothings. First of all that wecanadd a methodsuch as GetComments to ourArticle page typeclass. Second that wecan filter pages by type.In a real scenarioweprobablywouldn’twant to callDataFactory.Instance from the methodbutinject an instance of an interface into the object.