/// <summary> /// Renders the macro output as a string /// </summary> /// <param name="macroAlias">The macro alias.</param> /// <param name="macroParams">The macro params.</param> /// <param name="currentControllerContext">The current controller context.</param> /// <param name="isForRichTextEditor">If the request is to render the contents in the back office rich text editor</param> /// <param name="resolveContent">The method to call in order to resolve the content to render.</param> /// <param name="resolveMember">The method to call in order to resolve the current member. If null, this parameter is ignored</param> /// <returns></returns> public string RenderMacroAsString( string macroAlias, IDictionary <string, string> macroParams, ControllerContext currentControllerContext, bool isForRichTextEditor, Func <Content> resolveContent, /* CurrentPage */ Func <Member> resolveMember /* CurrentMember */) { // if we're rendering inside the rich text editor, bypass all caching and return the fresh result. if (isForRichTextEditor) { return(GetMacroStringOutput( macroAlias, RenderMacro(macroAlias, macroParams, currentControllerContext, true, resolveContent), currentControllerContext)); } // Macro text is cached in the ApplicationCache based on it's parameters, se we need to build that cache key... // get the macro model var macroModel = GetMacroModel(macroAlias); // get the content id to pass in to the macro cache key builder. // null indicates not to cache by page. HiveId?contentId = null; if (macroModel.Item1.CacheByPage) { if (resolveContent != null) { contentId = resolveContent().Id; } } // get the member id to pass into the macro cache key builder. // null indicates not to cache by member. HiveId?memberId = null; if (macroModel.Item1.CachePersonalized) { if (resolveMember != null) { memberId = resolveMember().Id; } } // build the cache key of the macro var macroCacheKey = GetMacroCacheKey(macroAlias, macroParams, contentId, memberId); // now generate the content for it. string macroContent = null; string cachedMacroContent = null; cachedMacroContent = _applicationContext.FrameworkContext.ApplicationCache.GetOrCreate(macroCacheKey, () => { // generate the content of the macro, since it's not in the cache. macroContent = GetMacroStringOutput( macroAlias, RenderMacro(macroAlias, macroParams, currentControllerContext, false, resolveContent), currentControllerContext); // bail if cache period is zero. if (macroModel.Item1.CachePeriodSeconds <= 0) { return(null); } // return the cache parameters var cacheParams = new HttpRuntimeCacheParameters <string>(macroContent); if (macroModel.Item2 != null && macroModel.Item2 is File) { // add file dependency cacheParams.Dependencies = new CacheDependency(macroModel.Item2.RootedPath); } cacheParams.SlidingExpiration = new TimeSpan(0, 0, 0, macroModel.Item1.CachePeriodSeconds); return(cacheParams); }); // return either the cahed contnet or the generated content. return(cachedMacroContent ?? macroContent); }
/// <summary> /// Performs the action rendering /// </summary> /// <param name="macroAlias"></param> /// <param name="currentControllerContext"></param> /// <param name="isForRichTextEditor">If the request is to render the contents in the back office rich text editor</param> /// <param name="resolveContent">callback to get the 'Content' model</param> /// <param name="macroParams"></param> /// <returns></returns> /// <remarks> /// /// We need to check if this is for the rich text editor, in which case, we need to bypass any caching /// so that it renders out the correct content, /// Then if its not for the RTE, we need to check our cache to see if its in there, if so then we'll just /// return it, otherwise we will add the cached item with a dependency on our cache 'File' path. /// /// </remarks> public ActionResult RenderMacro( string macroAlias, IDictionary <string, string> macroParams, ControllerContext currentControllerContext, bool isForRichTextEditor, Func <Content> resolveContent) { ActionResult macroResult = null; if (!isForRichTextEditor) { //if its not for rich text.... try { var output = _applicationContext.FrameworkContext .ApplicationCache.GetOrCreate("umb-macro-" + macroAlias + macroParams.GetHashCode(), () => { var macroModel = GetMacroModel(macroAlias); //set the macroResult to the local variable macroResult = GetMacroResult(macroAlias, () => macroModel.Item1, resolveContent, macroParams, currentControllerContext); //if it is null, it means that there was no content item if (macroResult == null) { return(null); } //check if the macro should be cached at all if (!macroModel.Item1.CacheByPage) { //By returning null, this will not be added to the cache and a null value returned return(null); } //TODO: Check caching by member! //return our caching parameters //TODO: We might not want a 'normal' cache dependency at some point, need to determine a way to specify cache dependencies or create a custom one based on the 'File' object or something var cacheParams = new HttpRuntimeCacheParameters <ActionResult>(macroResult) { Dependencies = new CacheDependency(macroModel.Item2.RootedPath), SlidingExpiration = new TimeSpan(0, 0, 0, macroModel.Item1.CachePeriodSeconds) }; return(cacheParams); }); //if this is null, it means: // - there was no current node, or it didn't get cached because the macro definition said to not cache it. //then we can check if our local 'macroResult' variable was set, if so it means: // - there was a current node and it simply wasn't cached because of the macro definition. if (output != null) { return((ActionResult)output); } if (macroResult != null) { return(macroResult); } //return null because there must be no 'currentNode' return(null); } catch (ApplicationException ex) { //if there's an exception, display a friendly message and log the error var txt = "Macro.RenderingFailed.Message".Localize(this, new { Error = ex.Message, MacroName = macroAlias }); var title = "Macro.RenderingFailed.Title".Localize(); LogHelper.Error <MacroRenderer>(txt, ex); return(MacroError(txt, title)); } } else { try { //if it is for rich text... var macroModel = GetMacroModel(macroAlias); return(!macroModel.Item1.RenderContentInEditor ? NoRichTextRenderMode(macroAlias) : GetMacroResult(macroAlias, () => macroModel.Item1, resolveContent, macroParams, currentControllerContext)); } catch (ApplicationException ex) { //if there's an exception, display a friendly message and log the error var txt = "Macro.RenderingFailed.Message".Localize(this, new { Error = ex.Message, MacroName = macroAlias }); var title = "Macro.RenderingFailed.Title".Localize(); LogHelper.Error <MacroRenderer>(txt, ex); return(MacroError(txt, title)); } } }
/// <summary> /// Performs the action rendering /// </summary> /// <param name="macroAlias"></param> /// <param name="currentControllerContext"></param> /// <param name="isForRichTextEditor">If the request is to render the contents in the back office rich text editor</param> /// <param name="resolveContent">callback to get the 'Content' model</param> /// <param name="macroParams"></param> /// <returns></returns> /// <remarks> /// /// We need to check if this is for the rich text editor, in which case, we need to bypass any caching /// so that it renders out the correct content, /// Then if its not for the RTE, we need to check our cache to see if its in there, if so then we'll just /// return it, otherwise we will add the cached item with a dependency on our cache 'File' path. /// /// </remarks> public ActionResult RenderMacro( string macroAlias, IDictionary<string, string> macroParams, ControllerContext currentControllerContext, bool isForRichTextEditor, Func<Content> resolveContent) { ActionResult macroResult = null; if (!isForRichTextEditor) { //if its not for rich text.... try { var output = _applicationContext.FrameworkContext .ApplicationCache.GetOrCreate("umb-macro-" + macroAlias + macroParams.GetHashCode(), () => { var macroModel = GetMacroModel(macroAlias); //set the macroResult to the local variable macroResult = GetMacroResult(macroAlias, () => macroModel.Item1, resolveContent, macroParams, currentControllerContext); //if it is null, it means that there was no content item if (macroResult == null) return null; //check if the macro should be cached at all if (!macroModel.Item1.CacheByPage) { //By returning null, this will not be added to the cache and a null value returned return null; } //TODO: Check caching by member! //return our caching parameters //TODO: We might not want a 'normal' cache dependency at some point, need to determine a way to specify cache dependencies or create a custom one based on the 'File' object or something var cacheParams = new HttpRuntimeCacheParameters<ActionResult>(macroResult) { Dependencies = new CacheDependency(macroModel.Item2.RootedPath), SlidingExpiration = new TimeSpan(0, 0, 0, macroModel.Item1.CachePeriodSeconds) }; return cacheParams; }); //if this is null, it means: // - there was no current node, or it didn't get cached because the macro definition said to not cache it. //then we can check if our local 'macroResult' variable was set, if so it means: // - there was a current node and it simply wasn't cached because of the macro definition. if (output != null) return (ActionResult)output; if (macroResult != null) return macroResult; //return null because there must be no 'currentNode' return null; } catch (ApplicationException ex) { //if there's an exception, display a friendly message and log the error var txt = "Macro.RenderingFailed.Message".Localize(this, new { Error = ex.Message, MacroName = macroAlias }); var title = "Macro.RenderingFailed.Title".Localize(); LogHelper.Error<MacroRenderer>(txt, ex); return MacroError(txt, title); } } else { try { //if it is for rich text... var macroModel = GetMacroModel(macroAlias); return !macroModel.Item1.RenderContentInEditor ? NoRichTextRenderMode(macroAlias) : GetMacroResult(macroAlias, () => macroModel.Item1, resolveContent, macroParams, currentControllerContext); } catch (ApplicationException ex) { //if there's an exception, display a friendly message and log the error var txt = "Macro.RenderingFailed.Message".Localize(this, new { Error = ex.Message, MacroName = macroAlias }); var title = "Macro.RenderingFailed.Title".Localize(); LogHelper.Error<MacroRenderer>(txt, ex); return MacroError(txt, title); } } }
/// <summary> /// Renders the macro output as a string /// </summary> /// <param name="macroAlias">The macro alias.</param> /// <param name="macroParams">The macro params.</param> /// <param name="currentControllerContext">The current controller context.</param> /// <param name="isForRichTextEditor">If the request is to render the contents in the back office rich text editor</param> /// <param name="resolveContent">The method to call in order to resolve the content to render.</param> /// <param name="resolveMember">The method to call in order to resolve the current member. If null, this parameter is ignored</param> /// <returns></returns> public string RenderMacroAsString( string macroAlias, IDictionary<string, string> macroParams, ControllerContext currentControllerContext, bool isForRichTextEditor, Func<Content> resolveContent, /* CurrentPage */ Func<Member> resolveMember /* CurrentMember */) { // if we're rendering inside the rich text editor, bypass all caching and return the fresh result. if (isForRichTextEditor) { return GetMacroStringOutput( macroAlias, RenderMacro(macroAlias, macroParams, currentControllerContext, true, resolveContent), currentControllerContext); } // Macro text is cached in the ApplicationCache based on it's parameters, se we need to build that cache key... // get the macro model var macroModel = GetMacroModel(macroAlias); // get the content id to pass in to the macro cache key builder. // null indicates not to cache by page. HiveId? contentId = null; if (macroModel.Item1.CacheByPage) { if (resolveContent != null) contentId = resolveContent().Id; } // get the member id to pass into the macro cache key builder. // null indicates not to cache by member. HiveId? memberId = null; if (macroModel.Item1.CachePersonalized) { if (resolveMember != null) memberId = resolveMember().Id; } // build the cache key of the macro var macroCacheKey = GetMacroCacheKey(macroAlias, macroParams, contentId, memberId); // now generate the content for it. string macroContent = null; string cachedMacroContent = null; cachedMacroContent = _applicationContext.FrameworkContext.ApplicationCache.GetOrCreate(macroCacheKey, () => { // generate the content of the macro, since it's not in the cache. macroContent = GetMacroStringOutput( macroAlias, RenderMacro(macroAlias, macroParams, currentControllerContext, false, resolveContent), currentControllerContext); // bail if cache period is zero. if (macroModel.Item1.CachePeriodSeconds <= 0) return null; // return the cache parameters var cacheParams = new HttpRuntimeCacheParameters<string>(macroContent); if (macroModel.Item2 != null && macroModel.Item2 is File) { // add file dependency cacheParams.Dependencies = new CacheDependency(macroModel.Item2.RootedPath); } cacheParams.SlidingExpiration = new TimeSpan(0, 0, 0, macroModel.Item1.CachePeriodSeconds); return cacheParams; }); // return either the cahed contnet or the generated content. return cachedMacroContent ?? macroContent; }