public ActionResult FeaturedBlogPost(AgilityContentItem module)
        {
            #region --- Get Blog Config and Repos ---
            var blogConfigRef             = module["BlogConfiguration"] as string;
            AgilityContentItem blogConfig = null;
            IAgilityContentRepository <AgilityContentItem> blogPosts      = null;
            IAgilityContentRepository <AgilityContentItem> blogCategories = null;
            IAgilityContentRepository <AgilityContentItem> blogTags       = null;
            IAgilityContentRepository <AgilityContentItem> blogAuthors    = null;
            BlogUtils.GetBlogConfig(blogConfigRef, out blogConfig, out blogPosts, out blogCategories, out blogTags, out blogAuthors);
            #endregion

            string postIDs = module["PostIDs"] as string;
            var    post    = BlogUtils.GetItemsByIDs(blogPosts.ContentReferenceName, postIDs).FirstOrDefault();

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

            var model = new PostViewModel();
            model.Configuration = blogConfig;
            model.Post          = post;

            return(PartialView(AgilityComponents.TemplatePath("Blog-FeaturedPostModule"), model));
        }
        public static string BlogDynamicUrl(this AgilityContentItem item, AgilityContentItem blogConfig, AgilityContentItem currentBlogCategory = null)
        {
            string url = "";
            string nestedDynamicPageUrl = "";

            if (item.IsBlogPost())
            {
                /*
                 * Determine if we have a current blog category (i.e. from category landing pages), use that to route the post
                 * If no current blog category set, use canonical category as main url
                 * If post has no category associated at all, use default post details route (without category)
                 */

                AgilityContentItem category = null;
                if (currentBlogCategory == null)
                {
                    //use the canonical category (first category = canonical category)
                    category = BlogUtils.GetItemsByIDs(item["Categories"], item["CategoriesIDs"]).FirstOrDefault();
                }
                else
                {
                    category = currentBlogCategory;
                }

                //no category set - use default route
                if (category == null)
                {
                    url = BlogContext.GetDynamicDefaultBlogPostPath(blogConfig);
                }
                else
                {
                    url = BlogContext.GetDynamicCategoryBlogPostPath(blogConfig, category);
                    nestedDynamicPageUrl = BlogContext.GetDynamicCategoryBlogPostPath(blogConfig, category, true);
                }
            }

            if (item.IsBlogAuthor())
            {
                url = BlogContext.GetDynamicBlogAuthorPath(blogConfig);
            }

            if (item.IsBlogCategory())
            {
                url = BlogContext.GetDynamicBlogCategoryPath(blogConfig);
            }

            if (item.IsBlogTag())
            {
                url = BlogContext.GetDynamicBlogTagPath(blogConfig);
            }

            if (string.IsNullOrEmpty(url))
            {
                return("");
            }

            DynamicPageItem d = Data.GetDynamicPageItem(url, item.ReferenceName, item.Row); //must get dynamic page using static paths (no nested dynamic names that have been already formulated)

            if (!string.IsNullOrEmpty(nestedDynamicPageUrl))
            {
                url = nestedDynamicPageUrl; // do the string replacement using the dynamic formulized route
            }

            url = string.Format("{0}/{1}", url.Substring(0, url.LastIndexOf('/')), d.Name).ToLowerInvariant();

            return(url);
        }
        public ActionResult BlogDetails(AgilityContentItem module)
        {
            #region --- Get Blog Config and Repos ---
            var blogConfigRef             = module["BlogConfiguration"] as string;
            AgilityContentItem blogConfig = null;
            IAgilityContentRepository <AgilityContentItem> blogPosts      = null;
            IAgilityContentRepository <AgilityContentItem> blogCategories = null;
            IAgilityContentRepository <AgilityContentItem> blogTags       = null;
            IAgilityContentRepository <AgilityContentItem> blogAuthors    = null;
            BlogUtils.GetBlogConfig(blogConfigRef, out blogConfig, out blogPosts, out blogCategories, out blogTags, out blogAuthors);
            #endregion

            #region --- Resolve Dynamic Post and Category (if any) ---

            var post = ResolveBlogPostDetails();

            if (post == null || !post.IsBlogPost())
            {
                Agility.Web.Tracing.WebTrace.WriteErrorLine("Cannot resolve current dynamic item to a Blog Posts.");
                return(null);
            }

            var currentNode = SiteMap.CurrentNode;
            AgilityContentItem currentCategory = null;
            if (currentNode != null && currentNode.ParentNode != null)
            {
                currentCategory = AgilityContext.GetDynamicPageItem <AgilityContentItem>(currentNode.ParentNode);
            }

            //only set category if the parent dynamic item is a category
            if (currentCategory != null && !currentCategory.IsBlogCategory())
            {
                currentCategory = null;
            }
            #endregion


            #region --- Get Related Posts ---
            int relatedPostsLimit;
            int.TryParse(string.Format("{0}", module["RelatedPostsLimit"]), out relatedPostsLimit);
            if (relatedPostsLimit < 0)
            {
                relatedPostsLimit = 0;
            }
            var relatedPosts = BlogUtils.GetRelatedPosts(post, blogPosts, true, relatedPostsLimit);
            #endregion

            #region --- Set SEO Properties ---
            string canonicalUrl = post.BlogDynamicUrl(blogConfig, currentCategory);
            AgilityContext.CanonicalLink = BlogUtils.GetAbsoluteUrl(canonicalUrl);

            //Enables image for twitter cards - but twitter cards need to be enabled ...
            //to enable twitter cards include setting in app settings in web.config
            AgilityContext.FeaturedImageUrl = BlogUtils.GetPostImageUrl(blogConfig, post, PostImageType.Details);

            if (string.IsNullOrEmpty(AgilityContext.Page.MetaTags))
            {
                AgilityContext.Page.MetaTags = Server.HtmlEncode(BlogUtils.GetPostDescription(post, "Excerpt", 255, true));
            }

            string websiteName = blogConfig["WebsiteName"] as string;
            if (string.IsNullOrEmpty(websiteName))
            {
                websiteName = AgilityContext.WebsiteName;
            }
            AgilityContext.Page.MetaTagsRaw += string.Format(
                "{6}" +
                "<meta property='og:title' content='{0}' />" +
                "<meta property='og:type' content='{1}' />" +
                "<meta property='og:url' content='{2}' />" +
                "<meta property='og:image' content='{3}' />" +
                "<meta property='og:site_name' content='{4}' />" +
                "<meta property='og:description' content='{5}' />",
                Server.HtmlEncode(AgilityContext.Page.Title),
                "article",
                Request.Url.ToString(),
                BlogUtils.GetPostImageUrl(blogConfig, post, PostImageType.Details),
                websiteName,
                Server.HtmlEncode(AgilityContext.Page.MetaTags),
                Environment.NewLine
                );
            #endregion

            #region --- Set ViewModel ---
            var model = new PostViewModel();
            model.Configuration   = blogConfig;
            model.Post            = post;
            model.RelatedPosts    = relatedPosts;
            model.CurrentCategory = currentCategory;
            model.Module          = module;
            model.Categories      = BlogUtils.GetItemsByIDs(blogCategories.ContentReferenceName, post["CategoriesIDs"]);;
            model.Tags            = BlogUtils.GetItemsByIDs(blogTags.ContentReferenceName, post["BlogTagsIDs"]);;
            #endregion

            return(PartialView(AgilityComponents.TemplatePath("Blog-PostDetailsModule"), model));
        }