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));
            }
        }