/// <summary> /// Gets the CMS Page using Dynamic Routing, returning the culture variation that either matches the given culture or the Slug's culture, or the default site culture if not found. /// </summary> /// <param name="Url">The Url (part after the domain), if empty will use the Current Request</param> /// <param name="Culture">The Culture, not needed if the Url contains the culture that the UrlSlug has as part of it's generation.</param> /// <param name="SiteName">The Site Name, defaults to current site.</param> /// <param name="Columns">List of columns you wish to include in the data returned.</param> /// <param name="AddPageToCacheDependency">If true, the found page will have it's DocumentID added to the request's Output Cache Dependency</param> /// <returns>The Page that matches the Url Slug, for the given or matching culture (or default culture if one isn't found).</returns> public ITreeNode GetPage(string Url = "", string Culture = "", string SiteName = "", IEnumerable <string> Columns = null, bool AddPageToCacheDependency = true) { // Load defaults SiteName = (!string.IsNullOrWhiteSpace(SiteName) ? SiteName : DynamicRouteInternalHelper.SiteContextSafe().SiteName); string DefaultCulture = DynamicRouteInternalHelper.SiteContextSafe().DefaultVisitorCulture; if (string.IsNullOrWhiteSpace(Url)) { Url = EnvironmentHelper.GetUrl(HttpContext.Current.Request.Url.AbsolutePath, HttpContext.Current.Request.ApplicationPath, SiteName); } // Handle Preview, during Route Config the Preview isn't available and isn't really needed, so ignore the thrown exception bool PreviewEnabled = false; try { PreviewEnabled = HttpContext.Current.Kentico().Preview().Enabled; } catch (InvalidOperationException) { } GetCultureEventArgs CultureArgs = new GetCultureEventArgs() { DefaultCulture = DefaultCulture, SiteName = SiteName, Request = HttpContext.Current.Request, PreviewEnabled = PreviewEnabled, Culture = Culture }; using (var DynamicRoutingGetCultureTaskHandler = DynamicRoutingEvents.GetCulture.StartEvent(CultureArgs)) { // If Preview is enabled, use the Kentico Preview CultureName if (PreviewEnabled && string.IsNullOrWhiteSpace(CultureArgs.Culture)) { try { CultureArgs.Culture = HttpContext.Current.Kentico().Preview().CultureName; } catch (Exception) { } } // If culture still not set, use the LocalizationContext.CurrentCulture if (string.IsNullOrWhiteSpace(CultureArgs.Culture)) { try { CultureArgs.Culture = LocalizationContext.CurrentCulture.CultureCode; } catch (Exception) { } } // If that fails then use the System.Globalization.CultureInfo if (string.IsNullOrWhiteSpace(CultureArgs.Culture)) { try { CultureArgs.Culture = System.Globalization.CultureInfo.CurrentCulture.Name; } catch (Exception) { } } DynamicRoutingGetCultureTaskHandler.FinishEvent(); } // set the culture Culture = CultureArgs.Culture; // Convert Columns to string, must include DocumentID though at all times if (Columns != null && !Columns.Contains("*") && !Columns.Contains("documentid", StringComparer.InvariantCultureIgnoreCase)) { var Appended = Columns.ToList(); Appended.Add("documentid"); Columns = Appended; } string ColumnsVal = Columns != null?string.Join(",", Columns.Distinct()) : "*"; // Create GetPageEventArgs Event ARgs GetPageEventArgs Args = new GetPageEventArgs() { RelativeUrl = Url, Culture = Culture, DefaultCulture = DefaultCulture, SiteName = SiteName, PreviewEnabled = PreviewEnabled, ColumnsVal = ColumnsVal, Request = HttpContext.Current.Request }; // Run any GetPage Event hooks which allow the users to set the Found Page ITreeNode FoundPage = null; using (var DynamicRoutingGetPageTaskHandler = DynamicRoutingEvents.GetPage.StartEvent(Args)) { if (Args.FoundPage == null) { try { Args.FoundPage = CacheHelper.Cache <TreeNode>(cs => { // Using custom query as Kentico's API was not properly handling a Join and where. DataTable NodeTable = ConnectionHelper.ExecuteQuery("DynamicRouting.UrlSlug.GetDocumentsByUrlSlug", new QueryDataParameters() { { "@Url", Url }, { "@Culture", Culture }, { "@DefaultCulture", DefaultCulture }, { "@SiteName", SiteName } }, topN: 1, columns: "DocumentID, ClassName").Tables[0]; if (NodeTable.Rows.Count > 0) { int DocumentID = ValidationHelper.GetInteger(NodeTable.Rows[0]["DocumentID"], 0); string ClassName = ValidationHelper.GetString(NodeTable.Rows[0]["ClassName"], ""); DocumentQuery Query = DocumentHelper.GetDocuments(ClassName) .WhereEquals("DocumentID", DocumentID) .CombineWithAnyCulture(); // Handle Columns if (!string.IsNullOrWhiteSpace(ColumnsVal)) { Query.Columns(ColumnsVal); } // Handle Preview if (PreviewEnabled) { Query.LatestVersion(true) .Published(false); } else { Query.Published(); } TreeNode Page = Query.FirstOrDefault(); // Cache dependencies on the Url Slugs and also the DocumentID if available. if (cs.Cached) { cs.CacheDependency = CacheHelper.GetCacheDependency(new string[] { "dynamicrouting.urlslug|all", "documentid|" + DocumentID }); } // Return Page Data return(Query.FirstOrDefault()); } else { return(null); } }, new CacheSettings((PreviewEnabled ? 0 : 1440), "DynamicRoutine.GetPage", Url, Culture, DefaultCulture, SiteName, PreviewEnabled, ColumnsVal)); } catch (Exception ex) { // Add exception so they can handle DynamicRoutingGetPageTaskHandler.EventArguments.ExceptionOnLookup = ex; } } // Finish event, this will trigger the After DynamicRoutingGetPageTaskHandler.FinishEvent(); // Return whatever Found Page FoundPage = DynamicRoutingGetPageTaskHandler.EventArguments.FoundPage; } // Add documentID to the output cache dependencies, we ensured that DocumentID would be returned in the result always. if (FoundPage != null && AddPageToCacheDependency && HttpContext.Current != null && HttpContext.Current.Response != null) { string Key = $"documentid|{FoundPage.DocumentID}"; CacheHelper.EnsureDummyKey(Key); HttpContext.Current.Response.AddCacheItemDependency(Key); } return(FoundPage); }
/// <summary> /// Can override this if you need to implement custom logic, such as a custom route. httpContext.Request.RequestContext.RouteData.Values is often used to grab route data. /// </summary> /// <param name="httpContext">The HttpContext of the request</param> /// <returns>The Tree Node for this request, null acceptable.</returns> private TreeNode GetTreeNode(HttpContextBase httpContext) { TreeNode FoundNode = null; string SiteName = SiteContextSafe().SiteName; string DefaultCulture = SiteContextSafe().DefaultVisitorCulture; // Create GetPage Event Arguments GetPageEventArgs PageArgs = new GetPageEventArgs() { RelativeUrl = GetUrl(httpContext.Request.Url.AbsolutePath, httpContext.Request.ApplicationPath, SiteName), HttpContext = httpContext, SiteName = SiteName, Culture = GetCulture(), DefaultCulture = DefaultCulture }; // Start event, allow user to overwrite FoundPage using (var KenticoAuthorizeGetPageTaskHandler = AuthorizeEvents.GetPage.StartEvent(PageArgs)) { if (PageArgs.FoundPage == null) { IPageDataContextRetriever PageContextRetriever = DependencyResolver.Current.GetService <IPageDataContextRetriever>(); var PageContext = PageContextRetriever.Retrieve <TreeNode>(); // Try using Kentico's Page Builder Data Context if (PageContext != null && PageContext.Page != null) { PageArgs.FoundPage = PageContext.Page; } else { try { // Try to find the page from node alias path, default lookup type PageArgs.FoundPage = CacheHelper.Cache(cs => { TreeNode Page = DocumentHelper.GetDocuments() .Path(PageArgs.RelativeUrl, PathTypeEnum.Single) .Culture(!string.IsNullOrWhiteSpace(PageArgs.Culture) ? PageArgs.Culture : PageArgs.DefaultCulture) .CombineWithAnyCulture() .CombineWithDefaultCulture() .OnSite(PageArgs.SiteName) .Columns("NodeACLID", "NodeID", "DocumentID", "DocumentCulture") // The Fields required for authorization .FirstOrDefault(); if (cs.Cached && Page != null) { cs.CacheDependency = CacheHelper.GetCacheDependency(new string[] { $"nodeid|{Page.NodeID}", $"documentid|{Page.DocumentID}" }); } return(Page); }, new CacheSettings(1440, "KenticoAuthorizeGetTreeNode", PageArgs.RelativeUrl, PageArgs.SiteName)); } catch (Exception ex) { PageArgs.ExceptionOnLookup = ex; } } } else if (PageArgs.FoundPage.NodeACLID <= 0) { PageArgs.ExceptionOnLookup = new NullReferenceException("The TreeNode does not contain the NodeACLID property, which is required for Permission lookup."); } // Finish the event KenticoAuthorizeGetPageTaskHandler.FinishEvent(); // Pass the Found Node back from the args FoundNode = PageArgs.FoundPage; } return(PageArgs.FoundPage); }
public static void OverrideGetPageEvent(object sender, GetPageEventArgs args) { string cultureCode = args.Culture; //Occasionally the culture code may come out as full text such as English - United Kingdom, using this info we can fetch the culture code if (args.Culture.Length > 5) { cultureCode = CultureInfoProvider.GetCultures().Where(a => a.CultureName == args.Culture).First().CultureCode; } UpdateCacheItem <string>("CurrentRelUrl", args.RelativeUrl); UpdateCacheItem <string>("CultureCode", cultureCode); if (args.FoundPage == null) { try { args.FoundPage = CacheHelper.Cache <TreeNode>(cs => { //TODO: ADD Culture DataTable PossibleUrlPatterns = GetPossibleUrls(args.RelativeUrl, cultureCode); if (PossibleUrlPatterns.Rows.Count > 0) { var matchedUrl = GetUrlMatch(args.RelativeUrl, cultureCode, PossibleUrlPatterns); if (matchedUrl == null || !matchedUrl.HasMatch) { return(null); } DocumentQuery Query = DocumentHelper.GetDocuments(matchedUrl.UrlBreakdown.KenticoData.ClassName).WhereEquals("NodeId", matchedUrl.UrlBreakdown.KenticoData.NodeId).CombineWithAnyCulture(); if (args.PreviewEnabled) { Query.LatestVersion(true).Published(false); } else { Query.PublishedVersion(true); } TreeNode page = Query.FirstOrDefault(); if (cs.Cached) { if (page != null) { cs.CacheDependency = CacheHelper.GetCacheDependency(new string[] { $"{WildcardUrlInfo.OBJECT_TYPE}|all", "documentid|" + page.DocumentID }); } else { cs.CacheDependency = CacheHelper.GetCacheDependency(new string[] { $"{WildcardUrlInfo.OBJECT_TYPE}dynamicrouting.wildcards|all" }); } } return(page); } else { return(null); } }, new CacheSettings(args.PreviewEnabled ? 0 : 1440, "DynamicRouting.GetPage", args.RelativeUrl, cultureCode, args.DefaultCulture, args.SiteName, args.PreviewEnabled, args.ColumnsVal)); } catch (Exception ex) { args.ExceptionOnLookup = ex; } if (args.FoundPage == null) { HttpContext.Current.Response.StatusCode = 404; } } }
/// <summary> /// Gets the CMS Page using Dynamic Routing, returning the culture variation that either matches the given culture or the Slug's culture, or the default site culture if not found. /// </summary> /// <param name="Url">The Url (part after the domain), if empty will use the Current Request</param> /// <param name="Culture">The Culture, not needed if the Url contains the culture that the UrlSlug has as part of it's generation.</param> /// <param name="SiteName">The Site Name, defaults to current site.</param> /// <param name="Columns">List of columns you wish to include in the data returned.</param> /// <returns>The Page that matches the Url Slug, for the given or matching culture (or default culture if one isn't found).</returns> public static ITreeNode GetPage(string Url = "", string Culture = "", string SiteName = "", IEnumerable <string> Columns = null) { // Load defaults SiteName = (!string.IsNullOrWhiteSpace(SiteName) ? SiteName : DynamicRouteInternalHelper.SiteContextSafe().SiteName); string DefaultCulture = DynamicRouteInternalHelper.SiteContextSafe().DefaultVisitorCulture; if (string.IsNullOrWhiteSpace(Url)) { Url = EnvironmentHelper.GetUrl(HttpContext.Current.Request.Url.AbsolutePath, HttpContext.Current.Request.ApplicationPath, SiteName); } // Handle Preview, during Route Config the Preview isn't available and isn't really needed, so ignore the thrown exception bool PreviewEnabled = false; try { PreviewEnabled = PortalContext.ViewMode != ViewModeEnum.LiveSite; } catch (InvalidOperationException) { } GetCultureEventArgs CultureArgs = new GetCultureEventArgs() { DefaultCulture = DefaultCulture, SiteName = SiteName, Request = HttpContext.Current.Request, PreviewEnabled = PreviewEnabled, Culture = Culture }; using (var DynamicRoutingGetCultureTaskHandler = DynamicRoutingEvents.GetCulture.StartEvent(CultureArgs)) { // If culture not set, use the LocalizationContext.CurrentCulture if (string.IsNullOrWhiteSpace(CultureArgs.Culture)) { try { CultureArgs.Culture = LocalizationContext.CurrentCulture.CultureName; } catch (Exception) { } } // if that fails then use the System.Globalization.CultureInfo if (string.IsNullOrWhiteSpace(CultureArgs.Culture)) { try { CultureArgs.Culture = System.Globalization.CultureInfo.CurrentCulture.Name; } catch (Exception) { } } DynamicRoutingGetCultureTaskHandler.FinishEvent(); } // set the culture Culture = CultureArgs.Culture; // Convert Columns to string ColumnsVal = Columns != null?string.Join(",", Columns.Distinct()) : "*"; // Create GetPageEventArgs Event ARgs GetPageEventArgs Args = new GetPageEventArgs() { RelativeUrl = Url, Culture = Culture, DefaultCulture = DefaultCulture, SiteName = SiteName, PreviewEnabled = PreviewEnabled, ColumnsVal = ColumnsVal, Request = HttpContext.Current.Request }; // Run any GetPage Event hooks which allow the users to set the Found Page ITreeNode FoundPage = null; using (var DynamicRoutingGetPageTaskHandler = DynamicRoutingEvents.GetPage.StartEvent(Args)) { if (Args.FoundPage == null) { try { // Get Page based on Url Args.FoundPage = CacheHelper.Cache <TreeNode>(cs => { // Using custom query as Kentico's API was not properly handling a Join and where. DataTable NodeTable = ConnectionHelper.ExecuteQuery("DynamicRouting.UrlSlug.GetDocumentsByUrlSlug", new QueryDataParameters() { { "@Url", Url }, { "@Culture", Culture }, { "@DefaultCulture", DefaultCulture }, { "@SiteName", SiteName }, { "@PreviewEnabled", PreviewEnabled } }, topN: 1, columns: "DocumentID, ClassName").Tables[0]; if (NodeTable.Rows.Count > 0) { int DocumentID = ValidationHelper.GetInteger(NodeTable.Rows[0]["DocumentID"], 0); string ClassName = ValidationHelper.GetString(NodeTable.Rows[0]["ClassName"], ""); DocumentQuery Query = DocumentHelper.GetDocuments(ClassName) .WhereEquals("DocumentID", DocumentID); // Handle Columns if (!string.IsNullOrWhiteSpace(ColumnsVal)) { Query.Columns(ColumnsVal); } // Handle Preview if (PreviewEnabled) { Query.LatestVersion(true) .Published(false); } else { Query.PublishedVersion(true); } TreeNode Page = Query.FirstOrDefault(); // Cache dependencies on the Url Slugs and also the DocumentID if available. if (cs.Cached) { if (Page != null) { cs.CacheDependency = CacheHelper.GetCacheDependency(new string[] { "dynamicrouting.urlslug|all", "dynamicrouting.versionhistoryurlslug|all", "dynamicrouting.versionhistoryurlslug|bydocumentid|" + Page.DocumentID, "documentid|" + Page.DocumentID, }); } else { cs.CacheDependency = CacheHelper.GetCacheDependency(new string[] { "dynamicrouting.urlslug|all", "dynamicrouting.versionhistoryurlslug|all" }); } } // Return Page Data return(Query.FirstOrDefault()); } else { return(null); } }, new CacheSettings(1440, "DynamicRoutine.GetPage", Url, Culture, DefaultCulture, SiteName, PreviewEnabled, ColumnsVal)); } catch (Exception ex) { // Add exception so they can handle DynamicRoutingGetPageTaskHandler.EventArguments.ExceptionOnLookup = ex; } } // Finish event, this will trigger the After DynamicRoutingGetPageTaskHandler.FinishEvent(); // Return whatever Found Page FoundPage = DynamicRoutingGetPageTaskHandler.EventArguments.FoundPage; } return(FoundPage); }
public Task <TreeNode> GetCustomPageAsync(GetPageEventArgs pageArgs, AuthorizationEventType eventType) { return(Task.FromResult <TreeNode>(null)); }
public async Task <TreeNode> GetCurrentPageAsync() { TreeNode foundNode = null; string SiteName = SiteContextSafe().SiteName; string DefaultCulture = SiteContextSafe().DefaultVisitorCulture; // Create GetPage Event Arguments GetPageEventArgs pageArgs = new GetPageEventArgs() { RelativeUrl = GetUrl(UriHelper.GetDisplayUrl(_httpContext.Request), (_httpContext.Request.PathBase.HasValue ? _httpContext.Request.PathBase.Value : ""), SiteName), HttpContext = _httpContext, SiteName = SiteName, Culture = await GetCultureAsync(), DefaultCulture = DefaultCulture }; var customTreeNode = await _authorizationContextCustomizer.GetCustomPageAsync(pageArgs, AuthorizationEventType.Before); if (customTreeNode != null) { if (customTreeNode.NodeACLID <= 0) { throw new NullReferenceException("The TreeNode does not contain the NodeACLID property, which is required for Permission lookup."); } foundNode = customTreeNode; } if (foundNode == null) { // Try to find the page from node alias path, default lookup type try { if (_pageDataContextRetriever.TryRetrieve <TreeNode>(out var pageContext)) { foundNode = pageContext.Page; } } catch (InvalidOperationException) { // this may be thrown for invalid pages or internal requests } if (foundNode == null) { foundNode = await _progressiveCache.LoadAsync(async cs => { var pages = await DocumentHelper.GetDocuments() .Path(pageArgs.RelativeUrl, PathTypeEnum.Single) .Culture(!string.IsNullOrWhiteSpace(pageArgs.Culture) ? pageArgs.Culture : pageArgs.DefaultCulture) .CombineWithAnyCulture() .CombineWithDefaultCulture() .OnSite(pageArgs.SiteName) .Columns("NodeACLID", "NodeID", "DocumentID", "DocumentCulture") // The Fields required for authorization .GetEnumerableTypedResultAsync(); var pageList = pages.ToList(); var page = pageList.FirstOrDefault(); if (cs.Cached && pageList.Any()) { cs.CacheDependency = CacheHelper.GetCacheDependency(new string[] { $"nodeid|{page.NodeID}", $"documentid|{page.DocumentID}" }); } return(page); }, new CacheSettings(1440, "KenticoAuthorizeGetTreeNode", pageArgs.RelativeUrl, pageArgs.SiteName)); } pageArgs.FoundPage = foundNode; var customTreeNodeAfter = await _authorizationContextCustomizer.GetCustomPageAsync(pageArgs, AuthorizationEventType.After); if (customTreeNodeAfter != null) { if (customTreeNode.NodeACLID <= 0) { new NullReferenceException("The TreeNode does not contain the NodeACLID property, which is required for Permission lookup."); } foundNode = pageArgs.FoundPage; } } return(foundNode); }