Ejemplo n.º 1
0
        public static DataRow GetCodeItem(string path)
        {
            //path is like this: DynamicAgilityCode/[ContentReferenceName]/[ItemReferenceName].ext
            var pre = Agility.Web.HttpModules.AgilityHttpModule.DynamicCodePrepend;

            string p1 = path.Substring(path.IndexOf(pre, StringComparison.CurrentCultureIgnoreCase) + pre.Length);

            if (p1.IndexOf("/") == -1 || p1.IndexOf(".") < p1.IndexOf("/"))
            {
                return(null);
            }

            string referenceName = p1.Substring(0, p1.IndexOf("/"));

            //get the content.
            var content = BaseCache.GetContent(referenceName, LANGUAGECODE_CODE, AgilityContext.WebsiteName);

            if (content == null ||
                content.DataSet == null ||
                (!content.DataSet.Tables.Contains("ContentItems")) ||
                content.DataSet.Tables["ContentItems"].Rows.Count == 0)
            {
                return(null);
            }

            int slashIndex = p1.IndexOf("/");
            int dotIndex   = p1.IndexOf(".");

            string itemReferenceName = p1.Substring(slashIndex + 1, dotIndex - slashIndex - 1);
            string filter            = string.Format("ReferenceName = '{0}'", itemReferenceName.Replace("'", "''"));

            StringBuilder sb = new StringBuilder();

            DataRow[] rows = null;
            try
            {
                rows = content.DataSet.Tables["ContentItems"].Select(filter);
            }
            catch { }


            if (rows == null || rows.Length == 0)
            {
                return(null);
            }


            DataRow row = rows[0];

            return(row);
        }
Ejemplo n.º 2
0
        public T GetContentItem <T>() where T : AgilityContentItem
        {
            var content = BaseCache.GetContent(ContentReferenceName, AgilityContext.LanguageCode, AgilityContext.WebsiteName, false);

            var row = content.GetItemByContentID(ContentID);

            if (row == null)
            {
                return(null);
            }

            Type            type   = typeof(T);
            ConstructorInfo constr = type.GetConstructor(System.Type.EmptyTypes);

            return(AgilityContentRepository <T> .ConvertDataRowToObject(constr, row, AgilityContext.LanguageCode, ContentReferenceName));
        }
        public object GetContentItemValue(string columnName)
        {
            if (row == null)
            {
                if (string.IsNullOrEmpty(LanguageCode))
                {
                    LanguageCode = AgilityContext.LanguageCode;
                }

                AgilityContent content = BaseCache.GetContent(ContentReferenceName, LanguageCode, AgilityContext.WebsiteName);
                row = content.GetItemByContentID(ContentID);
            }

            if (row != null && row.Table.Columns.Contains(columnName))
            {
                return(row[columnName]);
            }

            return(null);
        }
        private static void RedirectToDynamicPreviewUrl(Dictionary <string, AgilityRouteCacheItem> routes, string path, string languageCode)
        {
            List <string> urlPaths = new List <string>();

            string[] pathParts   = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
            string   staticRoute = string.Empty;

            AgilityRouteCacheItem routeItem = null;

            //keep some parent objects...
            AgilityPage            parentPage    = null;
            DynamicPageFormulaItem dpItemParent  = null;
            AgilityContent         parentContent = null;

            int previewContentID = -1;
            int previewVersionID = -1;

            if (!int.TryParse(AgilityContext.HttpContext.Request.Query["previewContentID"], out previewContentID))
            {
                if (!int.TryParse(AgilityContext.HttpContext.Request.Query["previewVersionID"], out previewVersionID))
                {
                    int.TryParse(AgilityContext.HttpContext.Request.Query["ContentID"], out previewContentID);
                }
            }

            foreach (string pathPart in pathParts)
            {
                string testStaticRoute = string.Format("{0}/{1}", staticRoute, pathPart);

                if (routes.TryGetValue(testStaticRoute, out routeItem))
                {
                    int pageID = routeItem.PageID;



                    //get the page...
                    AgilityPage page = BaseCache.GetPageFromID(pageID, languageCode, AgilityContext.WebsiteName, null);
                    if (page == null)
                    {
                        //if the page is null at this point, assume it's a folder page and jsut insert the static path...
                        urlPaths.Add(pathPart);
                        staticRoute = testStaticRoute;
                        continue;
                    }

                    string contentReferenceName = null;
                    int    parentContentID      = -1;



                    if (string.IsNullOrEmpty(page.DynamicPageContentViewReferenceName) &&
                        string.IsNullOrEmpty(page.DynamicPageParentFieldName))
                    {
                        //static page...
                        urlPaths.Add(pathPart);
                    }
                    else
                    {
                        //dynamic page..
                        if (!string.IsNullOrEmpty(page.DynamicPageContentViewReferenceName))
                        {
                            contentReferenceName = page.DynamicPageContentViewReferenceName;

                            if (!string.IsNullOrEmpty(page.DynamicPageParentFieldName))
                            {
                                if (parentPage == null || dpItemParent == null)
                                {
                                    return;
                                }

                                //we have to match up to the parent page...
                                parentContentID = dpItemParent.ContentID;
                            }
                        }
                        else if (!string.IsNullOrEmpty(page.DynamicPageParentFieldName))
                        {
                            //get the dynamic content from the PARENT page
                            if (parentPage == null || dpItemParent == null)
                            {
                                return;
                            }

                            object obj = dpItemParent.GetContentItemValue(page.DynamicPageParentFieldName);
                            if (obj != null)
                            {
                                contentReferenceName = string.Format("{0}", obj);
                            }
                        }

                        if (string.IsNullOrEmpty(contentReferenceName))
                        {
                            return;
                        }


                        //get the content first if we are in development or staging mode...
                        AgilityContentServer.AgilityContent content = BaseCache.GetContent(contentReferenceName, languageCode, AgilityContext.WebsiteName);


                        //get the dynamic content for this page
                        DynamicPageFormulaItemIndex dpIndex = BaseCache.GetDynamicPageFormulaIndex(pageID, contentReferenceName, languageCode, page, true);
                        if (dpIndex == null || dpIndex.Count == 0)
                        {
                            return;
                        }


                        DynamicPageFormulaItem dpItem = null;


                        //try to use the preview url
                        if (previewVersionID > 0 || previewContentID > 0)
                        {
                            DataRow row = null;
                            if (previewContentID > 0)
                            {
                                row = content.GetItemByContentID(previewContentID);
                            }
                            else
                            {
                                DataRow[] rows = content.DataSet.Tables["ContentItems"].Select(string.Format("VersionID = {0}", previewVersionID));
                                if (rows.Length > 0)
                                {
                                    row = rows[0];
                                }
                            }

                            if (row != null)
                            {
                                string pageName = string.Format("/{0}", DynamicPageFormulaItem.ResolveFormula(page.DynamicPageName, row, true)).ToLowerInvariant();
                                if (dpIndex.TryGetValue(pageName, out dpItem))
                                {
                                    //adjust the parent if we need to...
                                    if (!string.IsNullOrEmpty(page.DynamicPageParentFieldName) && dpItemParent != null)
                                    {
                                        //grab the parent id...
                                        object parentIDObj = dpItem.GetContentItemValue(page.DynamicPageParentFieldName);
                                        if (parentIDObj != null)
                                        {
                                            string parentIDStr = string.Format("{0}", parentIDObj);
                                            if (parentIDStr.IndexOf(",") != -1)
                                            {
                                                parentIDStr = parentIDStr.Substring(0, parentIDStr.IndexOf(","));
                                            }
                                            int adjustedParentID = -1;
                                            if (int.TryParse(parentIDStr, out adjustedParentID))
                                            {
                                                if (dpItemParent.ContentID != adjustedParentID)
                                                {
                                                    // if the parent id DOES NOT match, we need to do some URL jigging...
                                                    DataRow parentRow = parentContent.GetItemByContentID(adjustedParentID);

                                                    parentContentID = adjustedParentID;
                                                    if (parentRow != null)
                                                    {
                                                        //get the parent page name and switch it up in the url..
                                                        string parentPageName = string.Format("/{0}", DynamicPageFormulaItem.ResolveFormula(parentPage.DynamicPageName, parentRow, true)).ToLowerInvariant();
                                                        urlPaths[urlPaths.Count - 1] = parentPageName.Substring(1);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }


                        if (dpItem == null)
                        {
                            //use the first one if we don't have an item yet...
                            dpItem = dpIndex.Values.FirstOrDefault();
                        }


                        if (parentContentID > 1 && previewVersionID < 1 && previewContentID < 1)
                        {
                            //unless we have a parent id to follow...

                            foreach (DynamicPageFormulaItem item in dpIndex.Values)
                            {
                                object testParentContentIDObj = item.GetContentItemValue(page.DynamicPageParentFieldName);
                                if (testParentContentIDObj != null)
                                {
                                    int    testParentContentID    = -1;
                                    string testParentContentIDStr = string.Format("{0}", testParentContentIDObj);

                                    if (int.TryParse(testParentContentIDStr, out testParentContentID))
                                    {
                                        //if the value is an int, test for equality...
                                        if (parentContentID == testParentContentID)
                                        {
                                            dpItem = item;
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        //value is NOT an int, test for "in" '[id],' or ',[id],' or ',[id]'
                                        if (testParentContentIDStr.StartsWith(string.Format("{0},", parentContentID)) ||
                                            testParentContentIDStr.EndsWith(string.Format(",{0}", parentContentID)) ||
                                            testParentContentIDStr.Contains(string.Format(",{0},", parentContentID)))
                                        {
                                            dpItem = item;
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                        if (dpItem == null)
                        {
                            return;
                        }


                        urlPaths.Add(dpItem.Name.TrimStart("/".ToCharArray()));
                        dpItemParent  = dpItem;
                        parentContent = content;
                    }

                    staticRoute = testStaticRoute;
                    parentPage  = page;
                }
                else
                {
                    //if we can't find a static route, kick out.
                    return;
                }
            }

            if (urlPaths.Count > 0)
            {
                StringBuilder sbUrl = new StringBuilder("~/");
                sbUrl.Append(string.Join("/", urlPaths.ToArray()));

                if (AgilityContext.HttpContext.Request.Path.Value.EndsWith(".aspx", StringComparison.CurrentCultureIgnoreCase))
                {
                    sbUrl.Append(".aspx");
                }
                if (!string.IsNullOrEmpty(AgilityContext.HttpContext.Request.QueryString.Value))
                {
                    sbUrl.Append(AgilityContext.HttpContext.Request.QueryString.Value);
                }

                string redirectUrl = sbUrl.ToString();

                //strip off the querystrings that we don't want...
                redirectUrl = Agility.Web.Util.Url.RemoveQueryString(redirectUrl, "ContentID&VersionID&previewContentID&previewVersionID");


                Agility.Web.HttpModules.AgilityHttpModule.RedirectResponse(redirectUrl, 301);

                AgilityContext.IsResponseEnded = true;
            }
        }
        private static ResolvedPage ResolvePage(
            ref Dictionary <string, AgilityRouteCacheItem> routes,
            AgilityRouteCacheItem routeItem,
            string dynamicRoute,
            string languageCode,
            string websiteName,
            ref List <ResolvedPage> resolvedPages,
            string url)
        {
            AgilityPage page = BaseCache.GetPageFromID(routeItem.PageID, languageCode, websiteName, url);



            if (string.IsNullOrEmpty(dynamicRoute))
            {
                //make sure we have the page, if not, then kick out
                if (page == null)
                {
                    return(null);
                }

                if (!string.IsNullOrEmpty(page.DynamicPageContentViewReferenceName) ||
                    !string.IsNullOrEmpty(page.DynamicPageParentFieldName))
                {
                    //we have NO dynamic route, but the page is dynamic, kick out
                    return(null);
                }

                //not a dynamic page (a static page nested under a dynamic one...)
                return(new ResolvedPage(page, null));
            }
            else
            {
                //resolve the Dynamic Route

                if (string.IsNullOrEmpty(routeItem.ChildDynamicPagePath))
                {
                    //no dynamic page attached to this static page.. kick out
                    return(null);
                }

                //get the route item for the child dynamic page
                if (!routes.TryGetValue(routeItem.ChildDynamicPagePath, out routeItem))
                {
                    return(null);
                }



                //get the dynamic page
                page = BaseCache.GetPageFromID(routeItem.PageID, languageCode, websiteName, url);

                if (page == null)
                {
                    Agility.Web.Tracing.WebTrace.WriteWarningLine(string.Format("Routing: could not load page with id: {0} in language {1} websitename {2} url {3}", routeItem.PageID, languageCode, websiteName, url));
                    return(null);
                }


                if (string.IsNullOrEmpty(page.DynamicPageContentViewReferenceName) &&
                    string.IsNullOrEmpty(page.DynamicPageParentFieldName))
                {
                    //we have a dynamic route, but the page is not dynamic, kick out
                    return(null);
                }

                string contentReferenceName = page.DynamicPageContentViewReferenceName;
                int    parentContentID      = -1;
                if (string.IsNullOrEmpty(contentReferenceName))
                {
                    if (!string.IsNullOrEmpty(page.DynamicPageParentFieldName))
                    {
                        for (int i = resolvedPages.Count - 1; i >= 0; i--)
                        {
                            DynamicPageFormulaItem dpParent = resolvedPages[i].DynamicPageItem;
                            if (dpParent == null)
                            {
                                continue;
                            }

                            //get the content reference name from the parent page...
                            object fieldValueObj = dpParent.GetContentItemValue(page.DynamicPageParentFieldName);
                            if (fieldValueObj != null)
                            {
                                contentReferenceName = fieldValueObj as string;
                                break;
                            }
                        }
                    }
                }
                else if (!string.IsNullOrEmpty(page.DynamicPageParentFieldName))
                {
                    //filter the dynamic page list by the parent field...
                    for (int i = resolvedPages.Count - 1; i >= 0; i--)
                    {
                        DynamicPageFormulaItem dpParent = resolvedPages[i].DynamicPageItem;
                        if (dpParent == null)
                        {
                            continue;
                        }
                        if (dpParent != null)
                        {
                            parentContentID = dpParent.ContentID;
                            break;
                        }
                    }
                    if (parentContentID < 1)
                    {
                        return(null);
                    }
                }

                //if we didn't resolve a content view, kick out...
                if (string.IsNullOrEmpty(contentReferenceName))
                {
                    return(null);
                }

                //create/update the dynamic page index with this page id and dynamic page list reference name
                BaseCache.UpdateDynamicPageIndex(page.ID, contentReferenceName);

                //get the content first if we are in development or staging mode...
                if (AgilityContext.CurrentMode == Enum.Mode.Staging || Agility.Web.Configuration.Current.Settings.DevelopmentMode)
                {
                    AgilityContentServer.AgilityContent content = BaseCache.GetContent(contentReferenceName, page.LanguageCode, AgilityContext.WebsiteName);
                }

                //get the dynamic page list dictionary for this page (this method also updates if neccessary)...
                DynamicPageFormulaItemIndex dpIndex = BaseCache.GetDynamicPageFormulaIndex(page.ID, contentReferenceName, page.LanguageCode, page, true);

                DynamicPageFormulaItem dpItem = null;
                if (dpIndex == null || !dpIndex.TryGetValue(dynamicRoute, out dpItem))
                {
                    //check if friendly-making the route would result in a match
                    string friendly = DynamicPageFormulaItem.MakePathFriendly(dynamicRoute);
                    if (friendly == dynamicRoute || !dpIndex.TryGetValue(friendly, out dpItem))
                    {
                        //we didn't find the item, and making the given path friendly didn't work either. Kick out.
                        return(null);
                    }

                    //there's an item, but only after fixing the path. redirect.
                    string baseUrl     = Data.GetSiteMapNode(page.ID).PagePath;
                    string redirectUrl = baseUrl.LastIndexOf('/') > 0
                                                                                   ? baseUrl.Substring(0, baseUrl.LastIndexOf('/')) + friendly
                                                                                   : friendly;
                    if (url.ToLower().EndsWith(".aspx"))
                    {
                        redirectUrl += ".aspx";
                    }

                    //add the current query string..
                    string query = AgilityContext.HttpContext.Request.QueryString.Value;
                    if (!string.IsNullOrEmpty(query))
                    {
                        redirectUrl += query;
                    }

                    //set the url to get this page, and the ActionResult or HttpModule will 301 redirect to it.
                    ResolvedPage resolvedPage = new ResolvedPage(page, dpItem);
                    resolvedPage.RedirectURL = redirectUrl;
                    return(resolvedPage);
                }

                //check parent content if neccessary
                if (parentContentID > 0 &&
                    !string.IsNullOrEmpty(page.DynamicPageParentFieldName))
                {
                    object testParentContentIDObj = dpItem.GetContentItemValue(page.DynamicPageParentFieldName);

                    if (testParentContentIDObj != null)
                    {
                        int    testParentContentID    = -1;
                        string testParentContentIDStr = string.Format("{0}", testParentContentIDObj);

                        if (int.TryParse(testParentContentIDStr, out testParentContentID))
                        {
                            //if the value is an int, test for equality...
                            if (parentContentID != testParentContentID)
                            {
                                return(null);
                            }
                        }
                        else
                        {
                            //value is NOT an int, test for "in" '[id],' or ',[id],' or ',[id]'
                            if (!testParentContentIDStr.StartsWith(string.Format("{0},", parentContentID)) &&
                                !testParentContentIDStr.EndsWith(string.Format(",{0}", parentContentID)) &&
                                !testParentContentIDStr.Contains(string.Format(",{0},", parentContentID)))
                            {
                                return(null);
                            }
                        }
                    }
                }

                return(new ResolvedPage(page, dpItem));
            }
        }
Ejemplo n.º 6
0
        private static string AgilityFile(FileType FileType, params string[] referenceNames)
        {
            string contentReferenceName = null;
            string ext    = null;
            string prefix = null;

            switch (FileType)
            {
            case Web.FileType.CSS:
                contentReferenceName = AgilityDynamicCodeFile.REFNAME_AgilityCSSFiles;
                ext    = ".css";
                prefix = "Content/css/";
                break;

            case Web.FileType.Javascript:
                contentReferenceName = AgilityDynamicCodeFile.REFNAME_AgilityJavascriptFiles;
                ext    = ".js";
                prefix = "scripts/";
                break;
            }

            if (referenceNames == null || referenceNames.Length == 0)
            {
                return(string.Empty);
            }
            if (string.IsNullOrEmpty(contentReferenceName))
            {
                return(string.Empty);
            }

            Agility.Web.AgilityContentServer.AgilityContent content = BaseCache.GetContent(contentReferenceName, AgilityDynamicCodeFile.LANGUAGECODE_CODE, AgilityContext.WebsiteName);
            if (content == null)
            {
                return(string.Empty);
            }

            DataTable dt = content.DataSet.Tables["ContentItems"];

            if (dt == null)
            {
                return(string.Empty);
            }

            bool          minify     = true;
            List <string> versionIDs = new List <string>();

            foreach (string refName in referenceNames)
            {
                DataRow[] rows = dt.Select(string.Format("ReferenceName = '{0}'", refName.Replace("'", "''")));
                if (rows.Length > 0)
                {
                    if (string.Format("{0}", rows[0]["Minify"]).ToLower() != "true")
                    {
                        minify = false;
                    }
                    string idStr = string.Format("{0}", rows[0]["VersionID"]);
                    if (!string.IsNullOrEmpty(idStr))
                    {
                        versionIDs.Add(idStr);
                    }
                }
            }

            if (versionIDs.Count == 0)
            {
                return(string.Empty);
            }

            var    config     = BaseCache.GetDomainConfiguration(AgilityContext.WebsiteName);
            string baseDomain = config.XAgilityCDNBaseUrl;

            if (baseDomain.EndsWith("/"))
            {
                baseDomain = baseDomain.Substring(baseDomain.Length - 1);
            }

            //handle ssl...
            if (AgilityContext.HttpContext.Request.IsHttps)
            {
                //replace cdn.agiltiycms.com...
                baseDomain = baseDomain.Replace("http://cdn.agilitycms.com", "https://az184419.vo.msecnd.net");
                baseDomain = baseDomain.Replace("http://cdndev.agilitycms.com", "https://az99666.vo.msecnd.net");
            }

            string websiteNameStripped = baseDomain.Substring(baseDomain.LastIndexOf("/") + 1);

            baseDomain = baseDomain.Substring(0, baseDomain.LastIndexOf("/"));

            string url = string.Format("{0}/code/{1}/{2}/{3}{4}{5}",
                                       baseDomain,
                                       websiteNameStripped,
                                       contentReferenceName.ToLowerInvariant(),
                                       string.Join("-", versionIDs.ToArray()),
                                       minify ? ".min" : string.Empty,
                                       ext);

            return(url);
        }
Ejemplo n.º 7
0
        private List <AgilitySiteMapNode> GetDynamicChildNodes(AgilitySiteMapNode anode, AgilitySiteMapNode parentNode, List <AgilitySiteMapNode> collection)
        {
            string dynamicPageContentReferenceName = anode.DynamicPageContentReferenceName;
            string dynamicPageParentFieldName      = anode.DynamicPageParentFieldName;

            if (string.IsNullOrEmpty(dynamicPageContentReferenceName) && string.IsNullOrEmpty(dynamicPageParentFieldName))
            {
                return(collection);
            }


            //the child pages are dynamic pages...
            AgilityPage page            = anode.AgilityPage;
            int         parentContentID = 0;

            if (page != null)
            {
                string contentReferenceName = dynamicPageContentReferenceName;

                if (string.IsNullOrEmpty(contentReferenceName))
                {
                    AgilityDynamicSiteMapNode dpNode = anode.ParentNode as AgilityDynamicSiteMapNode;

                    if (dpNode == null)
                    {
                        AgilitySiteMapNode pnode = parentNode;

                        while (pnode != null)
                        {
                            dpNode = pnode.ParentNode as AgilityDynamicSiteMapNode;
                            if (dpNode != null)
                            {
                                break;
                            }
                            pnode = pnode.ParentNode;
                        }
                    }

                    if (!string.IsNullOrEmpty(dynamicPageParentFieldName) && dpNode != null && !string.IsNullOrEmpty(dpNode.ReferenceName))
                    {
                        //get the content reference name from the parent page...
                        AgilityContent parentContent = BaseCache.GetContent(dpNode.ReferenceName, AgilityContext.LanguageCode, AgilityContext.WebsiteName);
                        if (parentContent != null &&
                            parentContent.DataSet != null &&
                            parentContent.DataSet.Tables["ContentItems"] != null &&
                            parentContent.DataSet.Tables["ContentItems"].Columns.Contains(dynamicPageParentFieldName))
                        {
                            DataRow row = parentContent.GetItemByContentID(dpNode.ContentID);

                            if (row != null)
                            {
                                //the contentReferenceName is stored in the field value...
                                contentReferenceName = row[dynamicPageParentFieldName] as string;
                            }
                        }
                    }
                }
                else if (!string.IsNullOrEmpty(dynamicPageParentFieldName))
                {
                    //filter the dynamic page list by the parent field...
                    AgilityDynamicSiteMapNode dpNode = anode.ParentNode as AgilityDynamicSiteMapNode;

                    if (dpNode == null)
                    {
                        AgilitySiteMapNode pnode = parentNode;

                        while (pnode != null)
                        {
                            dpNode = pnode.ParentNode as AgilityDynamicSiteMapNode;
                            if (dpNode != null)
                            {
                                break;
                            }
                            pnode = pnode.ParentNode;
                        }
                    }

                    parentContentID = -1;
                    if (!string.IsNullOrEmpty(dynamicPageParentFieldName) && dpNode != null && !string.IsNullOrEmpty(dpNode.ReferenceName))
                    {
                        parentContentID = dpNode.ContentID;
                    }
                }


                if (!string.IsNullOrEmpty(contentReferenceName))
                {
                    //add this page and reference name to the page/dynamic content index
                    BaseCache.UpdateDynamicPageIndex(page.ID, contentReferenceName);

                    //get the content first
                    DataView dv = Data.GetContentView(contentReferenceName);

                    //get the dynamic page formula index
                    Dictionary <string, DynamicPageFormulaItem> dpIndex = BaseCache.GetDynamicPageFormulaIndex(page.ID, contentReferenceName, AgilityContext.LanguageCode, page.ServerPage, true);

                    if (dpIndex != null && dv != null)
                    {
                        //make an ID based index
                        Dictionary <int, DynamicPageFormulaItem> idIndex = new Dictionary <int, DynamicPageFormulaItem>();


                        foreach (var item in dpIndex.Values)
                        {
                            idIndex[item.ContentID] = item;
                        }


                        //loop all of the dynamic pages....
                        foreach (DataRowView dvr in dv)
                        {
                            DynamicPageFormulaItem item = null;

                            int contentID = -1;
                            if (!int.TryParse($"{dvr["ContentID"]}", out contentID))
                            {
                                contentID = -1;
                            }

                            if (!idIndex.TryGetValue(contentID, out item))
                            {
                                continue;
                            }

                            if (parentContentID != 0)
                            {
                                //do a lookup to ensure the parent id condition is met if necessary

                                object testParentContentIDObj = item.GetContentItemValue(dynamicPageParentFieldName);
                                if (testParentContentIDObj != null)
                                {
                                    int    testParentContentID    = -1;
                                    string testParentContentIDStr = string.Format("{0}", testParentContentIDObj);

                                    if (int.TryParse(testParentContentIDStr, out testParentContentID))
                                    {
                                        //if the value is an int, test for equality...
                                        if (parentContentID != testParentContentID)
                                        {
                                            continue;
                                        }
                                    }
                                    else
                                    {
                                        //value is NOT an int, test for "in" '[id],' or ',[id],' or ',[id]'
                                        if (!testParentContentIDStr.StartsWith(string.Format("{0},", parentContentID)) &&
                                            !testParentContentIDStr.EndsWith(string.Format(",{0}", parentContentID)) &&
                                            !testParentContentIDStr.Contains(string.Format(",{0},", parentContentID)))
                                        {
                                            continue;
                                        }
                                    }
                                }
                                else
                                {
                                    continue;
                                }
                            }

                            AgilityDynamicSiteMapNode thisDNode = AgilityDynamicSiteMapNode.GetDynamicNode(anode, item, page);

                            collection.Add(thisDNode);
                        }
                    }
                }
            }

            return(collection);
        }
        public static Task <IHtmlContent> RenderContentZone(this IViewComponentHelper component, AgilityPage page, string zoneName)
        {
            try
            {
                HttpContext currentContext = AgilityContext.HttpContext;

                String websiteName = AgilityContext.WebsiteName;
                if (page == null)
                {
                    if (AgilityContext.IsTemplatePreview)
                    {
                        //TODO render the template preview


                        //var templates = from cs in AgilityContext.CurrentPageTemplateInPreview.ContentSections
                        //				where string.Equals(cs.Name, zoneName, StringComparison.CurrentCultureIgnoreCase)
                        //				orderby cs.XModuleOrder
                        //				select cs;
                        //TextWriter tw = helper.ViewContext.Writer;

                        //foreach (var cs in templates)
                        //{
                        //	tw.Write(string.Format("<div class=\"AgilityContentSectionDefinition\"><div class=\"ContentSectionTitle\">{0}</div></div>", cs.Name));
                        //}
                    }

                    return(Task.Run <IHtmlContent>(() => { return new HtmlString("TODO: implement template preview"); }));
                }



                //regular page rendering
                var sections = from cs in page.ContentSections
                               where string.Equals(cs.Name, zoneName, StringComparison.CurrentCultureIgnoreCase)
                               orderby cs.ModuleOrder
                               select cs;

                List <Task <string> > sectionTasks = new List <Task <string> >();
                DateTime dtStart = DateTime.Now;

                foreach (var cs in sections)
                {
                    //only continue if we have a content ref name...
                    if (string.IsNullOrEmpty(cs.ContentReferenceName))
                    {
                        continue;
                    }

                    //keep track of the various way this module can be rendered
                    List <ModuleRender> renders = new List <ModuleRender>()
                    {
                        new ModuleRender()
                        {
                            ContentReferenceName = cs.ContentReferenceName
                        }
                    };

                    //if this content zone is part of a Module AB test Experiment
                    if (cs.ExperimentID > 0)
                    {
                        var lst = BaseCache.GetExperiments(AgilityContext.WebsiteName);
                        AgilityContentServer.AgilityExperiment experiment = lst.GetExperiment(cs.ExperimentID);

                        if (experiment != null)
                        {
                            foreach (var variant in experiment.Variants.Where(v => !string.IsNullOrWhiteSpace(v.ContentReferenceName)))
                            {
                                renders.Add(new ModuleRender()
                                {
                                    ContentReferenceName = variant.ContentReferenceName,
                                    Variant = variant
                                });
                            }
                        }
                    }

                    foreach (ModuleRender moduleRender in renders)
                    {
                        try
                        {
                            string contentReferenceName = moduleRender.ContentReferenceName;

                            Agility.Web.AgilityContentServer.AgilityContent moduleContent = BaseCache.GetContent(contentReferenceName, AgilityContext.LanguageCode, websiteName);
                            if (moduleContent == null ||
                                moduleContent.DataSet == null ||
                                moduleContent.DataSet.Tables["ContentItems"] == null ||
                                moduleContent.DataSet.Tables["ContentItems"].Rows.Count == 0)
                            {
                                continue;
                            }


                            DataRowView drv = moduleContent.DataSet.Tables["ContentItems"].DefaultView[0];

                            int moduleContentID = -1;
                            int moduleVersionID = -1;

                            if (!int.TryParse($"{drv["ContentID"]}", out moduleContentID))
                            {
                                moduleContentID = -1;
                            }
                            if (!int.TryParse($"{drv["VersionID"]}", out moduleVersionID))
                            {
                                moduleVersionID = -1;
                            }


                            Agility.Web.AgilityContentServer.AgilityModule module = BaseCache.GetModule(cs.ModuleID, websiteName);
                            if (module == null)
                            {
                                continue;
                            }


                            object model = new AgilityModuleModel()
                            {
                                ModuleContentName = contentReferenceName,
                                ModuleProperties  = drv,
                                LanguageCode      = AgilityContext.LanguageCode
                            };

                            string viewComponentName  = null;
                            string agilityCodeRefName = null;

                            using (StringReader sr = new StringReader(module.XmlSchema))
                            {
                                DataSet ds = new DataSet();
                                ds.ReadXmlSchema(sr);

                                viewComponentName  = ds.ExtendedProperties["ViewComponent"] as string;
                                agilityCodeRefName = ds.ExtendedProperties["AgilityCodeRefName"] as string;
                            }

                            if (!string.IsNullOrEmpty(viewComponentName))
                            {
                                #region *** VIEW COMPONENTS **
                                var viewComponentFactory = HtmlHelperViewExtensions.GetServiceOrFail <IViewComponentSelector>(AgilityContext.HttpContext);
                                var componentDesc        = viewComponentFactory.SelectComponent(viewComponentName);

                                if (componentDesc == null)
                                {
                                    throw new ApplicationException(string.Format("The view component {0} was not found.", viewComponentName));
                                }

                                MethodInfo method = componentDesc.MethodInfo;


                                if (method == null)
                                {
                                    throw new ApplicationException(string.Format("The component invoke method was not found in the component {0}", viewComponentName));
                                }

                                ParameterInfo[] paramAry = method.GetParameters();
                                if (paramAry.Length > 0)
                                {
                                    ParameterInfo paramInfo = paramAry[0];
                                    Type          paramType = paramInfo.ParameterType;
                                    if (paramType.IsSubclassOf(typeof(AgilityContentItem)) || paramType == typeof(AgilityContentItem))
                                    {
                                        ConstructorInfo ci = paramType.GetConstructor(System.Type.EmptyTypes);

                                        if (ci == null)
                                        {
                                            throw new ApplicationException(string.Format("No default constructor found for type {0}", paramType.Name));
                                        }

                                        AgilityContentItem moduleItem = ci.Invoke(new object[0]) as AgilityContentItem;
                                        moduleItem.DataRow       = drv.Row;
                                        moduleItem.LanguageCode  = AgilityContext.LanguageCode;
                                        moduleItem.ReferenceName = contentReferenceName;
                                        moduleItem.ContentID     = moduleContentID;
                                        moduleItem.VersionID     = moduleVersionID;


                                        try
                                        {
                                            Task <IHtmlContent> task = component.InvokeAsync(viewComponentName, moduleItem);

                                            moduleRender.RenderTask = task;
                                            moduleRender.ContentID  = moduleContentID;
                                        }
                                        catch (Exception ex)
                                        {
                                            moduleRender.PreRenderedContent = new HtmlString($"<p>Error rendering Component {viewComponentName}</p><pre>{ex}</pre>");
                                            moduleRender.ContentID          = moduleContentID;
                                        }
                                    }
                                    else
                                    {
                                        throw new ApplicationException(string.Format("The component invoke method parameter was not of type AgilityContent in the component {0}", viewComponentName));
                                    }
                                    #endregion
                                }
                            }
                            else if (!string.IsNullOrEmpty(agilityCodeRefName))
                            {
                                #region *** Agility Inline Code ***
                                DataView dv = Data.GetContentView(AgilityDynamicCodeFile.REFNAME_AgilityModuleCodeTemplates, AgilityDynamicCodeFile.LANGUAGECODE_CODE);

                                string    filter = string.Format("ReferenceName = '{0}' AND Visible = true", agilityCodeRefName);
                                DataRow[] rows   = dv.Table.Select(filter);
                                if (rows.Length > 0)
                                {
                                    string modulePath =
                                        $"~/Views/{rows[0]["VersionID"]}/DynamicAgilityCode/{AgilityDynamicCodeFile.REFNAME_AgilityModuleCodeTemplates}/{agilityCodeRefName}.cshtml";

                                    AgilityContentItem moduleItem = new AgilityContentItem();
                                    moduleItem.DataRow       = drv.Row;
                                    moduleItem.LanguageCode  = AgilityContext.LanguageCode;
                                    moduleItem.ReferenceName = contentReferenceName;
                                    moduleItem.ContentID     = moduleContentID;
                                    moduleItem.VersionID     = moduleVersionID;
                                    //moduleItem.InlineCodePath = modulePath;

                                    try
                                    {
                                        Task <IHtmlContent> task = component.InvokeAsync("AgilityInlineCode", new { inlineCodePath = modulePath, module = moduleItem });

                                        moduleRender.RenderTask = task;
                                        moduleRender.ContentID  = moduleContentID;
                                    }
                                    catch (Exception ex)
                                    {
                                        moduleRender.PreRenderedContent = new HtmlString($"<p>Error rendering Inline Code</p><pre>{ex}</pre>");
                                        moduleRender.ContentID          = moduleContentID;
                                    }
                                }
                                else
                                {
                                    moduleRender.PreRenderedContent = new HtmlString($"<p>Error rendering Inline Code</p>");
                                    moduleRender.ContentID          = moduleContentID;
                                }
                                #endregion
                            }
                            else if (!string.IsNullOrEmpty(module.ControlPath))
                            {
                                #region *** Control Path - Partial View ***
                                string className = GetClassName(module.ReferenceName ?? module.Name);
                                string typeName  = string.Format("Module_{0}", className);

                                Type paramType = Agility.Web.Utils.FileUtils.GetTypeFromReflection(null, typeName);
                                if (paramType.IsSubclassOf(typeof(AgilityContentItem)) || paramType == typeof(AgilityContentItem))
                                {
                                    ConstructorInfo ci = paramType.GetConstructor(System.Type.EmptyTypes);

                                    if (ci == null)
                                    {
                                        throw new ApplicationException(string.Format("No default constructor found for type {0}", paramType.Name));
                                    }

                                    AgilityContentItem moduleItem = ci.Invoke(new object[0]) as AgilityContentItem;
                                    moduleItem.DataRow       = drv.Row;
                                    moduleItem.LanguageCode  = AgilityContext.LanguageCode;
                                    moduleItem.ReferenceName = contentReferenceName;
                                    moduleItem.ContentID     = moduleContentID;
                                    moduleItem.VersionID     = moduleVersionID;


                                    try
                                    {
                                        Task <IHtmlContent> task = component.InvokeAsync("AgilityPartialView", new { partialViewPath = module.ControlPath, module = moduleItem });

                                        moduleRender.RenderTask = task;
                                        moduleRender.ContentID  = moduleContentID;
                                    }
                                    catch (Exception ex)
                                    {
                                        moduleRender.PreRenderedContent = new HtmlString($"<p>Error rendering Partial View at {module.ControlPath}</p><pre>{ex}</pre>");
                                        moduleRender.ContentID          = moduleContentID;
                                    }
                                }
                                else
                                {
                                    throw new ApplicationException(string.Format("The component invoke method parameter was not of type AgilityContent in the component {0}", viewComponentName));
                                }
                                #endregion
                            }
                            else if (!string.IsNullOrEmpty(module.Markup))
                            {
                                if (module.Markup.StartsWith("@"))
                                {
                                    #region *** Inline Razor Markup ***
                                    AgilityContentItem item = new AgilityContentItem();
                                    item.DataRow       = drv.Row;
                                    item.LanguageCode  = AgilityContext.LanguageCode;
                                    item.ReferenceName = contentReferenceName;
                                    item.ContentID     = moduleContentID;
                                    item.VersionID     = moduleVersionID;
                                    model = item;

                                    string viewPath = string.Format("~/Views/DynamicAgilityModule/MVC/{0}/{1}.cshtml", AgilityContext.CurrentMode, module.ID);

                                    try
                                    {
                                        Task <IHtmlContent> task = component.InvokeAsync("AgilityInlineCode", new { inlineCodePath = viewPath, module = item });

                                        moduleRender.RenderTask = task;
                                        moduleRender.ContentID  = moduleContentID;
                                    }
                                    catch (Exception ex)
                                    {
                                        moduleRender.PreRenderedContent = new HtmlString($"<p>Error rendering Dynamic Agility Module</p><pre>{ex}</pre>");
                                        moduleRender.ContentID          = moduleContentID;
                                    }
                                    #endregion
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            if (Current.Settings.DevelopmentMode)
                            {
                                moduleRender.PreRenderedContent = new HtmlString($"<div>Could not output zone {cs.Name}</div><div>{ex.ToString().Replace("\n", "<br/>")}</div>");
                            }
                            else
                            {
                                moduleRender.PreRenderedContent = new HtmlString($"<!-- Could not output zone {cs.Name} - See web log -->");
                                Agility.Web.Tracing.WebTrace.WriteException(ex);
                            }
                        }
                    }

                    Task <string> sectionTask = Task <string> .Run(() =>
                    {
                        AgilityContext.HttpContext = currentContext;
                        var rendersToOutput        = renders.Where(r => r.RenderTask != null || r.PreRenderedContent != null).ToList();
                        return(AgilityHelpers.RenderModuleHtml(rendersToOutput, cs));
                    });

                    sectionTasks.Add(sectionTask);
                }


                Task <IHtmlContent> retTask = Task.Run <IHtmlContent>(() =>
                {
                    AgilityContext.HttpContext = currentContext;

                    try
                    {
                        Task.WaitAll(sectionTasks.ToArray());
                    } catch { }

                    using (StringWriter htmlStringWriter = new StringWriter())
                    {
                        foreach (var t in sectionTasks)
                        {
                            if (t.IsFaulted)
                            {
                                Agility.Web.Tracing.WebTrace.WriteException(t.Exception, $"Error rendering module in zone {zoneName} - {t.AsyncState}");
                            }
                            else
                            {
                                htmlStringWriter.Write(t.Result);
                            }
                        }

                        TimeSpan ts = DateTime.Now - dtStart;
                        if (ts.TotalSeconds > 1)
                        {
                            string renderTimeMessage = string.Format("Content Zone: {0} - Render Time: {1:F2} seconds.", zoneName, ts.TotalMilliseconds / 1000);
                            Agility.Web.Tracing.WebTrace.WriteVerboseLine(renderTimeMessage);
                            htmlStringWriter.Write(string.Format("<!-- {0} -->", renderTimeMessage));
                        }

                        return(new HtmlString(htmlStringWriter.ToString()));
                    }
                });


                return(retTask);
            }
            catch (Exception ex)
            {
                string errHtml = null;
                string msg     = string.Format("Could not output content zone {0}.", zoneName);
                if (ex is InvalidOperationException && ex.Message.Contains("No route"))
                {
                    msg +=
                        @" This error is usually caused by a missing route in your Global.asax.cs. Ensure the following route is defined after the normal Agility route.\n
routes.MapRoute(""Default"", ""{controller}/{action}/{id}"",\n
    new { controller = """", action = """", id = """" }\n
);";
                }

                if (Current.Settings.DevelopmentMode)
                {
                    errHtml = ex.ToString().Replace("\n", "<br/>");
                }
                else
                {
                    errHtml = msg;
                }

                Agility.Web.Tracing.WebTrace.WriteException(ex, msg);

                return(Task.Run <IHtmlContent>(() => { return new HtmlString(errHtml); }));
            }
        }