using System.Globalization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models.PublishedContent; namespace Umbraco.Web.Routing { /// /// Provides an implementation of that handles page identifiers. /// /// /// Handles /1234 where 1234 is the identified of a document. /// public class ContentFinderByIdPath : IContentFinder { private readonly ILogger _logger; private readonly IRequestAccessor _requestAccessor; private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly WebRoutingSettings _webRoutingSettings; /// /// Initializes a new instance of the class. /// public ContentFinderByIdPath( IOptions webRoutingSettings, ILogger logger, IRequestAccessor requestAccessor, IUmbracoContextAccessor umbracoContextAccessor) { _webRoutingSettings = webRoutingSettings.Value ?? throw new System.ArgumentNullException(nameof(webRoutingSettings)); _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); _requestAccessor = requestAccessor ?? throw new System.ArgumentNullException(nameof(requestAccessor)); _umbracoContextAccessor = umbracoContextAccessor ?? throw new System.ArgumentNullException(nameof(umbracoContextAccessor)); } /// /// Tries to find and assign an Umbraco document to a PublishedRequest. /// /// The PublishedRequest. /// A value indicating whether an Umbraco document was found and assigned. public bool TryFindContent(IPublishedRequestBuilder frequest) { IUmbracoContext umbCtx = _umbracoContextAccessor.UmbracoContext; if (umbCtx == null || (umbCtx != null && umbCtx.InPreviewMode == false && _webRoutingSettings.DisableFindContentByIdPath)) { return false; } IPublishedContent node = null; var path = frequest.Uri.GetAbsolutePathDecoded(); var nodeId = -1; // no id if "/" if (path != "/") { var noSlashPath = path.Substring(1); if (int.TryParse(noSlashPath, out nodeId) == false) { nodeId = -1; } if (nodeId > 0) { _logger.LogDebug("Id={NodeId}", nodeId); node = umbCtx.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(CultureInfo.GetCultureInfo(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; } } }