Loading...
Area: Optimizely CMS
ARCHIVED This content is retired and no longer maintained. See the latest version here.

Recommended reading 

Table of Contents

  • Introduction
  • WebForms: DisplayChannel
  • MVC: IDisplayMode
  • DisplayChannelService
  • Previewing Content
  • Adding a New Device to View Resolution
  • Introduction

    The idea with display channels is to make it possible to control the rendering of content depending on the request. One example is to control which templates (WebForm, UserControl, View or partial view) that should be used to render depending on the request (for example, which browser it is). Another option is to have a single template but in that template check which channels are active and then control output (for example, which stylesheet to use) depending on active channel. This means it is possible to target the output for example specific devices.

    WebForms: DisplayChannel

    To create a DisplayChannel to be used with WebForms you create a class that inherits EPiServer.Web.DisplayChannel. There is no need for an explicit registration of the channel, during initialization the system will scan and register all found channel instances. The method IsActive is where you add your logic that controls if you channel is to be considered active for a request. When the system tries to resolve which template (WebForms or UserControl) to use to render an item it will check which DisplayChannels that are active and then it will prefer templates that has a tag included in EPiServer.Framework.DataAnnotations.TemplateDescriptorAttribute.Tags that matches EPiServer.Web.DisplayChannel.ChannelName for the active channel.

    The following example shows a simple DisplayChannel that is active for mobile devices:

    C#
    public class MobileDisplayChannel : DisplayChannel
    {
        public override bool IsActive(HttpContextBase context)
        {
            return context.Request.Browser.IsMobileDevice;
        }
    
        public override string ChannelName
        {
            get { return RenderingTags.Mobile; }
        }
    }

    If we then have two different templates registered for same type and one template has a tag that matches the ChannelName then that template will be used when the channel is active.

    The following example shows two different templates for same type:

    C#
    [ContentType]
    public class MyBlock : BlockData {}
    
    [TemplateDescriptor(Default=true)]
    public partial class MyBlockControl : BlockControlBase<MyBlock>
    { }
    
    [TemplateDescriptor(Tags = new string[] { RenderingTags.Mobile })]
    public partial class MyBlockMobileControl : BlockControlBase<MyBlock>
    { }

    MVC: IDisplayMode

    To register a System.Web.WebPages.IDisplayMode to be used with MVC you register your instance with EPiServer.Web.DisplayChannelService. The reason for registering the IDisplayMode towards EPiServer and not directly against ASP.NET is to make it possible for editors to preview the channel even if the request it self does not match the channel condition. That is for example to make it possible for an editor to view the site as it would appear for a mobile device even if the editor is working on a regular browser. Otherwise the same conventions as for System.Web.Mvc applies which is if for example if a channel “mobile” is active then the convention is to prefer a view named like Index.mobile.cshtml before one named Index.cshtml.

    The following example shows how to register a simple IDisplayMode that is active for mobile devices:

    C#
    public void Initialize(EPiServer.Framework.Initialization.InitializationEngine context)
    {
        context.Locate.DisplayChannelService()
            .RegisterDisplayMode(new DefaultDisplayMode(RenderingTags.Mobile)
        {
            ContextCondition = (r) => r.Request.Browser.IsMobileDevice
        });
    }

    DisplayChannelService

    If you need to know which channels that are active for a request you could get the active channels from EPiServer.Web.DisplayChannelService. The service can be retrieved either from EPiServer.ServiceLocation.ServiceLocator.Current or from EPiServer.ServiceLocation.ServiceLocationHelper which is exposed in several locations, for example, in PageBase, UserControlBase, InitializationEngine if you have a using statement for namespace EPiServer.Web. This can be useful for example when you want to select stylesheet depending on active channel.

    The following example shows how to set a CSS class depending on if mobile channel is active:

    C#
    public partial class ABlockControl : BlockControlBase<MyBlock>
    {
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            CssClass = Locate.DisplayChannelService().GetActiveChannels(new HttpContextWrapper(HttpContext.Current))
                .Any(c => String.Equals(c.ChannelName, RenderingTags.Mobile, StringComparison.OrdinalIgnoreCase)) ?
                "MobileMainArea" : "MainArea";
        }
    
        protected String CssClass { get; set; }
    }

    Previewing Content

    There is a possibility for the editor to preview the site with different channels active. When the editor selects to preview the site for a specific channel all requests to IsActive on the DisplayChannel and IDisplayMode instances are shortcutted and the one that is selected for preview will “fakely” return true for the request.

    Adding a New Device to View Resolution

    In the user interface there is a feature for changing the size of the preview view port. This is intended to give the editor a quick way of visualizing a page as it would turn out when shown on a smaller screen. A few devices are set up in the Alloy Templates project, and it is very easy to add your own.

    One popular device these days is the Google Nexus 7 tablet, this section describes how to add a preview option for it to the preview resolutions drop-down list.

    Looking at the hardware specs you can see that the native display resolution on the Nexus 7 is 1280 by 800 pixels, but these values cannot be used straight away. The reason is that most high resolution mobile devices apply scaling and actually report different screen dimensions than the physical ones. The iPhone 4 for instance, reports the same screen dimensions as the iPhone 3 even though its display sports four times as many pixels. Therefore you need to know which resolution the device actually reports to get as close as possible to reality. An easy way of figuring this out is to pay this screen size test page at Quirksmode.org a visit with the device in question and check the reported window width and height. For the Nexus 7 in portrait mode you get a reported canvas size of 600 by 790 pixels, and in landscape mode 960 by 440 pixels. The difference in width/height between the different modes is caused by soft buttons and browser chrome (location bar and tabs).

    Now when you have this information, you can add a new option to the resolution section of the view drop-down list by implementing the interface EPiServer.Web.IDisplayResolution

    C#
    public class Nexus7PortraitResolution : IDisplayResolution
    {
        public string Id
        {
            get { return GetType().Name; }
        }
    
        public string Name
        {
            get { return "Google Nexus 7 Portrait"; }
        }
    
        public int Height
        {
            get { return 790; }
        }
    
        public int Width
        {
            get { return 600; }
        }
    }

    Now build and reload and you should have a new display resolution option available.

    Adding a Backgroud Device Image

    If you inspect the HTML structure around the preview iframe you will notice an auto-generated CSS class named epi-viewPort-600x790, where the numbers correspond to the dimensions specified in the definition above. Define this CSS class to customize the look of the view port – assuming you are in the Alloy sample project – you add a new CSS file ClientResources/Style/displayresolutions.css with the following contents:

    .epi-viewPort-600x790
    {
        background: url('../images/nexus7.png') no-repeat center center;
    }

    The image nexus7.png referenced in the CSS class above is a background image picturing the Nexus 7, and is shown behind the scaled down view port.

    To get this CSS file loaded when the user interface loads you will need to go to piggy-back on the CMS module’s resource bundle. Knowing that the CMS module depends on a resource bundle named epi.cms.widgets.base you can add your CSS file to this resource bundle from the module.config of your project.

    <clientResources>
        <add name="epi.cms.widgets.base" path="Styles/displayresolutions.css" 
             resourceType="Style" isMinified="false" />
    </clientResources>

    Now your displayresolutions.css file will be loaded whenever the CMS module is started, in other words when going to the editorial interface.

    Keep in mind that there is no file watch on module.config, so changes are not picked up automatically by the application. Therefore you will have to touch web.config or restart the application by other means to see the changes on the site.

    You should now be able to select Nexus 7 in the resolution drop down and get the preview as shown below, with the browser preview to the left and the actual rendering to the right for comparison.

    While this approach of course does not give the exact same result as on the actual device, it can give the editor a fairly accurate idea of how a page will look on a different screen.

    Do you find this information helpful? Please log in to provide feedback.

    Last updated: Mar 25, 2013

    Recommended reading