<repo_name>jondjones/JonDJones.Episerver.DonutCaching<file_sep>/JonDJones.Com/Controllers/Pages/StartPageController.cs
﻿using System.Web.Mvc;
using JonDJones.Com.Core.Pages;

using EPiServer.Core;
using JonDJones.Com.Core.ViewModel;
using JonDJones.Com.Controllers.Base;
using JonDJones.Com.Core.ViewModel.Pages;
using DevTrends.MvcDonutCaching;
using DevTrends.MvcDonutCaching.Annotations;
using System;
using System.Web.Providers.Entities;
using System.Web;

using EPiServer.Web.Routing;
using EPiServer;
using EPiServer.ServiceLocation;
using JonDJones.Com.DonutHoleCaching;

namespace JonDJones.Com.Controllers.Pages
{
    public class StartPageController : BasePageController<StartPage>
    {
        [EpiServerDonutCache(Duration = 24 * 3600)]
        public ActionResult Index(StartPage currentPage)
        {
            return View("Index", new StartPageViewModel(currentPage, EpiServerDependencies));
        }

        public ActionResult ExpirePage()
        {
            Expire("32:0::HomePage");
            Expire("110:0::Donut One");
            Expire("113:0::Donut Two");
            Expire("112:0::Nested Donut");

            PageData startPage =
                   ServiceLocator.Current.GetInstance<IContentRepository>().Get<PageData>(ContentReference.StartPage);

            // get URL of the start page
            var startPageUrl = ServiceLocator.Current.GetInstance<UrlResolver>()
                        .GetVirtualPath(startPage.ContentLink, startPage.LanguageBranch);

            return Redirect("/");
        }

        public ActionResult ExpireDonutOne()
        {
            Expire("110:0::Donut One");
            return View("Index", CreateViewExpireModel());
        }

        public ActionResult ExpireDonutTwo()
        {
            Expire("113:0::Donut Two");
            return View("Index", CreateViewExpireModel());
        }

        private void Expire(string key)
        {
            OutputCache.Instance.Remove(key);
        }


        private StartPageViewModel CreateViewExpireModel()
        {
            var pageRouteHelper = EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance<EPiServer.Web.Routing.PageRouteHelper>();
            var currentPage = pageRouteHelper.Page as StartPage;

            var startPage = new StartPageViewModel(currentPage, EpiServerDependencies);
            startPage.Refreshed = true;

            return startPage;
        }

        public OutputCacheManager OutputCacheManager
        {
            get;
            [UsedImplicitly]
            set;
        }
    }
}<file_sep>/JonDJones.com.Core/Entities/Location.cs
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JonDJones.com.Core.Entities
{
    public class Award
    {
        public string AwardName { get; set; }

        public string Year { get; set; }
    }
}
<file_sep>/JonDJones.Com.DonutHoleCaching/DonutHtmlHelper.cs
﻿using EPiServer.Core;
using EPiServer.Web.Mvc.Html;
using EPiServer.ServiceLocation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using System.Web.Routing;
using System.Linq.Expressions;
using DevTrends.MvcDonutCaching;
using System.IO;

namespace JonDJones.Com.DonutHoleCaching
{
    public static class DonutHtmlHelper
    {
        public static void DonutHole(this HtmlHelper htmlHelper, ContentArea contentArea)
        {
            ServiceLocator.Current.GetInstance<DonutContentRenderer>().Render(htmlHelper, contentArea);
        }

        public static void DonutForContentArea(this HtmlHelper htmlHelper, ContentArea contentArea)
        {
            ServiceLocator.Current.GetInstance<DonutContentRenderer>().Render(htmlHelper, contentArea);
        }

        public static void DonutForContentArea(this HtmlHelper htmlHelper, ContentArea contentArea, object additionalViewData)
        {
            var additionalValues = new RouteValueDictionary(additionalViewData);

            foreach (var value in additionalValues)
            {
                htmlHelper.ViewContext.ViewData.Add(value.Key, value.Value);
            }

            ServiceLocator.Current.GetInstance<DonutContentRenderer>().Render(htmlHelper, contentArea);
        }

        public static void DonutForContent(this HtmlHelper htmlHelper, IContent content)
        {
            var serialisedContent = EpiServerDonutHelper.SerializeBlockContentReference(content);

            using (var textWriter = new StringWriter())
            {
                var cutomHtmlHelper = EpiServerDonutHelper.CreateHtmlHelper(htmlHelper.ViewContext.Controller, textWriter);
                EpiServerDonutHelper.RenderContentData(cutomHtmlHelper, content, string.Empty);

                var outputString = string.Format("<!--Donut#{0}#-->{1}<!--EndDonut-->", serialisedContent, textWriter);

                var htmlString =  new XhtmlString(outputString);
                htmlHelper.RenderXhtmlString(htmlString);
            }
        }
    }
}
<file_sep>/JonDJones.Com/Controllers/Blocks/DonutExampleBlockController.cs
﻿
using DevTrends.MvcDonutCaching;
using EPiServer.Framework.DataAnnotations;
using JonDJones.com.Core.Blocks;
using JonDJones.com.Core.Resources;
using JonDJones.com.Core.ViewModel.Blocks;
using JonDJones.Com.Controllers.Base;
using JonDJones.Com.DonutHoleCaching;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace JonDJones.Com.Controllers.Blocks
{
    public class DonutExampleBlockController : BaseBlockController<DonutExampleBlock>
    {
        [ChildActionOnly, EpiServerDonutCache(Duration = 60, Options = OutputCacheOptions.ReplaceDonutsInChildActions)]
        public override ActionResult Index(DonutExampleBlock currentBlock)
        {
            var displayTag = GetDisplayOptionTag();
            return PartialView("Index",
                               new DonutExampleBlockViewModel(currentBlock,
                               EpiServerDependencies,
                               displayTag));
        }
    }
}<file_sep>/JonDJones.Com.DonutHoleCaching/EpiServerDonutHelper.cs
﻿using EPiServer;
using EPiServer.Core;
using EPiServer.Framework.Web;
using EPiServer.ServiceLocation;
using EPiServer.Web;
using EPiServer.Web.Mvc;
using EPiServer.Web.Mvc.Html;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace JonDJones.Com.DonutHoleCaching
{
    public static class EpiServerDonutHelper
    {
        public static readonly string OpenDisplayTag = "<!--OpenTagOpen-->(.*?)<!--OpenTagClose-->";

        public static readonly string CloseDisplayTag = "<!--CloseTagOpen-->(.*?)<!--CloseTagClose-->";

        public static readonly string DonutTag = "<!--Donut#(.*?)#-->(.*?)<!--EndDonut-->";

        public static readonly string DisplayTagSwap = ">(.*?)<";

        private static readonly string TempCacheKey = "temp";

        public static System.Web.Mvc.HtmlHelper CreateHtmlHelper(ControllerBase controller, TextWriter textWriter)
        {
            var viewContext = new ViewContext(
                controller.ControllerContext,
                new WebFormView(controller.ControllerContext, TempCacheKey),
                controller.ViewData,
                controller.TempData,
                textWriter
            );

            return new HtmlHelper(viewContext, new ViewPage());
        }

        public static void RenderContentData(HtmlHelper html,
                                             IContentData content,
                                             string tag)
        {
            var templateResolver = ServiceLocator.Current.GetInstance<TemplateResolver>();
            var templateModel = templateResolver.Resolve(
                html.ViewContext.HttpContext,
                content.GetOriginalType(),
                content,
                TemplateTypeCategories.MvcPartial,
                tag);

            var contentRenderer = ServiceLocator.Current.GetInstance<IContentRenderer>();
            html.RenderContentData(
                content,
                true,
                templateModel,
                contentRenderer);
        }

        public static string GenerateUniqueCacheKey(ControllerContext filterContext)
        {
            if (filterContext.Controller.ControllerContext.RouteData.Values["currentContent"] == null)
            {
                var pageRouteHelper = ServiceLocator.Current.GetInstance<EPiServer.Web.Routing.PageRouteHelper>();

                var currentPage = pageRouteHelper.Page;

                var key = GenerateUniqueKey(currentPage);
                return key;
            }

            var blockContentReference = filterContext.Controller
                                             .ControllerContext
                                             .RouteData
                                             .Values["currentContent"] as IContent;

            if (blockContentReference != null)
            {
                var key = GenerateUniqueKey(blockContentReference);
                return key;
            }

            return null;
        }


        public static string CreateContentAreaDonutTag(TagBuilder tagBuilder,
                                                       string donutUniqueId,
                                                       string contentToRender)
        {
            var donutTagHtml = new StringBuilder();

            var startTag = Regex.Replace(OpenDisplayTag,
                                         DisplayTagSwap,
                                         string.Format(">{0}<", tagBuilder.ToString(TagRenderMode.StartTag)));

            var endTag = Regex.Replace(CloseDisplayTag,
                                       DisplayTagSwap,
                                       string.Format(">{0}<", tagBuilder.ToString(TagRenderMode.EndTag)));

            donutTagHtml.Append(startTag);
            donutTagHtml.Append(contentToRender);
            donutTagHtml.Append(endTag);

            var outputString = string.Format("<!--Donut#{0}#-->{1}<!--EndDonut-->", donutUniqueId, donutTagHtml.ToString());

            return outputString;
        }

        public static string SerializeBlockContentReference(IContent content)
        {
            return JsonConvert.SerializeObject(content.ContentLink);
        }

        private static string GenerateUniqueKey(IContent content)
        {
            return string.Format("{0}:{1}:{2}:{3}", content.ContentLink.ID,
                                                    content.ContentLink.WorkID,
                                                    content.ContentLink.ProviderName,
                                                    content.Name);
        }
    }
}
<file_sep>/JonDJones.com.Core/Blocks/NestedDonutBlock.cs
﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.DataAnnotations;

namespace JonDJones.com.Core.Blocks
{
    [ContentType(DisplayName = "Nested Donut Block",
        GUID = "e9b68cf4-8f65-4082-9163-c037c498b0b8",
        Description = "Nested Donut Block")]
    public class NestedDonutBlock : BlockData
    {
    }
}<file_sep>/packages/EPiServer.Forms.1.1.2.9000/readme.txt
﻿EPiServer.Forms


Installation
============
Forms is released as a standard nuget package, please use Visual Studio Nuget console management and run
install-package Episerver.Forms


Please go to http://webhelp.episerver.com/15-5/EN/addons/episerver-forms/episerver-forms.htm for more topics targeted to editors and merchandisers/marketers, configuration and customization.<file_sep>/JonDJones.Com.DonutHoleCaching/EpiServerDonutHoleFiller.cs
﻿using System.IO;
using System.Text.RegularExpressions;
using System.Web.Mvc;
using DevTrends.MvcDonutCaching;
using EPiServer;
using EPiServer.Core;
using EPiServer.Framework.Web;
using EPiServer.ServiceLocation;
using EPiServer.Web;
using EPiServer.Web.Mvc;
using EPiServer.Web.Mvc.Html;
using Newtonsoft.Json;
using System;
using EPiServer.DataAbstraction;
using System.Text;

namespace JonDJones.Com.DonutHoleCaching
{
    public class EpiServerDonutHoleFiller : DonutHoleFiller
    {
        private static readonly Regex DonutHoleRegex = new Regex(EpiServerDonutHelper.DonutTag, RegexOptions.Compiled | RegexOptions.Singleline);

        private static readonly Regex OpenTagRegex = new Regex(EpiServerDonutHelper.OpenDisplayTag,
                                                             RegexOptions.Compiled | RegexOptions.Singleline);

        private static readonly Regex CloseTagRegex = new Regex(EpiServerDonutHelper.CloseDisplayTag,
                                                             RegexOptions.Compiled | RegexOptions.Singleline);

        public EpiServerDonutHoleFiller(IActionSettingsSerialiser actionSettingsSerialiser)
            : base(actionSettingsSerialiser)
        {
        }

        public string ReplaceDonutHoleContent(string content, ControllerContext filterContext, OutputCacheOptions options)
        {
            if (filterContext.IsChildAction &&
                (options & OutputCacheOptions.ReplaceDonutsInChildActions) != OutputCacheOptions.ReplaceDonutsInChildActions)
                return content;

            return DonutHoleRegex.Replace(content, match =>
            {
                var contentReference = JsonConvert.DeserializeObject<ContentReference>(match.Groups[1].Value);

                if (contentReference == null)
                    return null;

                var htmlToRenderWithoutDonutComment = new StringBuilder();

                using (var stringWriter = new StringWriter())
                {
                    var htmlHelper = EpiServerDonutHelper.CreateHtmlHelper(filterContext.Controller, stringWriter);

                    var repo = ServiceLocator.Current.GetInstance<IContentRepository>();
                    var epiContentToRender = repo.Get<IContent>(contentReference);

                    var openTag = OpenTagRegex.Match(match.Groups[1].ToString()).Groups[1].ToString();

                    if (!string.IsNullOrEmpty(openTag))
                        htmlToRenderWithoutDonutComment.Append(openTag);

                    EpiServerDonutHelper.RenderContentData(htmlHelper, epiContentToRender, string.Empty);
                    htmlToRenderWithoutDonutComment.Append(stringWriter.ToString());

                    var closeTag = CloseTagRegex.Match(match.Groups[1].ToString()).Groups[1].ToString();

                    if (!string.IsNullOrEmpty(closeTag))
                        htmlToRenderWithoutDonutComment.Append(closeTag);
                }

                return htmlToRenderWithoutDonutComment.ToString();
            });
        }
    }
}<file_sep>/JonDJones.Com/Global.asax.cs
﻿using System;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.UI.WebControls;
using System.Web.Http;
using EPiServer.Web.Routing;
using System.Collections.Generic;
using EPiServer.Core;
using EPiServer.Web.Routing.Segments;
using EPiServer;
using EPiServer.ServiceLocation;
using System.Web;

namespace JonDJones.Com
{
    public class EPiServerApplication : EPiServer.Global
    {
        protected void Application_Start()
        {
            ViewEngines.Engines.Insert(0, new CustomViewEngine());

            AreaRegistration.RegisterAllAreas();
        }


        protected override void RegisterRoutes(RouteCollection routes)
        {
            base.RegisterRoutes(routes);
        }

        public override string GetVaryByCustomString(HttpContext context, string arg)
        {
            if (arg == "MyKey")
            {
                object o = context.Application["MyGuid"];
                if (o == null)
                {
                    o = Guid.NewGuid();
                    context.Application["MyGuid"] = o;
                }
                return o.ToString();
            }
            return base.GetVaryByCustomString(context, arg);
        }
    }
}<file_sep>/JonDJones.Com/Controllers/Blocks/NestDonutBlockController.cs
﻿
using DevTrends.MvcDonutCaching;
using EPiServer.Framework.DataAnnotations;
using JonDJones.com.Core.Blocks;
using JonDJones.com.Core.Resources;
using JonDJones.com.Core.ViewModel.Blocks;
using JonDJones.Com.Controllers.Base;
using JonDJones.Com.DonutHoleCaching;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace JonDJones.Com.Controllers.Blocks
{
    public class NestDonutBlockController : BaseBlockController<NestedDonutBlock>
    {
        [ChildActionOnly, EpiServerDonutCache(Duration = 5)]
        public override ActionResult Index(NestedDonutBlock currentBlock)
        {
            var displayTag = GetDisplayOptionTag();
            return PartialView("Index",
                               new NestedDonutBlockViewModel(currentBlock,
                               EpiServerDependencies,
                               displayTag));
        }
    }
}<file_sep>/JonDJones.com.Core/Blocks/DonutTwoExampleBlock.cs
﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.DataAnnotations;

namespace JonDJones.com.Core.Blocks
{
    [ContentType(DisplayName = "Donut Two Example Block",
        GUID = "dea37095-d991-4030-b3e0-d4a17475d06a",
        Description = "Donut Two Example")]
    public class DonutTwoExampleBlock : BlockData
    {
    }
}<file_sep>/JonDJones.Com.DonutHoleCaching/DonutContentRenderer.cs
﻿using DevTrends.MvcDonutCaching;
using EPiServer;
using EPiServer.Core;
using EPiServer.Web;
using EPiServer.Web.Mvc;
using EPiServer.Web.Mvc.Html;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace JonDJones.Com.DonutHoleCaching
{
    public class DonutContentRenderer : ContentAreaRenderer
    {
        public DonutContentRenderer(IContentRenderer contentRenderer,
                                    TemplateResolver templateResolver,
                                    ContentFragmentAttributeAssembler attributeAssembler,
                                    IContentRepository contentRepository,
                                    DisplayOptions displayOptions)
            : base(contentRenderer, templateResolver, attributeAssembler, contentRepository, displayOptions)
        {
        }

        protected override void RenderContentAreaItem(
            HtmlHelper htmlHelper,
            ContentAreaItem contentAreaItem,
            string templateTag,
            string htmlTag,
            string cssClass)
        {
            var content = contentAreaItem.GetContent(ContentRepository);
            if (content == null)
                return;

            var serialisedContent = EpiServerDonutHelper.SerializeBlockContentReference(content);

            using (var textWriter = new StringWriter())
            {
                var cutomHtmlHelper = EpiServerDonutHelper.CreateHtmlHelper(htmlHelper.ViewContext.Controller, textWriter);
                EpiServerDonutHelper.RenderContentData(cutomHtmlHelper, content, string.Empty);

                var tagBuilder = CreateContentAreaSeperatorHtmlTags(contentAreaItem, htmlTag, cssClass);
                var epiServerHtml = EpiServerDonutHelper.CreateContentAreaDonutTag(tagBuilder, serialisedContent, textWriter.ToString());

                htmlHelper.RenderXhtmlString(new XhtmlString(epiServerHtml));
            }
        }

        private TagBuilder CreateContentAreaSeperatorHtmlTags(ContentAreaItem contentAreaItem, string htmlTag, string cssClass)
        {
            var tagBuilder = new TagBuilder(htmlTag);
            AddNonEmptyCssClass(tagBuilder, cssClass);
            BeforeRenderContentAreaItemStartTag(tagBuilder, contentAreaItem);
            return tagBuilder;
        }

    }
}<file_sep>/JonDJones.com.Core/ViewModel/Pages/StartPageViewModel.cs
﻿using EPiServer.Core;
using JonDJones.Com.Core.Pages;
using JonDJones.Com.Core;
using JonDJones.Com.Core.ViewModel.Base;
using System.Collections.Generic;
using System.Linq;
using System;

namespace JonDJones.Com.Core.ViewModel.Pages
{
    public class StartPageViewModel : BaseViewModel<StartPage>
    {
        private readonly IEpiServerDependencies _epiServerDependencies;

        private readonly StartPage _currentPage;

        public StartPageViewModel(StartPage currentPage, IEpiServerDependencies epiServerDependencies)
            : base(currentPage)
        {
            _epiServerDependencies = epiServerDependencies;
        }

        public string TheTime
        {
            get
            {
                return DateTime.Now.ToString("HH:mm:ss");
            }
        }

        public bool Refreshed { get; set; }
    }
}<file_sep>/JonDJones.com.Core/PropertyList/AwardProperty.cs
﻿using EPiServer.Core;
using EPiServer.Framework.Serialization;
using EPiServer.PlugIn;
using EPiServer.ServiceLocation;
using JonDJones.com.Core.Entities;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JonDJones.com.Core.PropertyList
{
    [PropertyDefinitionTypePlugIn]
    public class AwardProperty : PropertyList<Award>
    {
        protected override Award ParseItem(string value)    
        {
            return JsonConvert.DeserializeObject<Award>(value); 
        }     
        
        public override PropertyData ParseToObject(string value)    
        {        
            ParseToSelf(value);        
            return this;    
        }  
    }
}
