private static async Task <Attempt <UrlInfo?> > DetectCollisionAsync( ILogger logger, IContent content, string url, string culture, IUmbracoContext umbracoContext, IPublishedRouter publishedRouter, ILocalizedTextService textService, IVariationContextAccessor variationContextAccessor, UriUtility uriUtility) { // test for collisions on the 'main' URL var uri = new Uri(url.TrimEnd(Constants.CharArrays.ForwardSlash), UriKind.RelativeOrAbsolute); if (uri.IsAbsoluteUri == false) { uri = uri.MakeAbsolute(umbracoContext.CleanedUmbracoUrl); } uri = uriUtility.UriToUmbraco(uri); IPublishedRequestBuilder builder = await publishedRouter.CreateRequestAsync(uri); IPublishedRequest pcr = await publishedRouter.RouteRequestAsync(builder, new RouteRequestOptions(RouteDirection.Outbound)); if (!pcr.HasPublishedContent()) { const string logMsg = nameof(DetectCollisionAsync) + " did not resolve a content item for original url: {Url}, translated to {TranslatedUrl} and culture: {Culture}"; logger.LogDebug(logMsg, url, uri, culture); var urlInfo = UrlInfo.Message(textService.Localize("content", "routeErrorCannotRoute"), culture); return(Attempt.Succeed(urlInfo)); } if (pcr.IgnorePublishedContentCollisions) { return(Attempt <UrlInfo?> .Fail()); } if (pcr.PublishedContent?.Id != content.Id) { IPublishedContent?o = pcr.PublishedContent; var l = new List <string>(); while (o != null) { l.Add(o.Name(variationContextAccessor) !); o = o.Parent; } l.Reverse(); var s = "/" + string.Join("/", l) + " (id=" + pcr.PublishedContent?.Id + ")"; var urlInfo = UrlInfo.Message(textService.Localize("content", "routeError", new[] { s }), culture); return(Attempt.Succeed(urlInfo)); } // no collision return(Attempt <UrlInfo?> .Fail()); }
/// <inheritdoc/> public async Task ExecuteResultAsync(ActionContext context) { HttpResponse response = context.HttpContext.Response; response.Clear(); response.StatusCode = StatusCodes.Status404NotFound; IPublishedRequest frequest = _umbracoContext.PublishedRequest; var reason = "Cannot render the page at URL '{0}'."; if (frequest.HasPublishedContent() == false) { reason = "No umbraco document matches the URL '{0}'."; } else if (frequest.HasTemplate() == false) { reason = "No template exists to render the document at URL '{0}'."; } var viewResult = new ViewResult { ViewName = "~/umbraco/UmbracoWebsite/NotFound.cshtml" }; context.HttpContext.Items.Add("reason", string.Format(reason, WebUtility.HtmlEncode(_umbracoContext.OriginalRequestUrl.PathAndQuery))); context.HttpContext.Items.Add("message", _message); await viewResult.ExecuteResultAsync(context); }
/// <summary> /// Gets the <see cref="UmbracoRouteResult" /> /// </summary> public static UmbracoRouteResult GetRouteResult(this IPublishedRequest publishedRequest) { if (publishedRequest.IsRedirect()) { return(UmbracoRouteResult.Redirect); } if (!publishedRequest.HasPublishedContent()) { return(UmbracoRouteResult.NotFound); } return(UmbracoRouteResult.Success); }
/// <summary> /// Special check for when no template or hijacked route is done which needs to re-run through the routing pipeline /// again for last chance finders /// </summary> private async Task <UmbracoRouteValues> CheckNoTemplateAsync( HttpContext httpContext, UmbracoRouteValues def, bool hasHijackedRoute) { IPublishedRequest request = def.PublishedRequest; // Here we need to check if there is no hijacked route and no template assigned but there is a content item. // If this is the case we want to return a blank page. // We also check if templates have been disabled since if they are then we're allowed to render even though there's no template, // for example for json rendering in headless. if (request.HasPublishedContent() && !request.HasTemplate() && !_umbracoFeatures.Disabled.DisableTemplates && !hasHijackedRoute) { IPublishedContent?content = request.PublishedContent; // This is basically a 404 even if there is content found. // We then need to re-run this through the pipeline for the last // chance finders to work. // Set to null since we are telling it there is no content. request = await _publishedRouter.UpdateRequestAsync(request, null); if (request == null) { throw new InvalidOperationException( $"The call to {nameof(IPublishedRouter.UpdateRequestAsync)} cannot return null"); } string?customActionName = GetTemplateName(request); def = new UmbracoRouteValues( request, def.ControllerActionDescriptor, customActionName); // if the content has changed, we must then again check for hijacked routes if (content != request.PublishedContent) { def = CheckHijackedRoute(httpContext, def, out _); } } return(def); }
private PublishedContentNotFoundResult GetNoTemplateResult(IPublishedRequest pcr) { // missing template, so we're in a 404 here // so the content, if any, is a custom 404 page of some sort if (!pcr.HasPublishedContent()) { // means the builder could not find a proper document to handle 404 return(new PublishedContentNotFoundResult(UmbracoContext)); } if (!pcr.HasTemplate()) { // means the engine could find a proper document, but the document has no template // at that point there isn't much we can do return(new PublishedContentNotFoundResult( UmbracoContext, "In addition, no template exists to render the custom 404.")); } return(new PublishedContentNotFoundResult(UmbracoContext)); }
/// <inheritdoc/> public async Task ExecuteResultAsync(ActionContext context) { HttpResponse response = context.HttpContext.Response; response.Clear(); response.StatusCode = StatusCodes.Status404NotFound; IPublishedRequest frequest = _umbracoContext.PublishedRequest; var reason = "Cannot render the page at URL '{0}'."; if (frequest.HasPublishedContent() == false) { reason = "No umbraco document matches the URL '{0}'."; } else if (frequest.HasTemplate() == false) { reason = "No template exists to render the document at URL '{0}'."; } await response.WriteAsync("<html><body><h1>Page not found</h1>"); await response.WriteAsync("<h2>"); await response.WriteAsync(string.Format(reason, WebUtility.HtmlEncode(_umbracoContext.OriginalRequestUrl.PathAndQuery))); await response.WriteAsync("</h2>"); if (string.IsNullOrWhiteSpace(_message) == false) { await response.WriteAsync("<p>" + _message + "</p>"); } await response.WriteAsync("<p>This page can be replaced with a custom 404. Check the <a target='_blank' href='https://umbra.co/custom-error-pages'>documentation for <a href=\"https://our.umbraco.com/Documentation/Tutorials/Custom-Error-Pages/#404-errors\" target=\"_blank\">Custom 404 Error Pages</a>.</p>"); await response.WriteAsync("<p style=\"border-top: 1px solid #ccc; padding-top: 10px\"><small>This page is intentionally left ugly ;-)</small></p>"); await response.WriteAsync("</body></html>"); }
/// <summary> /// Gets a value indicating whether the request was successfully routed /// </summary> public static bool Success(this IPublishedRequest publishedRequest) => !publishedRequest.IsRedirect() && publishedRequest.HasPublishedContent();