Episerver site switch for properties

Episerver site switch for properties

Usually when you have multiple sites in an Episerver implementation your models are inherit by all sites you create under the root node. However, not all the properties in a model are used in all sites. In this post, we are going to address this issue by using an attribute which will hide (not remove) the property to editors based on which site you are. In addition, you can use the same logic to display the property in the view only when you are in one of the sites.

The first thing we are going to do is to create a helper class which will allow us to differentiate when we are in the main site (assuming we only have two).

using System.Configuration;
using System.Web;
using EPiServer.Web;

namespace EpiExamples.Helpers
{
    public class MainSiteSwitchHelper
    {
        private static string MainSiteName { get; }

        static MainSiteSwitchHelper()
        {
            var mainSiteString = ConfigurationManager.AppSettings["MainSiteName"];
            if (string.IsNullOrEmpty(mainSiteString))
            {
                mainSiteString = "Main Site";
            }

            MainSiteName = mainSiteString;
        }
        public static bool IsMainSite => HttpContext.Current != null && (HttpContext.Current.Request.Url.Host.Contains(MainSiteHostName) || IsMainSiteByDefinition());

        private static string MainSiteHostName
        {
            get
            {
                var hostName = ConfigurationManager.AppSettings["MainSiteHostName"];
                if (string.IsNullOrEmpty(hostName))
                {
                    hostName = "mainsite";
                }

                return hostName;
            }
        }

        private static bool IsMainSiteByDefinition()
        {
            return MainSiteName.Contains(SiteDefinition.Current.Name);
        }
    }
}

The main objective of the helper is to check if it can match the values saved in the web.config file to the host name from the request or the site name defined in the admin interface of the CMS for the first site. If it does, it returns true and false otherwise.

We set MainSiteHostName and MainSiteName properties for this in the web.config file.

Keep in mind that to you cannot have a multi site implementation using IIS Express, you must configure them using your Local IIS, if you want a blog post about how to do this let me know in the comments.

Now, we will create an attribute that can be used in any property to differentiate between properties that belong only to the main (first) site

using System;
using System.Web.Mvc;
using EpiExamples.Helpers;

namespace EpiExamples.Attributes
{
    public class MainSiteSwitch : Attribute, IMetadataAware
    {
        public bool AllowEditing => MainSiteSwitchHelper.IsMainSite;

        public void OnMetadataCreated(ModelMetadata metadata)
        {
            metadata.ShowForEdit = AllowEditing;
        }
    }
}

To use this new attribute, we can go to any page or block model and decorate one of the properties with it.

using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.DataAnnotations;
using System.ComponentModel.DataAnnotations;
using EpiExamples.Attributes;

namespace EpiExamples.Models.Pages
{
    /// <summary>
    /// Used for the pages mainly consisting of manually created content such as text, images, and blocks
    /// </summary>
    [SiteContentType(GUID = "9CCC8A41-5C8C-4BE0-8E73-520FF3DE8267")]
    [SiteImageUrl(Global.StaticGraphicsFolderPath + "page-type-thumbnail-standard.png")]
    public class StandardPage : SitePageData
    {
        [Display(
            GroupName = SystemTabNames.Content,
            Order = 310)]
        [CultureSpecific]
        public virtual XhtmlString MainBody { get; set; }

        [Display(
            GroupName = SystemTabNames.Content,
            Order = 320)]
        public virtual ContentArea MainContentArea { get; set; }

        [MainSiteSwitch] // Property only used in main site
        [Display(
            GroupName = SystemTabNames.Content,
            Order = 330)]
        [CultureSpecific]
        public virtual string SubTitle { get; set; }
    }
}

We are using the Alloy template as starting point and from this template is where you can find the abstract class SitePageData, if you do not have this class you can replace it with your own main abstract base page or directly use PageData.

In the code above, you can see that the property SubTitle uses the attribute, this will show that property only when you are in the main (first) site and hide it when you are in the second site.

Finally, to hide the property in the view we can use the helper we created before.

@using EpiExamples
@model PageViewModel<StandardPage>

@{ Layout = "~/Views/Shared/Layouts/_LeftNavigation.cshtml"; }

<h1 @Html.EditAttributes(x => x.CurrentPage.PageName)>@Model.CurrentPage.PageName</h1>

@if (MainSiteSwitchHelper.IsMainSite)
{
    <h2>
        @Html.PropertyFor(x => x.CurrentPage.SubTitle)
    </h2>
}

<p class="introduction" @Html.EditAttributes(x => x.CurrentPage.MetaDescription)>@Model.CurrentPage.MetaDescription</p>
<div class="row">
    <div class="span8 clearfix" @Html.EditAttributes(x => x.CurrentPage.MainBody)>
        @Html.DisplayFor(m => m.CurrentPage.MainBody)
    </div>
</div>
@Html.PropertyFor(x => x.CurrentPage.MainContentArea, new { CssClass = "row", Tag = Global.ContentAreaTags.TwoThirdsWidth })

And that is all. When your editor is in edit mode, they will be able to see the difference when they are modifying an standard page in the main site and in the second site.

I am sure there are better approaches out there to fulfill this requirements, but this one is fast and easy to implement. Feel free to criticize, I hope it will help someone and as always keep learning !!!

Written by:

Jorge Cardenas

Developer with several years of experience who is passionate about technology and how to solve problems through it.

View All Posts

Leave a Reply