This is a short demo of how you can use the new simpler way to implement Dynamic Content with a ordinary User Control and some Plug-In attributes.

Screenshot of Dynamic Content in EPiServer CMS using DynamicContentPlugIn attribute

DynamicContentPlugIn is the simplifying solution

First add a normal User Control or EPiServer User Control if you want to be aware about the Current Page.

HelloDynamic.ascx.cs


using EPiServer.DynamicContent;
using EPiServer.PlugIn;

namespace EPiServer
{
    [DynamicContentPlugIn(DisplayName = "Hello...", 

      ViewUrl = "~/HelloDynamic.ascx")]
    public partial class HelloDynamic : EPiServer.UserControlBase
    {
        public string Firstname { get; set; }
        public PageReference FeatureArticle { get; set; }
    }
}

DynamicContentPlugIn will auto register the Dynamic Content control and wrap wrap all handling of settings, rendering and state handling. There is no need to register the class in episerver.config or to implement IDynamicContent.

All public properties inheriting from PageData will be used as settings. Properties with primitives as type like string, int, bool but also PageReference will be converted to PropertyString, PropertyNumber, PropertyBoolean respectively PropertyPageReference.

HelloDynamic.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="HelloDynamic.ascx.cs" Inherits="EPiServer.HelloDynamic" %>
<h1>Hello <%= Firstname %>!</h1>

How to add a Custom Settings Editor for Dynamic Content

imageIf you do not use the Url and Area parameters of the DynamicContentPlugIn attribute you will get the default settings editor that just show all Properties in a list.

HelloDynamic.ascx.cs


    [DynamicContentPlugIn(DisplayName = "Hello...", 

        ViewUrl = "~/HelloDynamic.ascx", 

        Url = "~/HelloDynamicEdit.ascx", 

        Area = PlugInArea.DynamicContent)]
    public partial class HelloDynamic : EPiServer.UserControlBase

HelloDynamicEdit.ascx.cs

using EPiServer.DynamicContent;

namespace EPiServer
{
    public partial class HelloDynamicEdit : DynamicContentEditControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                Firstname.Text = Content.Properties["Firstname"].Value as string;
            }
        }

        public override void PrepareForSave()
        {
            Content.Properties["Firstname"].Value = Firstname.Text;
        }
    }
}

Inherit from DynamicContentEditControl and implement the method PrepareForSave() to move the values back from your user interface to the Property collection of your Dynamic Content class. Note the use of IsPostBack to prevent overwriting of changed values.

HelloDynamicEdit.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="HelloDynamicEdit.ascx.cs" Inherits="EPiServer.HelloDynamicEdit" %>
<h1>This is a custom editor</h1>
<p>Hello <asp:TextBox ID="Firstname" runat="server" />!</p>

Translating the User Interface for Dynamic Content

You can use the DisplayName and Description parameters for the name and instructions for editors. Use LanguagePath parameter together with translations in the lang-folder.


    [DynamicContentPlugIn(DisplayName = "Hello...", 

        ViewUrl = "~/HelloDynamic.ascx", 

        LanguagePath = "/dynamiccontent/hello")]
    public partial class HelloDynamic : EPiServer.UserControlBase
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<languages>
   <language name="Svenska" id="sv">
      <dynamiccontent>
         <hello>
            <name>Hej…</name>
            <description>En beskrivning…</description>
         </hello>
      </dynamiccontent>
      <pagetypes>
         <common>
            <property name="Firstname">
               <caption>Fornamn</caption>
               <help>Vad heter du?</help>
            </property>
         </common>
      </pagetypes>
   </language>
</languages>
Bookmark and Share

Tags: , ,

This is maybe a strange blog post  because it is written as an instruction to a junior developer who I have been coaching on how to be better at QA of web sites and a template for a site test protocol.

I’m sharing it with you to get feedback myself on my mentoring.


Project: <project or site name>
Release: < build date and version number >
Test leader: <name>
Date: <date when test was performed>

Page Validation Tests

TEST: Simple WAI test

Performed with Firefox with Web Developer Toolbar plug-in. Turn on option Persist Features, and disable JavaScript, disable CSS and disable images.

clip_image002

clip_image004

clip_image006

clip_image008

Success criteria’s
  • Verify that you can understand the page and the structure of the information. All sections should have h1-h6-tags.
  • Use CSS for class for Aural Text to hide headings only needed by screen readers.
  • Make sure label tags are used and that they point to correct control.
  • Test functionality! Buttons does post-back but Link Buttons rely on JavaScript and will fail to work.
  • Make sure all images has alt-tags. Decorative images should not be in markup only in CSS.

Meridium’s site is a good example:

clip_image010

TEST: Markup and CSS Validation

Test quality of markup and CSS with the validation tool in Web Developer Toolbar.

clip_image012

Success criteria
  • There should be NO validation errors at all.

TEST: Traffic check

This test can be done in parallel with a full run of another test. Just start capturing and analyze the result afterwards.

Disable browser cache during this test with Web Developer Toolbar in firefox.

clip_image014

Capture all traffic between your browser and the web server using Fiddler HTTP Debugging proxy.

clip_image016

Success criteria’s
  • No error server responses (400-599)
  • All resources has relevant caching

TEST: Browser Layout Validation

Compare each page with reference layout.

Success criteria’s
  • Page should look good on its own with balance.
  • Structure should not collapse or information be hidden.
  • Missing functionality should degrade gracefully (i.e. rounded corners being square on IE)
  • No major differences in margins or padding.
  • Elements should align.

Instructions for test documentation

A developer should of course do a self test in a few browsers before check-in but a complete test of a site is still needed with all A-Grade browsers.

Each row in the test protocol is a representative test page on the site or test of functionality block. There is usually one row for each Page Type and/or each Product Backlog item.

Each column represents a type of test that should be performed on each test page or functionality block. Each cell holds the result from a single test.

Legend to use for test result

  • [Blank] Test not performed yet.
  • X Not applicable, this test case is not relevant.
  • OK Test is performed without remarks.
  • 123 Test is performed with remarks. Number is a reference to the remark. Use screenshot if needed to clarify

Test Result Matrix

Test Cases

Other

Browser Layout Validation

 

Simple WAI Test
No JS, CSS, Img

Markup and CSS Validation

Traffic check
404, 500, cache

IE7
(XP)

IE8

IE9

FX 3.6

FX 4

Safari (Mac)

Chrome

Start Page

                   

Normal Page

                   
                   

Test Remarks

1. <test remark>

2.

3.


Page Performance Test

This test is performed on the start page of the site and on commonly used AJAX functions.

Use YSlow plug-in to analyze the start page.

clip_image018

Success criteria’s

All C-F grades should be reviewed but only some issues in the list are related to development and other to configuration of hosting environment.

IMPORTANT! Always use jQuery and Microsoft AJAX scripts from Google or Microsoft CDN!

The following tests should always be reviewed by developers:

YSlow Test Result

Grade

Test

 

Make fewer HTTP requests

Decreasing the number of components on a page reduces the number of HTTP requests required to render the page, resulting in faster page loads. Some ways to reduce the number of components include: combine files, combine multiple scripts into one script, combine multiple CSS files into one style sheet, and use CSS Sprites and image maps.

 

Put CSS at top

Moving style sheets to the document HEAD element helps pages appear to load quicker since this allows pages to render progressively.

 

Put JavaScript at bottom

JavaScript scripts block parallel downloads; that is, when a script is downloading, the browser will not start any other downloads. To help the page load faster, move scripts to the bottom of the page if they are deferrable.

 

Make AJAX cacheable

One of AJAX’s benefits is it provides instantaneous feedback to the user because it requests information asynchronously from the backend web server. However, using AJAX does not guarantee the user will not wait for the asynchronous JavaScript and XML responses to return. Optimizing AJAX responses is important to improve performance, and making the responses cacheable is the best way to optimize them.

 

Use GET for AJAX requests

When using the XMLHttpRequest object, the browser implements POST in two steps: (1) send the headers, and (2) send the data. It is better to use GET instead of POST since GET sends the headers and the data together (unless there are many cookies). IE’s maximum URL length is 2 KB, so if you are sending more than this amount of data you may not be able to use GET.

 

Do not scale images in HTML

Web page designers sometimes set image dimensions by using the width and height attributes of the HTML image element. Avoid doing this since it can result in images being larger than needed. For example, if your page requires image myimg.jpg which has dimensions 240×720 but displays it with dimensions 120×360 using the width and height attributes, then the browser will download an image that is larger than necessary.

 

Make favicon small and cacheable

A favicon is an icon associated with a web page; this icon resides in the favicon.ico file in the server’s root. Since the browser requests this file, it needs to be present; if it is missing, the browser returns a 404 error (see "Avoid HTTP 404 (Not Found) error" above). Since favicon.ico resides in the server’s root, each time the browser requests this file, the cookies for the server’s root are sent. Making the favicon small and reducing the cookie size for the server’s root cookies improves performance for retrieving the favicon. Making favicon.ico cacheable avoids frequent requests for it.

Other Tests Results

Check?

Test

 

Use jQuery and other common resources from Google or Microsoft CDN

 

CSS Sprites is used to minimize number of images


Functional Regression Testing

Before a major release a full regression test should be performed on all existing functionality to reduce the risk that a function is broken after it was originally tested.

Since testing must be systematical and it is hard to remember what should be tested each sprint needs to add its test scenarios to the check list.

As a guideline each product backlog item should have at least one documented regression test.

TEST: Registration Flow

Test related to authentication and registration.

Check?

Test

 

Register as a new user (test links in mail!)

 

Login

 

Logout (and test access to protected resource)

 

Change forgotten password (test links in mail!)

 

Change mail address for account

TEST: Feature A

Test related to …

Check?

Test

   
   
   

TEST: Feature B

Test related to …

Check?

Test

   
   
   
Bookmark and Share

Tags: , ,

Just a list of small things noted while working with the latest release.

  • Page Folder is not default for File Manager. Message change from “Save” to “Create page folder” when a page folder does not exist.
  • Simple address fixed – Works with and without trailing slash.
  • Help documentation is not local anymore but is moved to http://webhelp.episerver.com.
  • New Gadget: Visitor Group Statistics
  • jQuery plugins that uses size of elements (like carousel, equal height) now works in Preview Frame
  • Background Job in edit mode: Copy/Paste and Empty Wastebasket
  • New class BackgroundJobHelper for your own stuff.
  • Export and Import Data Tool can handle Visitor Group definitions.
  • EPiServer.config – virtualRoles tag is moved to EPiServerFramwork.config!
  • Dojo JavaScript library included in EPiServer Framework. Used in OnlineCenter and VisitorGroups.
  • jQuery-ui replaced with dijit.
  • web.config: Shell Module configuration has a new setting to register dojo modules.

<dojoModules>
  <add name="dojo"
       path="ClientResources/dojo/dojo"/>

Bookmark and Share

Tags: ,

I like to dig around and here are a few things I did notice in the upcoming EPiServer CMS 6 R2 release.

  • Visitor Groups and personalized content
  • On Page Edit is cross browser compatible (not only available for IE)
  • New AutoSaveRepository to handle drafts unsaved pages.
  • New InUseNotificationRepository used to warn editors that someone is working with a page.
  • Much easier to create and register Dynamic Content as a developer and an editor can change values easier and preview it.

And a few smaller things…

  • New namespace EPiServer.Framework.CssParsing and EPiServer.Framework.HtmlParsing with public classes.
  • new Geolocation and database in EPiServer.Framework.Personalization
  • Virtual Roles moved to EPiServer.Framework
  • EPiServer’s InitializationModule will forward HttpModule initialization and the HttpApplication to all modules with both IInitializableModule and IInitializableHttpModule interface. An easy way to setup events without having to mess with own http module registration in web.config.
  • Most methods in UserControlBase are now virtual like in PageBase so you can override them.
  • PageBase now has a GetPage method with language selector parameter.
  • Dope is obsolete and renamed to OnPageEdit :)
  • DataFactory.Copy is now delegated to an interface (IPageCopyHandler) so you can override the behavior
  • New method DataFactory.GetPages(IList<PageReference> pageLinks, ILanguageSelector selector)
  • UrlRewriteEventArgs used by UrlRewriterModule has a new property ForceRewriteHtml that overrides the existing Cancel property.
  • New interface IPermanentLinkMapper exposed on UrlRewriteProvider that can be used instead of accessing PermanentLinkMapStore class directly.
  • Several new nice extension methods for FindControl (typed and recursively) in EPiServer.Web.ControlExtensions.
  • PropertyDataControl has a new property CustomTagName that change rendering in view mode from a Label using span to a HtmlControl with the tag specified in CustomTagName and creating child controls in view mode is controlled with virtual method ShouldCreateDefaultControls.
  • PropertyDataControl has a new CopyWebAttributes method that supports HtmlControls and not only WebControls.
  • MultipleOptionsListSettings is a new settings class with UI to enter name and value pairs used by the new properties PropertyCheckBoxList and PropertyDropDownList.
  • You can now set default language for a site in EPiServerFramwork.config and get the value with ContentLanguage.GetDefaultHostLanguage()
    <add name="*" language="en" />
  • New filter: FilterReplacementLanguage
  • TinyMCE editor is initialized using the new CssParser that extract styles from editor css files like the old editor. The name of the style is extracted from the dummy css attribute EditMenuName like in earlier but since this is done server side it can be translated (below editorstyleoptions node). Read more in Linus blog post
  • DynamicContentPlugInAttribute can be used to register Dynamic Content without messing with web.config. Use ViewUrl parameter for User Controls can be used to register user controls.
  • New namespace EPiServer.Core.Html.StringParsing with public classes that handles the different elements of rich text (static text, url, dynamic content, vistor group content)
  • LanguageSelector and related classes are refactored (and probably works better but different). Read more in a blog post from Linus.
Bookmark and Share

Tags:

I wrote earlier about the annoying fact that alphabetic sorting of child pages in EPiServer CMS 5 is controlled by the collation settings in your database server and suggested that it could be fixed. My first solution that tinkers with database settings had side effects and should not be used.

How to fix sorting of children in EPiServer CMS 5

//Hook FirstBeginRequest Application_Start event in Global.asax.cs
void InitializationModule_FirstBeginRequest(object sender, EventArgs e)
{
    DataFactory.Instance.FinishedLoadingChildren += EPDataFactory_FinishedLoadingChildren;
}

private void EPDataFactory_FinishedLoadingChildren(object sender, EPiServer.ChildrenEventArgs eventArgs)
{
    if ((eventArgs.Children.Count > 0) && (((int)DataFactory.Instance.GetPage(eventArgs.PageLink)["PageChildOrderRule"]) == 3))
    {
        FilterPropertySort comparer = new FilterPropertySort("PageName");
        comparer.CompareInfo = ContentLanguage.PreferredCulture.CompareInfo;
        eventArgs.Children.Sort(comparer);
    }
}

Just add the code above to your Global.asax.cs file and add the hook to FirstBeginRequest event in Application_Start. It will apply sorting of children that is culture sensitive and changes according to the current language.

NB! This fix is not needed in EPiServer CMS 6 because it is already built-in.

Bookmark and Share

« Older entries