// 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)
    {
        IUmbracoContext umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext();

        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.RenderAsync(
                                                               macroAlias,
                                                               umbracoContext.PublishedRequest?.PublishedContent,

                                                               // needs to be explicitly casted to Dictionary<string, object>
                                                               macroAttributes.ConvertTo(x => (string)x, x => x) !).GetAwaiter().GetResult().Text));

            return(sb.ToString());
        }
    }
Example #2
0
    private async Task <IActionResult> GetMacroResultAsHtml(string?macroAlias, int pageId,
                                                            IDictionary <string, object>?macroParams)
    {
        IMacro?m = macroAlias is null ? null : _macroService.GetByAlias(macroAlias);

        if (m == null)
        {
            return(NotFound());
        }

        IUmbracoContext   umbracoContext   = _umbracoContextAccessor.GetRequiredUmbracoContext();
        IPublishedContent?publishedContent = umbracoContext.Content?.GetById(true, pageId);

        //if it isn't supposed to be rendered in the editor then return an empty string
        //currently we cannot render a macro if the page doesn't yet exist
        if (pageId == -1 || publishedContent == null || m.DontRender)
        {
            //need to create a specific content result formatted as HTML since this controller has been configured
            //with only json formatters.
            return(Content(string.Empty, "text/html", Encoding.UTF8));
        }


        // When rendering the macro in the backoffice the default setting would be to use the Culture of the logged in user.
        // Since a Macro might contain thing thats related to the culture of the "IPublishedContent" (ie Dictionary keys) we want
        // to set the current culture to the culture related to the content item. This is hacky but it works.

        // fixme
        // in a 1:1 situation we do not handle the language being edited
        // so the macro renders in the wrong language

        var culture = DomainUtilities.GetCultureFromDomains(publishedContent.Id, publishedContent.Path, null,
                                                            umbracoContext, _siteDomainHelper);

        if (culture != null)
        {
            Thread.CurrentThread.CurrentCulture       =
                Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(culture);
        }

        // must have an active variation context!
        _variationContextAccessor.VariationContext = new VariationContext(culture);

        using (umbracoContext.ForcedPreview(true))
        {
            //need to create a specific content result formatted as HTML since this controller has been configured
            //with only json formatters.
            return(Content(
                       (await _componentRenderer.RenderMacroForContent(publishedContent, m.Alias, macroParams)).ToString() ??
                       string.Empty, "text/html",
                       Encoding.UTF8));
        }
    }