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));
            }
        }
        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);
            }
        }
Exemple #3
0
        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();
            }));
        }
        /// <summary>
        /// Executes the callback.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="hasErrors">if set to <c>true</c> [has errors].</param>
        private void ExecuteCallback(ControllerContext context, bool hasErrors)
        {
            // Custom code
            var cacheKey = EpiServerDonutHelper.GenerateUniqueCacheKey(context);

            if (string.IsNullOrEmpty(cacheKey))
            {
                return;
            }

            var callback = context.HttpContext.Items[cacheKey] as Action <bool>;

            if (callback != null)
            {
                callback.Invoke(hasErrors);
            }
        }
        /// <summary>
        /// Called after an action result executes.
        /// </summary>
        /// <param name="filterContext">The filter context.</param>
        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            if (CacheSettings == null)
            {
                return;
            }

            var cacheKey = EpiServerDonutHelper.GenerateUniqueCacheKey(filterContext);

            // See OnActionExecuting
            ExecuteCallback(filterContext, filterContext.Exception != null);

            // If we are in the context of a child action, the main action is responsible for setting
            // the right HTTP Cache headers for the final response.
            if (!filterContext.IsChildAction)
            {
                CacheHeadersHelper.SetCacheHeaders(filterContext.HttpContext.Response, CacheSettings);
            }
        }
        /// <summary>
        /// Called before an action method executes.
        /// </summary>
        /// <param name="filterContext">The filter context.</param>
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            CacheSettings = BuildCacheSettings();

            // Custom Code
            var cacheKey = EpiServerDonutHelper.GenerateUniqueCacheKey(filterContext);

            // If we are unable to generate a cache key it means we can't do anything
            if (string.IsNullOrEmpty(cacheKey))
            {
                return;
            }

            // Are we actually storing data on the server side ?
            if (CacheSettings.IsServerCachingEnabled)
            {
                CacheItem cachedItem = null;

                // If the request is a POST, we lookup for NoCacheLookupForPosts option
                // We are fetching the stored value only if the option has not been set and the request is not a POST
                if (
                    (CacheSettings.Options & OutputCacheOptions.NoCacheLookupForPosts) != OutputCacheOptions.NoCacheLookupForPosts ||
                    filterContext.HttpContext.Request.HttpMethod != "POST"
                    )
                {
                    cachedItem = OutputCacheManager.GetItem(cacheKey);
                }

                // We have a cached version on the server side
                if (cachedItem != null)
                {
                    // We inject the previous result into the MVC pipeline
                    // The MVC action won't execute as we injected the previous cached result.

                    var donutReplacedHtml = DonutHoleFiller.ReplaceDonutHoleContent(cachedItem.Content, filterContext, CacheSettings.Options);

                    Logger.ErrorFormat("PRE DONUT HTML FROM CACHE {0} {1}", cacheKey, cachedItem.Content);
                    Logger.ErrorFormat("DONUT REPLACED HTML FROM CACHE {0} {1}", cacheKey, donutReplacedHtml);

                    filterContext.Result = new ContentResult
                    {
                        Content     = donutReplacedHtml,
                        ContentType = cachedItem.ContentType
                    };
                }
            }

            // Did we already injected something ?
            if (filterContext.Result != null)
            {
                return; // No need to continue
            }

            // We are hooking into the pipeline to replace the response Output writer
            // by something we own and later eventually gonna cache
            var cachingWriter = new StringWriter(CultureInfo.InvariantCulture);

            var originalWriter = filterContext.HttpContext.Response.Output;

            filterContext.HttpContext.Response.Output = cachingWriter;

            // Will be called back by OnResultExecuted -> ExecuteCallback
            filterContext.HttpContext.Items[cacheKey] = new Action <bool>(hasErrors =>
            {
                // Removing this executing action from the context
                filterContext.HttpContext.Items.Remove(cacheKey);

                // We restore the original writer for response
                filterContext.HttpContext.Response.Output = originalWriter;

                if (hasErrors)
                {
                    return; // Something went wrong, we are not going to cache something bad
                }

                var itemToRenderWithDonuts = cachingWriter.ToString();
                var originalWriterString   = originalWriter.ToString();
                // Now we use owned caching writer to actually store data
                var cacheItem = new CacheItem
                {
                    Content     = itemToRenderWithDonuts,
                    ContentType = filterContext.HttpContext.Response.ContentType
                };

                var donutRemovedHtml = DonutHoleFiller.RemoveDonutHoleWrappers(cacheItem.Content, filterContext, CacheSettings.Options);

                filterContext.HttpContext.Response.Write(donutRemovedHtml);

                Logger.ErrorFormat("PRE DONUT HTML LIVE {0} {1}", cacheKey, cacheItem.Content);
                Logger.ErrorFormat("DONUT REPLACED HTML LIVE {0} {1}", cacheKey, donutRemovedHtml);

                if (CacheSettings.IsServerCachingEnabled && filterContext.HttpContext.Response.StatusCode == 200)
                {
                    OutputCacheManager.AddItem(cacheKey, cacheItem, DateTime.UtcNow.AddSeconds(CacheSettings.Duration));
                }
            });
        }