/// <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); }
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(); } }
/// <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); }
/// <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); }
/// <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"); }
/// <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); }
/// <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); }
/// <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); } }