Change MasterPage Image Based on Category

Jun 13, 2011 at 1:44 PM
Edited Jun 13, 2011 at 1:45 PM

In my site.master layout I have an image that I want to change based on the current category.  For those pages that aren't a post (like the home page) I have one image I want to display, then I have separate images for each of the top-level categories.  So I guess I need to determine: 

1) If I'm on a post page or not.

2) If I'm on a post page, which category the current post is in and whether it matches a top-level category for which I have an image associated.

 

Thanks.

Jun 13, 2011 at 2:48 PM

Easiest check for post is to check "/post/" sunstring in request url.

And then Post.Categories will give you what all categories the post belongs to.

Jun 13, 2011 at 2:57 PM

This post may also help. Adding default images for each category 

Jun 13, 2011 at 7:41 PM
Edited Jun 13, 2011 at 7:49 PM

Unfortunately the Post.Categories property is not available from site.master.cs (presumably because it is not a Post page).  If I try to reference Post.Categories from the Master Page I get an object reference error.

Remember I need to switch an image in my Master Page (site.master), not an image within each individual post.  So, I need a way to determine, from the Master Page, the category of the post being viewed (if it is indeed a post page).

 

 

 

Jun 13, 2011 at 9:02 PM
Edited Jun 13, 2011 at 9:28 PM

Not one hundred percent on exactly what you are trying to accomplish, but bitnbytes is pointing in the right direction, if you query the URL and can determine you are on a post then you should be able to access Post.Categories when you need to do so.

Here is some sample code, following on from the post discussion referenced above on adding default images for categories.

  Code behind site.master - untested - to demonstrate the logic

public partial class site : System.Web.UI.MasterPage
{
    //Something to store your page types
    private enum PageStyle { Cat, Front, Post, Other }
    private PageStyle _pageLocation;
    private Page _page = null;

    //Have a folder to use for storing category images - with image names to match category names 
    private string imageRoot = Utils.AbsoluteWebRoot.ToString() + "themes/Default/images/categories/";

    protected void Page_Load(object sender, EventArgs e)
    {
        _pageLocation = GetPageLocation();

        if (_pageLocation == PageStyle.Front)
        {
            //Do front page stuff
            return;
        }

        //If you are viewing by category then add the title and the matching categrory image
        if (_pageLocation == PageStyle.Cat)
        {
            if (!String.IsNullOrEmpty(Request.QueryString["id"]))
            {
                string cTitle = Category.GetCategory(new Guid(Request.QueryString["id"])).Title;
                HtmlGenericControl hdr1 = new HtmlGenericControl("h1")
                {
                    InnerText = "All posts in " + cTitle
                };
               
                //cphHdr for this example would be a placeholder on your master somewhere suitable
                cphHdr.Controls.Add(hdr1);
                HtmlImage cImg = new HtmlImage()
                {
                    Src = imageRoot + cTitle + ".gif", //or .jpeg or whatever - as long as they are consistent in type
                    Alt = cTitle,
                    Width = 64,
                    Height = 64
                };
                cImg.Attributes.Add("class", "catImg");
                cphHdr.Controls.Add(cImg);
            }
            return;
        } 
        /********************************************************************************************/
        if (_pageLocation == PageStyle.Post)
        {            
            //You now know you are on a post, so you can get a post reference and access it's properties
            //Do stuff
        }
        /********************************************************************************************/
    }


    #region GetPageLocation
    private PageStyle GetPageLocation()
    {
        //Query the URL to determine what you have, could test for tag, post, page(specifc page - archive, contact) etc.
        string path = HttpContext.Current.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)
        {
            // Browse by date ends in default.aspx, it's the front only if year is not present in the querystring parameter
            if (String.IsNullOrEmpty(HttpContext.Current.Request["year"]))
            {
                endPath = path.Substring(path.LastIndexOf('/') + 1);
                if (endPath.StartsWith("default.aspx") || endPath == "")
                {
                    return PageStyle.Front;
                }
            }
        }
        if (path.Contains("category/"))
        {
            return PageStyle.Cat;
        }
        if (path.Contains("post/"))
        {
            return PageStyle.Post;
        }
        //If path contains other things you want to find and so on and so on
        //eventually
        return PageStyle.Other;

    }
    #endregion
}
Jun 13, 2011 at 9:02 PM
Edited Jun 13, 2011 at 10:41 PM

Probably should have given a better example for the post method, needs testing.

 

if (_pageLocation == PageStyle.Post) {

   if (!String.IsNullOrEmpty(Request.QueryString["id"])) {
      //Get the first category for that post, it could be assigned to more than one
      string firstCategory = Post.GetPost(new Guid(Request.QueryString["id"])).Categories[0].Title;
      //Do other stuff
   }

} 
Jun 14, 2011 at 1:30 PM

Thanks Andy, that code works.  What was throwing me off was I was initially trying to access the Post.Categories property which wasn't available in the Master Page.  Also I was confused how you pulled the Post ID from the QueryString when nothing was appearing in the address bar, but obviously it is being stripped-out.

I had worked out another method where I set a Session variable in the post.aspx.cs page and then in the Page_PreRender of the site.master.cs I was reading that Session variable and changing the Master Page theme accordingly.  However, your method is much cleaner and doesn't require turning on Session variables which is nice.