示例#1
0
        /// <summary>
        /// Looks for wildcard domains in the path and updates <c>Culture</c> accordingly.
        /// </summary>
        internal void HandleWildcardDomains(IPublishedRequestBuilder request)
        {
            const string tracePrefix = "HandleWildcardDomains: ";

            if (request.PublishedContent == null)
            {
                return;
            }

            var nodePath = request.PublishedContent.Path;

            _logger.LogDebug("{TracePrefix}Path={NodePath}", tracePrefix, nodePath);
            var    rootNodeId     = request.Domain != null ? request.Domain.ContentId : (int?)null;
            var    umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext();
            Domain domain         = DomainUtilities.FindWildcardDomainInPath(umbracoContext.PublishedSnapshot.Domains.GetAll(true), nodePath, rootNodeId);

            // always has a contentId and a culture
            if (domain != null)
            {
                request.SetCulture(domain.Culture);
                _logger.LogDebug("{TracePrefix}Got domain on node {DomainContentId}, set culture to {CultureName}", tracePrefix, domain.ContentId, request.Culture);
            }
            else
            {
                _logger.LogDebug("{TracePrefix}No match.", tracePrefix);
            }
        }
示例#2
0
        /// <summary>
        /// Tries to find and assign an Umbraco document to a <c>PublishedRequest</c>.
        /// </summary>
        /// <param name="frequest">The <c>PublishedRequest</c>.</param>
        /// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
        public bool TryFindContent(IPublishedRequestBuilder frequest)
        {
            if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext))
            {
                return(false);
            }
            if (umbracoContext == null || (umbracoContext != null && umbracoContext.InPreviewMode == false && _webRoutingSettings.DisableFindContentByIdPath))
            {
                return(false);
            }

            IPublishedContent node = null;
            var path = frequest.AbsolutePathDecoded;

            var nodeId = -1;

            // no id if "/"
            if (path != "/")
            {
                var noSlashPath = path.Substring(1);

                if (int.TryParse(noSlashPath, NumberStyles.Integer, CultureInfo.InvariantCulture, out nodeId) == false)
                {
                    nodeId = -1;
                }

                if (nodeId > 0)
                {
                    _logger.LogDebug("Id={NodeId}", nodeId);
                    node = umbracoContext.Content.GetById(nodeId);

                    if (node != null)
                    {
                        var cultureFromQuerystring = _requestAccessor.GetQueryStringValue("culture");

                        // if we have a node, check if we have a culture in the query string
                        if (!string.IsNullOrEmpty(cultureFromQuerystring))
                        {
                            // we're assuming it will match a culture, if an invalid one is passed in, an exception will throw (there is no TryGetCultureInfo method), i think this is ok though
                            frequest.SetCulture(cultureFromQuerystring);
                        }

                        frequest.SetPublishedContent(node);
                        _logger.LogDebug("Found node with id={PublishedContentId}", node.Id);
                    }
                    else
                    {
                        nodeId = -1; // trigger message below
                    }
                }
            }

            if (nodeId == -1)
            {
                _logger.LogDebug("Not a node id");
            }

            return(node != null);
        }
示例#3
0
    /// <summary>
    ///     Finds the site root (if any) matching the http request, and updates the PublishedRequest accordingly.
    /// </summary>
    /// <returns>A value indicating whether a domain was found.</returns>
    internal bool FindDomain(IPublishedRequestBuilder request)
    {
        const string tracePrefix = "FindDomain: ";

        // note - we are not handling schemes nor ports here.
        if (_logger.IsEnabled(LogLevel.Debug))
        {
            _logger.LogDebug("{TracePrefix}Uri={RequestUri}", tracePrefix, request.Uri);
        }

        IUmbracoContext umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext();
        IDomainCache?   domainsCache   = umbracoContext.PublishedSnapshot.Domains;
        var             domains        = domainsCache?.GetAll(false).ToList();

        // determines whether a domain corresponds to a published document, since some
        // domains may exist but on a document that has been unpublished - as a whole - or
        // that is not published for the domain's culture - in which case the domain does
        // not apply
        bool IsPublishedContentDomain(Domain domain)
        {
            // just get it from content cache - optimize there, not here
            IPublishedContent?domainDocument = umbracoContext.PublishedSnapshot.Content?.GetById(domain.ContentId);

            // not published - at all
            if (domainDocument == null)
            {
                return(false);
            }

            // invariant - always published
            if (!domainDocument.ContentType.VariesByCulture())
            {
                return(true);
            }

            // variant, ensure that the culture corresponding to the domain's language is published
            return(domain.Culture is not null && domainDocument.Cultures.ContainsKey(domain.Culture));
        }

        domains = domains?.Where(IsPublishedContentDomain).ToList();

        var defaultCulture = domainsCache?.DefaultCulture;

        // try to find a domain matching the current request
        DomainAndUri?domainAndUri = DomainUtilities.SelectDomain(domains, request.Uri, defaultCulture: defaultCulture);

        // handle domain - always has a contentId and a culture
        if (domainAndUri != null)
        {
            // matching an existing domain
            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug(
                    "{TracePrefix}Matches domain={Domain}, rootId={RootContentId}, culture={Culture}",
                    tracePrefix,
                    domainAndUri.Name,
                    domainAndUri.ContentId,
                    domainAndUri.Culture);
            }

            request.SetDomain(domainAndUri);

            // canonical? not implemented at the moment
            // if (...)
            // {
            //  _pcr.RedirectUrl = "...";
            //  return true;
            // }
        }
        else
        {
            // not matching any existing domain
            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug("{TracePrefix}Matches no domain", tracePrefix);
            }

            request.SetCulture(defaultCulture ?? CultureInfo.CurrentUICulture.Name);
        }

        if (_logger.IsEnabled(LogLevel.Debug))
        {
            _logger.LogDebug("{TracePrefix}Culture={CultureName}", tracePrefix, request.Culture);
        }

        return(request.Domain != null);
    }
    public async Task RenderAsync(int pageId, int?altTemplateId, StringWriter writer)
    {
        if (writer == null)
        {
            throw new ArgumentNullException(nameof(writer));
        }

        IUmbracoContext umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext();

        // instantiate a request and process
        // important to use CleanedUmbracoUrl - lowercase path-only version of the current URL, though this isn't going to matter
        // terribly much for this implementation since we are just creating a doc content request to modify it's properties manually.
        IPublishedRequestBuilder requestBuilder =
            await _publishedRouter.CreateRequestAsync(umbracoContext.CleanedUmbracoUrl);

        IPublishedContent?doc = umbracoContext.Content?.GetById(pageId);

        if (doc == null)
        {
            writer.Write("<!-- Could not render template for Id {0}, the document was not found -->", pageId);
            return;
        }

        // in some cases the UmbracoContext will not have a PublishedRequest assigned to it if we are not in the
        // execution of a front-end rendered page. In this case set the culture to the default.
        // set the culture to the same as is currently rendering
        if (umbracoContext.PublishedRequest == null)
        {
            ILanguage?defaultLanguage = _languageService.GetAllLanguages().FirstOrDefault();

            requestBuilder.SetCulture(defaultLanguage == null
                ? CultureInfo.CurrentUICulture.Name
                : defaultLanguage.IsoCode);
        }
        else
        {
            requestBuilder.SetCulture(umbracoContext.PublishedRequest.Culture);
        }

        // set the doc that was found by id
        requestBuilder.SetPublishedContent(doc);

        // set the template, either based on the AltTemplate found or the standard template of the doc
        var templateId = _webRoutingSettings.DisableAlternativeTemplates || !altTemplateId.HasValue
            ? doc.TemplateId
            : altTemplateId.Value;

        if (templateId.HasValue)
        {
            requestBuilder.SetTemplate(_fileService.GetTemplate(templateId.Value));
        }

        // if there is not template then exit
        if (requestBuilder.HasTemplate() == false)
        {
            if (altTemplateId.HasValue == false)
            {
                writer.Write(
                    "<!-- Could not render template for Id {0}, the document's template was not found with id {0}-->",
                    doc.TemplateId);
            }
            else
            {
                writer.Write(
                    "<!-- Could not render template for Id {0}, the altTemplate was not found with id {0}-->",
                    altTemplateId);
            }

            return;
        }

        // First, save all of the items locally that we know are used in the chain of execution, we'll need to restore these
        // after this page has rendered.
        SaveExistingItems(out IPublishedRequest? oldPublishedRequest);

        IPublishedRequest contentRequest = requestBuilder.Build();

        try
        {
            // set the new items on context objects for this templates execution
            SetNewItemsOnContextObjects(contentRequest);

            // Render the template
            ExecuteTemplateRendering(writer, contentRequest);
        }
        finally
        {
            // restore items on context objects to continuing rendering the parent template
            RestoreItems(oldPublishedRequest);
        }
    }