Expanding breadcrumb control

Topics: Controls
Jun 18, 2012 at 5:03 PM

Hello,

I'm trying to expand on the breadcrumb control here to work for posts and not just pages.

I've looked for documentation, and through the intellisense, but I'm struggling and could do with a bit of help starting please.

I am using the BlogEngine.Core namespace. In the PostView.ascx file it just uses 

<%=Server.HtmlEncode(Post.Title) %>

and I notice it inherits BlogEngine.Core.Web.Controls.PostViewBase.

I'm sure it's simple, but I need to access the Post Title from within my control. 

Can anyone point me the right direction please?

Thanks

 

Coordinator
Jun 19, 2012 at 5:16 AM

You control doesn't know where you put it, so you can't use core properties like Post.Title. It may be on the page that has nothing to do with Post at all.

What you can do is to look up at control parent (page you drop it on) and get it's title:

var postTitle = this.Parent.Page.Title;

Jun 19, 2012 at 12:08 PM

rtur: That makes sense, thank you.

As my control could be placed anywhere, is there no way I can test to see if the core properties are available please? I would have thought that I should be able to make a control particularly for post pages, or should I be making an extension and not a control?

So far I have managed to get all posts

 

private List<BlogEngine.Core.Post> GetPosts()
    {
        List<BlogEngine.Core.Post> posts = new List<BlogEngine.Core.Post>();

        foreach (BlogEngine.Core.Post post in BlogEngine.Core.Post.Posts)
        {
            if (post.IsPublished)
            {
                posts.Add(post);
            }
        }

        return posts;
    }

Which isn't much help I suppose. I downloaded any extensions/controls I could find that might be able to access info specific to a post or page (such as post wordcount) but it's built in a DLL so I can't use it. The FacebookLike extension has this

    void Post_Serving(object sender, ServingEventArgs e)
    {
        if (e.Location == ServingLocation.Feed) return;

        bool ShowPostList = Convert.ToBoolean(_extensionSettings.GetSingleValue("ShowPostList"));
        if (e.Location == ServingLocation.PostList && !ShowPostList) return;

        Post post = sender as Post;
        ButtonSettings bSettings = new ButtonSettings();
        StringBuilder sBuild = new StringBuilder();
        sBuild.AppendLine("<div class=\"FacebookLike\">");
        string likeScript = string.Format("<iframe src=\"http://www.facebook.com/plugins/like.php?href={0}&amp;layout={1}&amp;show_faces={2}&amp;width={3}&amp;action={4}&amp;font&amp;colorscheme={5}&amp;height=80\" scrolling=\"no\" frameborder=\"0\" style=\"border:none; overflow:hidden; width:450px; height:80px;\" allowTransparency=\"true\"></iframe>",
            post.AbsoluteLink.AbsoluteUri, bSettings.Layout, bSettings.ShowFaces, bSettings.Width, bSettings.Action, bSettings.ColorScheme);
        sBuild.AppendLine(likeScript);
        sBuild.AppendLine("</div>");
        e.Body += sBuild.ToString();
    }

Which uses the sender parameter to get the Post object. This is an extension though and not a control. 

I'll keep trying to find my way to it, but any more advice you have would be greatly appreciated. 

Thank you very much

Russ

Jun 19, 2012 at 12:27 PM
Edited Jun 19, 2012 at 12:47 PM

Ok I have something working, but it's not the way I would like to do it (nor will it be efficient when we have many posts).

    private BlogEngine.Core.Post GetPost()
    {
        BlogEngine.Core.Post thisPost = new BlogEngine.Core.Post();

        foreach (BlogEngine.Core.Post post in BlogEngine.Core.Post.Posts)
        {
            if (HttpContext.Current.Request.Url.AbsoluteUri.ToString().Split('=')[1] == post.Id.ToString())
            {
               return post;
            }
        }

        return null;
    }

So loop through every post, then match on ID, and if it matches then it's our current post.

Can anyone suggest a way to pass in the current Post object, or if there is a more direct way rather than looping through all the posts?

 

Thank you

Jun 19, 2012 at 7:07 PM
Edited Jun 19, 2012 at 7:28 PM

If I'm reading this correctly, then page detection might be an option.

I find that quite useful for a number of things, but also for page and post navigation.

Here's snippets from what I have in my theme master (so you would need to edit to suit, but it's not dissimilar to what's in default.aspx.cs).

 

 
public enum PageType { Author, Cat, Date, Front, Page, PageCSA, Post, Tag, TagPage, Other }

protected PageType currentPageType = GetPageType();

public static PageType GetPageType()
    {
        HttpContext context = HttpContext.Current;
        string path = context.Request.RawUrl.ToLower(), endPath = null;

        // Start with homepage (front page)
        // Homepage url ends in default.aspx or blank, so find last slash and check 
        if (path.LastIndexOf('/') > -1)
        {
            endPath = path.Substring(path.LastIndexOf('/') + 1);
            if (endPath.StartsWith("default.aspx") || endPath.StartsWith("blog.aspx") || endPath == "")
            {
                // Browse by date ends in default.aspx, it's the front only if year is not present in the querystring parameter
                if (context.Request["year"] != null)
                {
                    return PageType.Date;
                }
                // If we were using the calendar widget, we would have to check for calendar in the URL, set pageType and add any required logic
                else
                {
                    return PageType.Front;
                }
            }
            // Check for other named pages while we are here
            if (endPath.StartsWith("contact.aspx") || endPath.StartsWith("search.aspx") || endPath.StartsWith("archivepoll.aspx"))
            {
                return PageType.PageCSA; 
            }
            if (endPath.StartsWith("alltags.aspx"))
            {
                return PageType.TagPage;
            }
        }
        if (!String.IsNullOrEmpty(context.Request.QueryString["tag"]))
        {
            return PageType.Tag;
        }
        if (path.Contains("/category/") || path.Contains("/archive.aspx"))
        {
            return PageType.Cat;
        }
        if (path.Contains("/page/"))
        {
            return PageType.Page;
        }
        if (path.Contains("/post/"))
        {
            return PageType.Post;
        }
        if (path.Contains("/author/"))
        {
            return PageType.Author;
        }

        return PageType.Other;
    }

 

Then you can check where your'e at and call whatever routine you need, for example:

 

if (this.currentPageType == PageType.Post)
        {
            //retrieve the post from the qs Id (depending on how you implement you may need the current context)
		Post currentPost = Post.GetPost(new Guid(Request.QueryString["id"]));
		//do stuff
            return;
        }

and so forth

 

 

if (this.currentPageType == PageType.Cat)
        {
            if (Request.QueryString["id"] != null)
            {
                Category cat = Category.GetCategory(new Guid(Request.QueryString["id"]));
                HtmlGenericControl hdr1 = new HtmlGenericControl("h1")
                {
                    InnerText = this.Page.Title
                };
                hdr1.Attributes.Add("id", "hdr1");
                cphHdr.Controls.Add(hdr1);

                HtmlGenericControl postListMast = new HtmlGenericControl("div")
                {
                    InnerHtml = GetCatCrumb(cat)
                };
                postListMast.Attributes.Add("id", "postListMast");
                cphHdr.Controls.Add(postListMast);
            }
            SetPostNav();
            return;
        }
private string GetCatCrumb(Category cat)
    {
        List<string> links = new List<string>();

        links.Add(cat.Title);
        var parentId = cat.Parent;
        while (parentId != null)
        {
            var parentCategory = Category.GetCategory(parentId.Value);
            links.Add(string.Format(crumb, parentCategory.RelativeLink, parentCategory.Title));
            parentId = parentCategory.Parent;
        }

        if (links.Count > 1)
        {
            links.Reverse();
        }

        string catCrumb = string.Format(
            crumb,
            Utils.RelativeWebRoot + "category/allcats.aspx",
            Resources.labels.all + " " + Resources.labels.categories
        ) + separator + string.Join(separator, links.ToArray());

        string rss = string.Format(
            rssPostListLink,
            cat.FeedRelativeLink,
            this.rssText + " " + Resources.labels.category + " " + cat.Title,
            Resources.labels.subscribe
        );

        return "<div id=\"postListLead\">" + catCrumb + "</div> " + rss;
    }