示例#1
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 async Task <bool> TryFindContent(IPublishedRequestBuilder frequest)
        {
            if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext))
            {
                return(false);
            }
            IPublishedContent?node = null;

            // no alias if "/"
            if (frequest.Uri.AbsolutePath != "/")
            {
                node = FindContentByAlias(
                    umbracoContext !.Content,
                    frequest.Domain != null ? frequest.Domain.ContentId : 0,
                    frequest.Culture,
                    frequest.AbsolutePathDecoded);

                if (node != null)
                {
                    frequest.SetPublishedContent(node);
                    if (_logger.IsEnabled(LogLevel.Debug))
                    {
                        _logger.LogDebug("Path '{UriAbsolutePath}' is an alias for id={PublishedContentId}", frequest.Uri.AbsolutePath, node.Id);
                    }
                }
            }

            return(node != null);
        }
        private async Task SetUmbracoRouteValues(ActionExecutingContext context, IPublishedContent content)
        {
            if (content != null)
            {
                IUmbracoContextAccessor umbracoContextAccessor = context.HttpContext.RequestServices.GetRequiredService <IUmbracoContextAccessor>();
                IPublishedRouter        router = context.HttpContext.RequestServices.GetRequiredService <IPublishedRouter>();

                var umbracoContext = umbracoContextAccessor.GetRequiredUmbracoContext();

                IPublishedRequestBuilder requestBuilder = await router.CreateRequestAsync(umbracoContext.CleanedUmbracoUrl);

                requestBuilder.SetPublishedContent(content);
                IPublishedRequest publishedRequest = requestBuilder.Build();

                var routeValues = new UmbracoRouteValues(
                    publishedRequest,
                    (ControllerActionDescriptor)context.ActionDescriptor);

                context.HttpContext.Features.Set(routeValues);
            }
            else
            {
                // if there is no content then it should be a not found
                context.Result = new NotFoundResult();
            }
        }
        /// <summary>
        /// Tries to find an Umbraco document for a <c>PublishedRequest</c> and a route.
        /// </summary>
        /// <returns>The document node, or null.</returns>
        protected IPublishedContent FindContent(IPublishedRequestBuilder docreq, string route)
        {
            if (!UmbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext))
            {
                return(null);
            }

            if (docreq == null)
            {
                throw new System.ArgumentNullException(nameof(docreq));
            }

            _logger.LogDebug("Test route {Route}", route);

            IPublishedContent node = umbracoContext.Content.GetByRoute(umbracoContext.InPreviewMode, route, culture: docreq.Culture);

            if (node != null)
            {
                docreq.SetPublishedContent(node);
                _logger.LogDebug("Got content, id={NodeId}", node.Id);
            }
            else
            {
                _logger.LogDebug("No match.");
            }

            return(node);
        }
示例#4
0
    private async Task SetUmbracoRouteValues(ActionExecutingContext context, IPublishedContent?content)
    {
        if (content != null)
        {
            UriUtility uriUtility = context.HttpContext.RequestServices.GetRequiredService <UriUtility>();

            var originalRequestUrl = new Uri(context.HttpContext.Request.GetEncodedUrl());
            Uri cleanedUrl         = uriUtility.UriToUmbraco(originalRequestUrl);

            IPublishedRouter router = context.HttpContext.RequestServices.GetRequiredService <IPublishedRouter>();

            IPublishedRequestBuilder requestBuilder = await router.CreateRequestAsync(cleanedUrl);

            requestBuilder.SetPublishedContent(content);
            IPublishedRequest publishedRequest = requestBuilder.Build();

            var routeValues = new UmbracoRouteValues(
                publishedRequest,
                (ControllerActionDescriptor)context.ActionDescriptor);

            context.HttpContext.Features.Set(routeValues);
        }
        else
        {
            // if there is no content then it should be a not found
            context.Result = new NotFoundResult();
        }
    }
示例#5
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);
        }
示例#6
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>
        /// <remarks>If successful, also assigns the template.</remarks>
        public override bool TryFindContent(IPublishedRequestBuilder frequest)
        {
            var path = frequest.AbsolutePathDecoded;

            if (frequest.Domain != null)
            {
                path = DomainUtilities.PathRelativeToDomain(frequest.Domain.Uri, path);
            }

            // no template if "/"
            if (path == "/")
            {
                _logger.LogDebug("No template in path '/'");
                return(false);
            }

            // look for template in last position
            var pos           = path.LastIndexOf('/');
            var templateAlias = path.Substring(pos + 1);

            path = pos == 0 ? "/" : path.Substring(0, pos);

            ITemplate template = _fileService.GetTemplate(templateAlias);

            if (template == null)
            {
                _logger.LogDebug("Not a valid template: '{TemplateAlias}'", templateAlias);
                return(false);
            }

            _logger.LogDebug("Valid template: '{TemplateAlias}'", templateAlias);

            // look for node corresponding to the rest of the route
            var route = frequest.Domain != null ? (frequest.Domain.ContentId + path) : path;
            IPublishedContent node = FindContent(frequest, route);

            if (node == null)
            {
                _logger.LogDebug("Not a valid route to node: '{Route}'", route);
                return(false);
            }

            // IsAllowedTemplate deals both with DisableAlternativeTemplates and ValidateAlternativeTemplates settings
            if (!node.IsAllowedTemplate(_contentTypeService, _webRoutingSettings, template.Id))
            {
                _logger.LogWarning("Alternative template '{TemplateAlias}' is not allowed on node {NodeId}.", template.Alias, node.Id);
                frequest.SetPublishedContent(null); // clear
                return(false);
            }

            // got it
            frequest.SetTemplate(template);
            return(true);
        }
示例#7
0
        /// <summary>
        /// Handles the published content (if any).
        /// </summary>
        /// <param name="request">The request builder.</param>
        /// <remarks>
        /// Handles "not found", internal redirects ...
        /// things that must be handled in one place because they can create loops
        /// </remarks>
        private void HandlePublishedContent(IPublishedRequestBuilder request)
        {
            // because these might loop, we have to have some sort of infinite loop detection
            int       i = 0, j = 0;
            const int maxLoop = 8;

            do
            {
                _logger.LogDebug("HandlePublishedContent: Loop {LoopCounter}", i);

                // handle not found
                if (request.PublishedContent == null)
                {
                    request.SetIs404();
                    _logger.LogDebug("HandlePublishedContent: No document, try last chance lookup");

                    // if it fails then give up, there isn't much more that we can do
                    if (_contentLastChanceFinder.TryFindContent(request) == false)
                    {
                        _logger.LogDebug("HandlePublishedContent: Failed to find a document, give up");
                        break;
                    }

                    _logger.LogDebug("HandlePublishedContent: Found a document");
                }

                // follow internal redirects as long as it's not running out of control ie infinite loop of some sort
                j = 0;
                while (FollowInternalRedirects(request) && j++ < maxLoop)
                {
                }

                // we're running out of control
                if (j == maxLoop)
                {
                    break;
                }

                // loop while we don't have page, ie the redirect or access
                // got us to nowhere and now we need to run the notFoundLookup again
                // as long as it's not running out of control ie infinite loop of some sort
            } while (request.PublishedContent == null && i++ < maxLoop);

            if (i == maxLoop || j == maxLoop)
            {
                _logger.LogDebug("HandlePublishedContent: Looks like we are running into an infinite loop, abort");
                request.SetPublishedContent(null);
            }

            _logger.LogDebug("HandlePublishedContent: End");
        }
示例#8
0
        /// <inheritdoc/>
        public bool TryFindContent(IPublishedRequestBuilder frequest)
        {
            if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext))
            {
                return(false);
            }
            if (int.TryParse(_requestAccessor.GetRequestValue("umbPageID"), NumberStyles.Integer, CultureInfo.InvariantCulture, out int pageId))
            {
                IPublishedContent doc = umbracoContext.Content.GetById(pageId);

                if (doc != null)
                {
                    frequest.SetPublishedContent(doc);
                    return(true);
                }
            }

            return(false);
        }
        public void Setting_Published_Content_Clears_Template_And_Redirect()
        {
            IPublishedRequestBuilder sut = GetBuilder();

            sut.SetTemplate(Mock.Of <ITemplate>());

            Assert.IsNotNull(sut.Template);

            sut.SetInternalRedirect(Mock.Of <IPublishedContent>());

            Assert.IsNull(sut.Template);
            Assert.IsTrue(sut.IsInternalRedirect);

            sut.SetTemplate(Mock.Of <ITemplate>());
            sut.SetPublishedContent(Mock.Of <IPublishedContent>());

            Assert.IsNull(sut.Template);
            Assert.IsFalse(sut.IsInternalRedirect);
        }
示例#10
0
    /// <summary>
    ///     Tries to find an Umbraco document for a <c>PublishedRequest</c> and a route.
    /// </summary>
    /// <returns>The document node, or null.</returns>
    protected IPublishedContent?FindContent(IPublishedRequestBuilder docreq, string route)
    {
        if (!UmbracoContextAccessor.TryGetUmbracoContext(out IUmbracoContext? umbracoContext))
        {
            return(null);
        }

        if (docreq == null)
        {
            throw new ArgumentNullException(nameof(docreq));
        }

        if (_logger.IsEnabled(LogLevel.Debug))
        {
            _logger.LogDebug("Test route {Route}", route);
        }

        IPublishedContent?node =
            umbracoContext.Content?.GetByRoute(umbracoContext.InPreviewMode, route, culture: docreq.Culture);

        if (node != null)
        {
            docreq.SetPublishedContent(node);
            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug("Got content, id={NodeId}", node.Id);
            }
        }
        else
        {
            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug("No match.");
            }
        }

        return(node);
    }
示例#11
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);
            }
            _logger.LogDebug("Looking for a page to handle 404.");

            int?domainContentId = null;

            // try to find a culture as best as we can
            string errorCulture = CultureInfo.CurrentUICulture.Name;

            if (frequest.Domain != null)
            {
                errorCulture    = frequest.Domain.Culture;
                domainContentId = frequest.Domain.ContentId;
            }
            else
            {
                var route = frequest.AbsolutePathDecoded;
                var pos   = route.LastIndexOf('/');
                IPublishedContent node = null;
                while (pos > 1)
                {
                    route = route.Substring(0, pos);
                    node  = umbracoContext.Content.GetByRoute(route, culture: frequest?.Culture);
                    if (node != null)
                    {
                        break;
                    }

                    pos = route.LastIndexOf('/');
                }

                if (node != null)
                {
                    Domain d = DomainUtilities.FindWildcardDomainInPath(umbracoContext.PublishedSnapshot.Domains.GetAll(true), node.Path, null);
                    if (d != null)
                    {
                        errorCulture = d.Culture;
                    }
                }
            }

            var error404 = NotFoundHandlerHelper.GetCurrentNotFoundPageId(
                _contentSettings.Error404Collection.ToArray(),
                _entityService,
                new PublishedContentQuery(umbracoContext.PublishedSnapshot, _variationContextAccessor, _examineManager),
                errorCulture,
                domainContentId);

            IPublishedContent content = null;

            if (error404.HasValue)
            {
                _logger.LogDebug("Got id={ErrorNodeId}.", error404.Value);

                content = umbracoContext.Content.GetById(error404.Value);

                _logger.LogDebug(content == null
                    ? "Could not find content with that id."
                    : "Found corresponding content.");
            }
            else
            {
                _logger.LogDebug("Got nothing.");
            }

            frequest
            .SetPublishedContent(content)
            .SetIs404();

            return(content != 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);
        }
    }