New Community Website

Ordinarily, you'd be at the right spot, but we've recently launched a brand new community website... For the community, by the community.

Yay... Take Me to the Community!

The Community Blog is a personal opinion of community members and by no means the official standpoint of DNN Corp or DNN Platform. This is a place to express personal thoughts about DNNPlatform, the community and its ecosystem. Do you have useful information that you would like to share with the DNN Community in a featured article or blog? If so, please contact .

The use of the Community Blog is covered by our Community Blog Guidelines - please read before commenting or posting.

DotNetNuke Tips and Tricks #23: Extending the Blog Module

Have you ever been given a technical challenge that just seemed to interesting to pass up? This past weekend I was asked the question about extending the blog module to add an author biography to the footer of the blog post.  The gist of the question was how could we do this without causing problems on upgrade.  Since I always like a good challenge, I thought this would be a good opportunity to also show how a little creativity will allow you to solve many of the challenges that you face in DotNetNuke.

I have felt for a while that the DotNetNuke blog module was quite capable, but needed a few helper modules to give it a boost.  This is a perfect showcase on how to extend a module without actually changing the module or any of it’s data.  I also thought this would be a good opportunity to learn a few new techniques so I included the use of the new jQuery Templates which were added in jQuery 1.4.3, but which are also available as a separate download.

The first step in developing the module was to figure out how I was going to change the blog entry view.  In looking at the HTML which was generated you can see the general structure of a blog entry.  There is a couple of elements above the entry to display things like the title, date and author, and then a few elements below the entry to display the footer, sharebadge and comments.

<div class="BlogBody">
  <div class="BlogHead"></div>
  <acronym class="BlogPublished"></acronym>
  <p class="BlogSubHead"></p>
  <div class="HorizontalLine"></div>
  <!-- Blog Entry -->
  <div class="BlogFooter"></div>
  <div id="ShareBadgePRO_Toolbar" class="ShareBadgePRO_Toolbar"></div>
  <!-- Comments Section -->

In order to add my author biography block, I would need a method to inject some HTML into the page at a predefined position.  Of course this is challenge that is easily solved with jQuery.  If I have some HTML and I know where I want to place it on the page I can make a simple call like:


One of the goals I had in mind when developing the module is that I wanted to be able to allow the administrator to control the template that is used for laying out the biography block.  This would allow the administrator to control which Profile elements are displayed and how to arrange them on the page.  I had two options which immediately sprang to mind: 1) use the DotNetNuke Token engine, or 2) use the new jQuery templating engine.

While there are many nice aspects of the core token engine, one of its major shortcomings is that it does not allow for conditional logic (or any other kind of logic for that matter).  If you look at the new Profile page for the default Host User in DotNetNuke this becomes readily apparent.  Since the Host user does not have any profile data, you are left with a lonely “,” sitting in the middle of the display.  The built in token solution does not allow me to control the display based on the presence or absence of data.  When a profile address is completely filled out, the comma is a desired element, but when there is no profile data we really should hide the comma.

The jQuery templating plugin that was built by Microsoft addresses most of the templating problems I have encountered with the core DotNetNuke tokenization API.  The jQuery templates support the use of tags like {{if}}, {{each}}, {{html}} and {{wrap}} to provide basic logic and formatting of the final output based on the data that is available.  For me this is a critical need in any template solution, making the jQuery templates the clear winner for this module.

One other item that I needed to solve on the JavaScript side was dealing with the various browsers and jQuery versions.  In order to use the jQuery templates, I would save the profile data to the page using the ClientAPI, which I outlined in my earlier post on passing server variables to client side JavaScript.  I would need a way to parse this data which is stored as JSON so that I could bind it to my template.  Most modern browsers already provide native JSON parsing, but for those that didn’t, I would need to load the JSON2.js file which is the API that modern browsers emulated when adding the native capability.  I would likewise need to perform a similar check to determine whether or not to load the jQuery Templates plugin.  The basic test looks something like this:

//Load JSON script for older browsers
if (!(typeof (JSON) === 'object' &&
  typeof (JSON.stringify) === 'function')) {
  $.getScript(serviceUrl + 'js/json2.js', function () {
    bio = JSON.parse(bio);
else {
  bio = JSON.parse(bio);

With all of the major issues out of the way, I just need to pass the data to the template and inject the final HTML into the page at the right location, but nothing that is too difficult.  With the client side code out of the way, I can move my attention to the server side code.

On the server side, I really just need to be able to gather the appropriate profile data and pass that data to the client code.  There is no real magic here since it is just looking for the entryid from the querystring and using the blog entry to get the author’s user object.  I selectively pull the desired user profile properties and convert them to a JSON object.

Dim author As String = (New With {.UserId = ui.UserID, _
  .UserName = ui.Username, _
  .DisplayName = ui.DisplayName, _
  .ImageUrl = ui.Profile.AvatarURL, _
  .Biography = If(bio.PropertyValue Is Nothing, _
                  Localization.GetString("EmptyBiography", LocalResourceFile), _
                  HttpUtility.HtmlDecode(bio.PropertyValue)), _
  .Website = ui.Profile.Website, _
  .Country = ui.Profile.Country}).ToJson()

The end result of all of this is that we now have the ability to add a biography section to the blog, and all without touching the blog module.  In the video below you can see the module in action.


You can download the source code and the working module on the BlogBio project page at CodePlex.

This article is cross-posted from my personal blog.


Comment Form

Only registered users may post comments.


Aderson Oliveira (22)
Alec Whittington (11)
Alessandra Davies (3)
Alex Shirley (10)
Andrew Hoefling (3)
Andrew Nurse (30)
Andy Tryba (1)
Anthony Glenwright (5)
Antonio Chagoury (28)
Ash Prasad (37)
Ben Schmidt (1)
Benjamin Hermann (25)
Benoit Sarton (9)
Beth Firebaugh (12)
Bill Walker (36)
Bob Kruger (5)
Bogdan Litescu (1)
Brian Dukes (2)
Brice Snow (1)
Bruce Chapman (20)
Bryan Andrews (1)
cathal connolly (55)
Charles Nurse (163)
Chris Hammond (213)
Chris Paterra (55)
Clint Patterson (108)
Cuong Dang (21)
Daniel Bartholomew (2)
Daniel Mettler (181)
Daniel Valadas (48)
Dave Buckner (2)
David Poindexter (12)
David Rodriguez (3)
Dennis Shiao (1)
Doug Howell (11)
Erik van Ballegoij (30)
Ernst Peter Tamminga (80)
Francisco Perez Andres (17)
Geoff Barlow (12)
George Alatrash (12)
Gifford Watkins (3)
Gilles Le Pigocher (3)
Ian Robinson (7)
Israel Martinez (17)
Jan Blomquist (2)
Jan Jonas (3)
Jaspreet Bhatia (1)
Jenni Merrifield (6)
Joe Brinkman (274)
John Mitchell (1)
Jon Henning (14)
Jonathan Sheely (4)
Jordan Coopersmith (1)
Joseph Craig (2)
Kan Ma (1)
Keivan Beigi (3)
Kelly Ford (4)
Ken Grierson (10)
Kevin Schreiner (6)
Leigh Pointer (31)
Lorraine Young (60)
Malik Khan (1)
Matt Rutledge (2)
Matthias Schlomann (16)
Mauricio Márquez (5)
Michael Doxsey (7)
Michael Tobisch (3)
Michael Washington (202)
Miguel Gatmaytan (3)
Mike Horton (19)
Mitchel Sellers (40)
Nathan Rover (3)
Navin V Nagiah (14)
Néstor Sánchez (31)
Nik Kalyani (14)
Oliver Hine (1)
Patricio F. Salinas (1)
Patrick Ryan (1)
Peter Donker (54)
Philip Beadle (135)
Philipp Becker (4)
Richard Dumas (22)
Robert J Collins (5)
Roger Selwyn (8)
Ruben Lopez (1)
Ryan Martinez (1)
Sacha Trauwaen (1)
Salar Golestanian (4)
Sanjay Mehrotra (9)
Scott McCulloch (1)
Scott Schlesier (11)
Scott Wilkinson (3)
Scott Willhite (97)
Sebastian Leupold (80)
Shaun Walker (237)
Shawn Mehaffie (17)
Stefan Cullmann (12)
Stefan Kamphuis (12)
Steve Fabian (31)
Steven Fisher (1)
Timo Breumelhof (24)
Tony Henrich (3)
Torsten Weggen (3)
Tycho de Waard (4)
Vicenç Masanas (27)
Vincent Nguyen (3)
Vitaly Kozadayev (6)
Will Morgenweck (40)
Will Strohl (180)
William Severance (5)
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out