Exemplo n.º 1
0
        /// <summary>
        /// Renders the macro with the specified alias, passing in the specified parameters.
        /// </summary>
        /// <param name="alias">The macro alias.</param>
        /// <param name="parameters">The parameters.</param>
        /// <param name="content">The content used for macro rendering</param>
        /// <returns></returns>
        private IHtmlString RenderMacro(IPublishedContent content, string alias, IDictionary <string, object> parameters)
        {
            if (content == null)
            {
                throw new ArgumentNullException(nameof(content));
            }

            // TODO: We are doing at ToLower here because for some insane reason the UpdateMacroModel method looks for a lower case match. the whole macro concept needs to be rewritten.
            //NOTE: the value could have HTML encoded values, so we need to deal with that
            var macroProps = parameters?.ToDictionary(
                x => x.Key.ToLowerInvariant(),
                i => (i.Value is string) ? HttpUtility.HtmlDecode(i.Value.ToString()) : i.Value);

            string html = _macroRenderer.Render(alias, content, macroProps).GetAsText();

            return(new HtmlString(html));
        }
Exemplo n.º 2
0
        // NOT thread-safe over a request because it modifies the
        // global UmbracoContext.Current.InPreviewMode status. So it
        // should never execute in // over the same UmbracoContext with
        // different preview modes.
        private string RenderRteMacros(string source, bool preview)
        {
            var umbracoContext = _umbracoContextAccessor.UmbracoContext;

            using (umbracoContext.ForcedPreview(preview)) // force for macro rendering
            {
                var sb = new StringBuilder();

                MacroTagParser.ParseMacros(
                    source,
                    //callback for when text block is found
                    textBlock => sb.Append(textBlock),
                    //callback for when macro syntax is found
                    (macroAlias, macroAttributes) => sb.Append(_macroRenderer.Render(
                                                                   macroAlias,
                                                                   umbracoContext.PublishedRequest?.PublishedContent,
                                                                   //needs to be explicitly casted to Dictionary<string, object>
                                                                   macroAttributes.ConvertTo(x => (string)x, x => x)).GetAsText()));

                return(sb.ToString());
            }
        }
        /// <summary>
        /// Renders the macro with the specified alias, passing in the specified parameters.
        /// </summary>
        /// <param name="alias">The macro alias.</param>
        /// <param name="parameters">The parameters.</param>
        /// <param name="content">The content used for macro rendering</param>
        /// <returns></returns>
        private IHtmlString RenderMacro(string alias, IDictionary <string, object> parameters, IPublishedContent content)
        {
            if (content == null)
            {
                throw new ArgumentNullException(nameof(content));
            }

            // TODO: We are doing at ToLower here because for some insane reason the UpdateMacroModel method looks for a lower case match. the whole macro concept needs to be rewritten.
            //NOTE: the value could have HTML encoded values, so we need to deal with that
            var macroProps = parameters.ToDictionary(
                x => x.Key.ToLowerInvariant(),
                i => (i.Value is string) ? HttpUtility.HtmlDecode(i.Value.ToString()) : i.Value);

            var macroControl = _macroRenderer.Render(alias, content, macroProps).GetAsControl();

            string html;

            if (macroControl is LiteralControl control)
            {
                // no need to execute, we already have text
                html = control.Text;
            }
            else
            {
                using (var containerPage = new FormlessPage())
                {
                    containerPage.Controls.Add(macroControl);

                    using (var output = new StringWriter())
                    {
                        // .Execute() does a PushTraceContext/PopTraceContext and writes trace output straight into 'output'
                        // and I do not see how we could wire the trace context to the current context... so it creates dirty
                        // trace output right in the middle of the page.
                        //
                        // The only thing we can do is fully disable trace output while .Execute() runs and restore afterwards
                        // which means trace output is lost if the macro is a control (.ascx or user control) that is invoked
                        // from within Razor -- which makes sense anyway because the control can _not_ run correctly from
                        // within Razor since it will never be inserted into the page pipeline (which may even not exist at all
                        // if we're running MVC).
                        //
                        // I'm sure there's more things that will get lost with this context changing but I guess we'll figure
                        // those out as we go along. One thing we lose is the content type response output.
                        // http://issues.umbraco.org/issue/U4-1599 if it is setup during the macro execution. So
                        // here we'll save the content type response and reset it after execute is called.

                        var contentType    = _umbracoContextAccessor.UmbracoContext.HttpContext.Response.ContentType;
                        var traceIsEnabled = containerPage.Trace.IsEnabled;
                        containerPage.Trace.IsEnabled = false;
                        _umbracoContextAccessor.UmbracoContext.HttpContext.Server.Execute(containerPage, output, true);
                        containerPage.Trace.IsEnabled = traceIsEnabled;
                        //reset the content type
                        _umbracoContextAccessor.UmbracoContext.HttpContext.Response.ContentType = contentType;

                        //Now, we need to ensure that local links are parsed
                        html = TemplateUtilities.ParseInternalLinks(output.ToString(), _umbracoContextAccessor.UmbracoContext.UrlProvider);
                    }
                }
            }

            return(new HtmlString(html));
        }