August 16, 2017

Episerver Shared Content with *Partial* Override Control





I was asked to create a quick proof of concept for sharing content between sites in Episerver. While there are many ways to do this, I wanted to create one that allowed for only part of the content to be overridden while the rest was enforced from the parent. The View shows how the output to the page can be determined on whether there is content available.

I don't claim it to be perfect nor production-ready. Just a bit of fun and a PoC.



ReferencePage

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

namespace Multisite.Models.Pages
{
    [ContentType(DisplayName = "ReferencePage", GUID = "ba2e770e-867c-4b80-9535-3672832f7e32", Description = "")]
    public class ReferencePage : StandardPage
    {
        [Display(
            Name = "Referenced Content",
            GroupName = SystemTabNames.Content,
            Order = 0)]
        [Required]
        public virtual PageReference ReferencedContent { get; set; }
    }
}

ViewModel

using EPiServer;
using EPiServer.ServiceLocation;
using Multisite.Models.Pages;

namespace Multisite.Models.ViewModels
{
    public class ReferencePageViewModel : PageViewModel
    {
        public StandardPage ReferencedPage { get; set; }

        public ReferencePageViewModel(ReferencePage currentPage) : base(currentPage)
        {
            base.CurrentPage = currentPage;
            LoadReferencedContent(currentPage);
        }

        private void LoadReferencedContent(ReferencePage currentPage)
        {
            var contentLoader = ServiceLocator.Current.GetInstance();
            ReferencedPage = contentLoader.Get(currentPage.ReferencedContent);
        }
    }
}

Controller

using System.Web.Mvc;
using EPiServer;
using EPiServer.Framework.DataAnnotations;
using EPiServer.Web.Mvc;
using Multisite.Models.Pages;
using Multisite.Models.ViewModels;

namespace Multisite.Controllers
{
    [TemplateDescriptor(Default = true, ModelType = typeof(ReferencePage), Inherited = false)]
    public class ReferencePageController : PageController
    {
        public ActionResult Index(ReferencePage currentPage)
        {
            var model = new ReferencePageViewModel(currentPage);
            return View(string.Format("~/Views/{0}/Index.cshtml", currentPage.GetOriginalType().Name), model);
        }
    }
}

View

@using Multisite
@model ReferencePageViewModel

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

<h1 @Html.EditAttributes(x => x.CurrentPage.PageName)>@Model.CurrentPage.PageName</h1>
<p class="introduction" @Html.EditAttributes(x => x.CurrentPage.MetaDescription)>
    @Model.CurrentPage.MetaDescription
</p>
<div class="row">
    <div class="span8 clearfix">
        @(Model.CurrentPage.MainBody != null && !Model.CurrentPage.MainBody.IsEmpty ? Html.DisplayFor(m => m.CurrentPage.MainBody) : Html.DisplayFor(m => m.ReferencedPage.MainBody))
    </div>
</div>
@(Model.CurrentPage.MainContentArea != null && 
        Model.CurrentPage.MainContentArea.Items != null && 
        Model.CurrentPage.MainContentArea.Items.Any() == false ? 
        Html.PropertyFor(x => x.CurrentPage.MainContentArea, new { CssClass = "row", Tag = Global.ContentAreaTags.TwoThirdsWidth }) :
        Html.DisplayFor(x => x.ReferencedPage.MainContentArea, new { CssClass = "row", Tag = Global.ContentAreaTags.TwoThirdsWidth }))



Happy coding!

1 comment:

Valdis Iljuconoks said...

please don't use ServiceLocator :) at least Injected could be one of the options..