free geoip CS Tidbits - Jayson's Blog - jaysonKnight.com
jaysonKnight.com
Welcome to my corner of the internet

CS Tidbits - Jayson's Blog

  • CS Tidbit #28: Creating Nested Navigation Bar Items

    In my previous CS Tidbit, I outlined how to add an archive page to your blogs to free up some sidebar real estate while still giving readers access to our post history. Of course, now that we have this in place, how do we let our readers know where it is? In the past, adding links to one of the standard sidebar widgets meant manually adding entries to various skin files, and doing it in each theme on our site. There was also really no way to control security on the links either without adding some more customizations, ie if you had a link that you only wanted displayed to logged in users, or to owners of a particular section (Sharepoint calls this Security Trimming, I'm not sure what CS refers to it as).

    Fortunately for us, CS now supports creating nested navigation bar items via the control panel, and also allows us to specify security attributes to control what audience gets to see these links. In this tidbit, I'll outline how to accomplish this. Our end result is going to look something like this:

    image

    This is just the standard navigation bar that you'd see in CS2008.5's Hawaii theme, along with 4 nested navigation bar items. To create these items, navigate to Control Panel and select Site Administration, and then head over to Site Theme. The url to this page will look something like http://<yourSite.com>/ControlPanel/Settings/ThemeConfiguration.aspx. In the theme configuration editor, select the Header tab and look for the section called Navigation Bar. You'll see a box similar to the one pictured here:

    image

    In this example, we'll add a link to the archive page we created in the previous CS Tidbit. Click the Add button, and then fill in information similar to the following:

    image

    Once you're done putting in the correct info, click save. You can then click and drag the newly created link to the section where you'd like it to be nested under. It's actually a pretty slick control. Once you have it where you want, click the save button in the lower right hand corner and navigate back to your site. The newly created nested navigation item should be displayed under the section you placed it in. All of this adds some nice navigational touches for your site visitors to be able to find stuff in an easier more consistent manner.

  • CS Tidbits #27: Add An Archive Page For Blogs

    It's been a while since I've posted any CS Tidbits, but now that Community Server 2008.5 has been released, it's time to get back in gear and post some tips and tricks that I'm learning as I get to know this new release.

    If you're like me and have been blogging for a non-trivial amount of time (over 5 years in my case), an archived list view of your posts starts to look a bit unwieldy. CS 2008.5 does ship with an archive widget to display in your blog's sidebar, however this will lead to a long page length, and doesn't look as tidy as it could if the archive list could live in its own page. Fortunately for us, adding a dedicated archive page is easy enough. First, create a blank .aspx page in your /themes/blogs/hawaii directory, and name it archive.aspx. Then just add the following markup to it:

    <%@ Page Language="C#" AutoEventWireup="true" EnableViewState="False" MasterPageFile="theme.Master" Inherits="CommunityServer.Blogs.Controls.CSBlogThemePage" %> 
     
    <asp:Content ContentPlaceHolderID="bbcr" runat="server">
        <div class="CommonBreadCrumbArea"><div class="Common">
            <CSBlog:WeblogData Property="Name" LinkTo="HomePage" runat="server" />
            &raquo;
            <CSBlog:WeblogData LinkTo="archive" runat="server" Text="Archive" />
        </div></div>
    </asp:Content> 
     
    <asp:Content ContentPlaceHolderID="tr" runat="server">
        <CSControl:Title runat="server" IncludeSectionOrHubName="true" IncludeSiteName="true" EnableRendering="true" Tag="H1" CssClass="CommonTitle">
            <ContentTemplate><CSBlog:WeblogData runat="server" Text="Archive" /></ContentTemplate>
        </CSControl:Title>
    </asp:Content> 
     
    <asp:Content ContentPlaceHolderID="bcr" runat="Server"> 
     
        <div class="CommonContentBox">
            <div class="CommonContentBoxContent">
                <CSBlog:ArchiveDataItemList runat="server" />
            </div>
        </div>
    </asp:Content>

    That should be all you need to do as the URL for the page is already wired up correctly in your SiteUrls.config file by the following line:

    <url name = "weblogarchive"  path="##blogdirectory##archive.aspx" pattern="##blogName##/archive.aspx"  physicalPath="##blogthemeDir##" vanity="{2}?App=${{app}}" page="archive.aspx" indexable="false" />

    To view the newly created archive page, navigate to <yourSite>/blogs/<blogName>/archive.aspx. Of course you'll want to add a link to this somewhere on your blog. I'll cover how to create a nested navigation bar for blog links in a future CS Tidbit post.

  • CS Tidbits #26 -- Harness The Power Of Config File Overrides

    Now that Community Server 2007 has been released, it's time to fire up the CS Tidbits category again and see what I can come up with. Coming tidbits will still be geared towards site admins (making your site easier to use, simple tweaks and additions, etc), but I'll also go into some details about Chameleon, CS's long awaited skinning engine overhaul.

    Today's tidbit is one of the most commonly requested scenarios (I've covered it before): "I want to add a new menu tab/add a second blog/etc to my CS installation, how do I do that?" Fundamentally the concept is the same as in previous versions of CS...you need to modify your SiteUrls.config file which is where all the magic of URL rewriting is laid out. CS 2007 introduces the notion of override.config files, which in their simplest of forms take on the name of *_override.config where * is the name of the config file you wish to modify (of course you cannot apply any overrides to the web.config file seeing as it's a special file for the asp.net runtime), and you then use XPath notation to manipulate (or add) tags to your config files. I am by no means an XPath expert, if you are curious about the syntax and rules there are numerous resources on the web at your disposal, plus an entire army of experts over on CS.org who are happy to help out.

    The scenario I ran into was the following: I needed my CS site to remain unchanged at the root (http://jaysonknight.com shows the aggregate page), needed /blog to point towards my main blog, and have /feeds map to my external news section without having the application key in the URL. Note: this post assumes you've already configured both blogs in Control Panel before doing anything else.

    The first thing we need to do (which remains unchanged from previous versions of CS) is add the physical menu tab which links to the second blog. You must specify this value in the actual SiteUrls.config file, it cannot be specified in an override file. All override files are actually processed first by the CS runtime, so if you specify a new menu tab location in an override you have no control over the order it will appear in the menu, meaning it will show up first. In my case I needed it to be 3rd, so just add it after the first 2 <link> elements. Here's the line to add to the <navigation> element in SiteUrls.config:

     

    <link name="feeds" resourceUrl="feedshome" text="External News"
    roles="Everyone" applicationType = "Weblog" />

    Now we need to do the actual URL manipulation, so create a blank file called SiteUrls_override.config and add the following:

     

    <?xml version="1.0" encoding="utf-8" ?>
    <Overrides>

    <Override xpath = "/SiteUrls/locations/location[@name='weblogs']" mode = "change"
    name = "path" value = "/" />
    <Override xpath = "/SiteUrls/locations/location[@name='weblogs']" mode = "new"
    name = "physicalPath" value = "/blogs/" />

    <Override xpath = "/SiteUrls/locations/location[@name='weblogs']/url[@name='webloghome']"
    mode = "update">
    <url name = "webloghome" path="blog" pattern="default.aspx"
    physicalPath="/themes/default/common/" vanity="{2}" page="home.aspx" />
    <url name = "feedshome" path="feeds" pattern="default.aspx"
    physicalPath="/themes/default/common/" vanity="{2}" page="home.aspx" />
    </Override>
    </Overrides>

    All we're doing is resetting the URL of the weblogs link element to '/' (root), then mapping all requests to be routed to the physical /blogs/ directory in your CS installation (where all the dummy .aspx pages are located to pass the request off to the asp.net runtime), however you will still need to create a directory for each of the <url> elements named with the value in the path attribute, and put a blank default.aspx page in them. You'll notice the mode attribute specified a couple of times above...the accepted values should be fairly self explanatory...it's this value that tells the override parser what to actually do with the XPath statements, how to apply them to the existing config files. Lastly we do the actual URL rewriting in the mode=update block of XPath by mapping the url names to the links specified in the <location> element, and then telling CS what to display, in this case generating a url in the root/applicationKey format (since the path was reset to /, we specify the new path as /blog or /feed, etc). In our case we want home.aspx to display rather than postlist.aspx (the default). Following this pattern you can add as many blogs to your site as you are licensed for.

    As should be fairly obvious, the power of config files means simplicity, reusability, and portability of your config file customizations without having to actually edit the config files themselves. A bit of trial and error might be necessary for the uninitiated, but the benefits of having a system like this in place should be obvious.

  • CS Tidbits #25: Disable Stale Spam Comment Auditing

    I've been in the process of building some Community Server add-ins lately (namely a couple of Control Panel add-ins) and stumbled across today's tidbit: Comments that are deemed as spam (they have accrued enough points to be considered as such) and are also flagged as stale (they've been sitting in your database for x number of days) are cleaned up on a regular basis by the DeleteStaleSpamComments job which runs every x number of days that you configure it to fire. 

    There are a couple of issues with this process:  A) the job interval will get reset if the asp.net process hosting your CS installation restarts before the configured number of days pass by (which I will address in a future Tidbit) and thus will never fire, and B) while the comments are indeed deleted from the cs_posts table, they are archived into the cs_posts_deleted_archive table, so whatever space they were taking up isn't actually freed back to your database.  The fix for this is easy enough...locate the cs_weblog_DeleteStaleSpamComments stored procedure and delete the following block of SQL:

    INSERT cs_posts_deleted_archive (PostID, UserID, SectionID, SettingsID, ApplicationType, Body, Subject, IPAddress, DeletedDate, ParentID, ThreadID, PostLevel, PostType, PropertyNames, PropertyValues, SpamScore, PostStatus) SELECT P.PostID, P.UserID, P.SectionID, P.SettingsID, 1, P.Body, P.Subject, P.IPAddress, getdate(), P.ParentID, P.ThreadID, P.PostLevel, P.PostType, P.PropertyNames, P.PropertyValues, P.SpamScore, P.PostStatus FROM cs_Posts P INNER JOIN @CommentsToDelete D ON P.PostID = D.PostID

    That is unless you really want all of your comment spam archived in case you decide one day you want them back.

  • CS Tidbits #24: Aggregate Your Site's Aggregates

    This question came up over on the CS.org forums recently: "Is there a 'super' aggregate for all feeds in a Community Server installation?" 

    The short answer is no, however with the introduction of Content Mirroring in the 2.1 release, the somewhat longer answer is yes...but it isn't apparent at first glance.  What you'll need to do is create a new Mirrored Content Section to house your site's existing syndication feeds (in essence what you're doing is combining all of your feeds into a single section); by doing this that section will then expose a new feed containing all of your site's content, thus a single feed for your entire site.  This may sound a little confusing if you're not familiar with how Content Mirroring works in CS...for a refresher see tidbits 16 and 18 (though in this case, the steps outlined in #18 are optional).

    Sidenote:  Things have been quiet from most of the CS MVPs, and over on CS.org in general.  I personally attribute this to CS becoming a more self-sustaining entity...just a few months ago it was all anyone could do to keep up with the amount of posts coming in over on the forums, but I've noticed recently that A) the CS community is growing which means B) the amount of viable content over on the support forums is growing as well.  The fact that Telligent has the likes of Dave Burke and Rick Reszler manning the forums on a regular basis certainly helps as well.  For me this has been delightful to watch, especially having been actively involved with CS for over 2 years now; I can only imagine how giddy this makes the Telligent devs seeing the fruits of their labor create its own eco-system.  For me, this is what community based collaboration and support is all about...knowing at the end of the day that perhaps you made someone's life just a little bit easier.

    Anyone else feeling reminiscent should take a stroll down J-O's CS Museum page.

  • CS Tidbits #23: Tweak Your Mirrored Content Job

    Today's tidbit is another easy one to implement that would otherwise go unnoticed unless you were experiencing the same issues that some of the CS MVPs were having on our dedicated box.  Short version: If you have more than a trivial number of feeds defined for a mirrored content section (in my case, I have over 50), the RollerBlogUpdater job can bog down your system when it kicks off, i.e. peg the processor at 100% and bump memory up a couple dozen megs when it runs.  Does this happen in all instances?  I don't have any hard data to back that up, but the 2 cases I've seen where more than 20 feeds were defined it was indeed occurring. 

    Long version: Easy explanation...latency.  Well, latency combined with the fact that the job which fetches mirrored content executes on the main thread of CS, which means it blocks execution until the job completes.  If you have 50 feeds to pull, and latency averages 1 second, that's 50 seconds for the job to run with the caveat of blocking execution for anything else running on the main thread as well as pegging the processor the entire time.  On a dedicated box this might not matter, but in a shared hosting scenario this could lead to overall degradation of the machine depending on A) how many sites the box is hosting and B) how many of those are CS sites with a non-trivial amount of mirrored content feeds.  It is worth mentioning that the memory is reclaimed fairly quickly whenever garbage collection kicks in, and of course the processor settles down once the job completes, but the fix is trivial: put the RollerBlogUpdater job on its own thread by editing your CommunityServer.config, adding the singleThread = "false" attribute to that job node:

    <job singleThread = "false" name = "RollerBlogsUpdater" type = "CommunityServer.RollerBlogs.Components.RollerBlogUpdater, CommunityServer.RollerBlogs" enabled = "true" enableShutDown = "false" />

    Now when that job kicks off, it'll spawn on it's own thread (thus not blocking main execution) and processor utilization will be normal while the job runs.

  • CS Tidbits #22: Tame That Tag Cloud

    Rob Howard recently posted about an interesting topic: Should tags in CS be moderated.  My opinion on that is outside the realm of today's tidbit (though I'll give you a hint...I think options are always a good thing), but there is a sort of band-aid solution that can be applied in the interim if site admins notice their tag clouds spiraling rapidly out of control which can happen in one of 2 scenarios: Users are abusing tags, or you have a blog that hosts mirrored content from a large number of sites that all have members posting their content to various tags.  Before long you end up with a very large tag cloud with numerous (random) tags that only have 1 or 2 posts in them, which leads to clutter and messiness.

    There are actually 2 ways around this:

    1. Define default tags for your aggregate...only those tags will be displayed in the tag cloud, but the side effect of this is that only posts grouped in the default tags will be displayed on the aggregate.  This actually tripped up many of the posters over on weblogs.asp.net when it was upgraded to CS 2.1, plus it's tedious to set up.  A more ideal solution would be to...
    2. Define the maximum number of tags that can be displayed in the tag cloud for a specific tag cloud control or
    3. Define the minimum number of posts a tag must contain to be displayed in the tag cloud.

    I personally think #3 is a more ideal solution, but I'll cover both as it's quite easy to implement.  Any control that declares a <Blog:TagCloud> control (or any type of tagcloud, i.e.<CS:TagCloud>, <Galleries:TagCloud>, etc) expose both a MaximumNumberOfTags property (applies to #2, the default value is 100) and a MinimumPostsPerTag property (applies to #3, the default value is 1).  Things should be pretty self explanatory at this point, simply add one (or both) of the above properties to your tag cloud control declaration in your skin file and set the value that you want.  Of course these numbers should be set based on just how wild you want your tag cloud to get.  For sites with lots of members/posters, I would recommend going with a MinimumPostsPerTag value of 5; that should weed out any stray tags that aren't pertinent to the main focus of the site.  It's that simple!

  • CS Tidbits #21: Exploring The CS Spam Blocker

    Blog spam...it's the new (well, not so new) scourge of the internet.  On my site alone I get several hundred attempts a day from spammers wanting to leave their garbage on my blog.  Fortunately Community Server ships with a built-in spam blocking tool; unfortunately it's not very well documented and can be a bit vague to new users/site admins.  In this Tidbit I'll attempt to clear up any ambiguity about the Spam Blocker and demonstrate how to get it configured properly so that site admins can (hopefully) rid their sites of spam.

    CS uses a rules based scoring system to try and identify potential spams; when CS receives any type of content it has to go through the rules configured in the Spam Blocker (content meaning a blog post, a comment on a blog, a post to a forum, gallery, etc...anything and everything that can be posted to your site by users).  Within each rule itself you can specify how to score the content by assigning points (I like to call them penalties) based on criteria that you specify in the rule.  When content comes into CS it has a score of 0; as it passes through the rules engine it accrues penalties based on thresholds that you can define within each rule.  The default Spam Blocker settings for marking content as spam is 5 penalties (meaning it will still get stored in your database but won't be published...you can review that content to decide if it actually is spam), and the content will be automatically deleted if it reaches 10 penalties.  These are the values I will use in this post; both of these values are configurable in the Spam Blocker administration tool in Control Panel.

    Let's dig a little deeper as this can seem a bit complex at first glance.  The 4 rules that ship with CS are:

    1. Forbidden Word Rule:  Rates spam factor based on the existence of configured forbidden words.  By default this rule will assign 5 penalties to a post that contains any forbidden word that you define within the rule.  So, if you want to flag posts that mention Windows or Linux as spam (just using a hypothetical example), you would add those words to the list, and if content comes in that mentions both of these words, it would accrue 10 penalties and be automatically deleted.  If it mentions just one of the words it will accrue 5 penalties and then you can decide whether to publish the content or not.
    2. Bad Word Count Rule:  Rates spam factor based on number of occurrences of configured bad words.  By default this rule will assign 2 penalties per occurrence of a specified bad word (and CS ships with a predefined list).  Again, this is configurable within the rule itself so if you wanted to allow 3 occurrences of a bad word before assigning penalties, you'd simply change the "maximum number of times" setting to 3.
    3. Link Count Rule:  Rates spam factor based on number of links (href's) in the post.  This rule has no default settings, but is the most important rule to configure IMO as it will weed out 90% of spam; most spams are simply a list of links.  My experience (at least as it relates to blogging, this is probably very different when it comes to the forums realm) has been that any content with more than 3 links is probably spam, so I assign 5 penalties per link that exceeds this threshold.
    4. IP Count Rule:  Rates spam factor based on the number of recent posts from the same IP address.  This rule is a little more complicated than the other rules, but is also a key one to configure properly as most spams are automated; the spammer attempts to connect to your site with a bot and post as much content as possible within a specified timeframe (usually just a couple of minutes).  This rule will assign penalties to a specific number of posts from the same IP address within a specified threshold.  My settings are to assign 5 penalties to content that exceeds 5 attempts within 60 seconds.  You can exclude IP addresses from this rule if you're running tests on your site or whatnot, or if you are a CS application owner and regularly make posts with lots of links you can exclude your IP so that your content won't be flagged as spam.

    Generally speaking these rules should cover all of your spam blocking needs, however the key factors to consider when configuring your Spam Blocker are:

    • How many penalties to assign content based on exceeded thresholds (this seems to trip up site admins more than any other factor).
    • How many penalties content can accrue before being automatically moderated and/or deleted. 

    This will of course vary from site to site.  On my site (which is blog-centric) I only have rules 3 and 4 enabled and am virtually spam free (at the very least the spam isn't published to my site; I can go into Control Panel and delete it).  For a forums-centric site rules 1 and 2 are probably equally as important and should be configured properly as well, but rule 3 would need to have a higher link count threshold for obvious reasons.

    Of course like the rest of CS, the Spam Blocker is extensible and you can write your own rules (which is outside the scope of this post, but perhaps I'll delve into that later) if you'd like.  For example, you could write a rule that permanently bans an IP address if it exceeds certain thresholds, or as Thomas Freudenberg did you can write a rule that plugs into a 3rd party service (Akismet in this case).

    The Spam Blocker is a fantastic addition to Community Server, and when configured properly works quite well.  Hats off to Jose Lema (aka the Fajita Man) for doing the bulk of the work on this; well done sir.

  • CS Tidbits #20: Add Basic Stats To Your Blog

    I pulled a Ken in that I wrote a basic BlogStats control quite a while back and simply forgot about it, and it actually fits perfectly into my current series of CS Tidbits.  So I busted it out of Vault and cleaned it up a bit and added it to my current (soon to be published) CS Custom Controls project.  In a nutshell it's a simple control that can be dropped onto any of your individual blog's skin files to get some basic posting information such as is displayed in the image on the left.  Very basic, but useful enough IMO.  If anyone can think of other useful information that should be displayed let me know and I'll add it.

    You can download it from here, there is a readme file included with detailed instructions on how to install it.  I'm also cooking up some other nifty controls, so stay tuned.

  • CS Tidbits #19: Enable Tag Cloud Topic Count

    No lengthy screencasts today, just a quick and easy way to add an enhancement to your site that I believe users will appreciate.

    I'm all about numbers, I don't know why.  I like to see how many posts a blogger has made to their site, how many comments have been made, etc.  It's a useful barometer (for me at least) so see if it's an active blog or not, i.e. if someone has made a bazillion posts but only has 5 comments, then something is obviously wrong.  If there are only 50 posts but it has a bazillion comments, more than like the owner has given up due to comment spam.  Etc.  Only the finest blogs make it to my aggregator, and the following is (a one of many) useful metric to gauge what's going on over at a particular blog.

    In this evening's tidbit (which will be the first of a Tidbit mini-series to add this type of statistical information in various places on your site) we'll add a Topic Count counter to each tag in your tag cloud.

    It's dead simple.  Any control that declares a <Blog:TagCloud> control (or any type of tagcloud, i.e.<CS:TagCloud>, <Galleries:TagCloud>, etc) exposes a ShowTagCounts property, which they inherit from the CommunityServer.Controls.BaseTagCloud control.

    To enable the topic count, find any TagCloud control in your /skins/<skinThatContainsTagCloud> and find the TagCloud control declaration.  Add the following attribute: ShowTagCounts="true" before the closing wicket and topic counts will show up similar to the image on the left.  It's that easy.

1 2 3 Next >

Copyright © :: JaysonKnight.com
External Content © :: Respective Authors

Terms of Service/Privacy Policy