dasBlog is a decent blogging engine originally created by Clemens Vasters. A nice thing that not many people seem to be aware of is that you can easily extend it by creating custom macros. Such a custom macro isn't anything else than just a class library that you can hook into your copy of dasBlog and use it later on in one of the available templates that make up the website.

I couldn't really find a lot of information about this, so I decided to create my own article about the subject that also puts in the solutions I found. 
Also I would like to show the code that I use in my current installment that's reusable directly for other dasBlog users.

Creation:

So, as I already mentioned, creating macros is just like creating a class library. So lets fire up vs.net, create a new project and in the templates choose Class library like in Figure 1. The name of the project is also important when we will be configuring dasBlog to let it know about the existence of our macros. I chose MydasBlogMacros but you can choose your own name of course.


Figure 1: Create a new project based upon the Class Library template.

If you haven't downloaded the code for dasBlog now's a good time to do so. You can download the bits from the official site(1) or you can use the guideline to get the latest bits and pieces(2) like I did.

Now we have to add 3 references in order to be able to create our custom macro. You do this by right clicking in the Solution Explorer of Visual Studio.NET on the References node. Take a look at Figure 2 to choose System.Web, and Figure 3 to choose 2 assemblies that are from dasBlog itself. These 2 are newTelligence.DasBlog.Runtime and newTelligence.DasBlog.Web.Core. The result is shown in Figure 4.


Figure 2: locate and choose System.Web


Figure 3: Navigate to the bin folder of the compiled bits of dasBlog and select the needed assemblies.


Figure 4: After adding the needed references.

In Figure 4 you can also see that I deleted the default Class1.cs file and added a new class with the name Macros.cs. This is the only class we'll need for the moment. Here's the code for the Macros class:

    1 using System;

    2 using System.Collections.Generic;

    3 using System.Text;

    4 using System.Web.UI;

    5 using newtelligence.DasBlog.Runtime;

    6 using newtelligence.DasBlog.Web.Core;

    7 

    8 namespace MydasBlogMacros

    9 {

   10     public class MyMacros

   11     {

   12         protected SharedBasePage sharedBasePage;

   13         protected Entry currentEntry;

   14 

   15         public MyMacros(SharedBasePage page, Entry entry)

   16         {

   17             sharedBasePage = page;

   18             currentEntry = entry;

   19         }

   20 

   21         public virtual Control EmailIt(string linkText, string cssStyle)

   22         {

   23             if (this.currentEntry != null)

   24             {

   25                 string link = this.currentEntry.Link != null

   26                     ? this.currentEntry.Link : Utils.GetPermaLinkUrl(this.currentEntry);

   27 

   28                 return new LiteralControl("<a href=\"mailto:?subject=" + this.currentEntry.Title +

   29                     "&body=I found this to be a great read: " + link +

   30                     ". Hope you like it too.\" class=\"" +

   31                     cssStyle + "\">" + linkText + "</a>");

   32             }

   33 

   34             return new LiteralControl("");

   35         }

   36 

   37         public virtual Control Delicious(string linkText, string cssStyle)

   38         {

   39             if (this.currentEntry != null)

   40             {

   41                 string link = this.currentEntry.Link != null

   42                     ? this.currentEntry.Link : Utils.GetPermaLinkUrl(this.currentEntry);

   43 

   44                 return new LiteralControl("<a href=\"http://del.icio.us/post?url=" + link

   45                     +  "&title=" + this.currentEntry.Title + "\" class=\"" + cssStyle + "\">"

   46                     + linkText + "</a>");

   47             }

   48 

   49             return new LiteralControl("");

   50         }

   51 

   52         public virtual Control Digg(string linkText, string cssStyle)

   53         {

   54             string link = this.currentEntry.Link != null

   55                     ? this.currentEntry.Link : Utils.GetPermaLinkUrl(this.currentEntry);

   56 

   57             return new LiteralControl("<a href=\"http://www.digg.com/submit?url=" + link +

   58                 "\" class=\"" + cssStyle + "\">"

   59                 + linkText + "</a>");

   60         }

   61 

   62         public virtual Control Technorati(string linkText, string cssStyle)

   63         {

   64             if (this.currentEntry != null)

   65             {

   66                 string link = this.currentEntry.Link != null

   67                     ? this.currentEntry.Link : Utils.GetPermaLinkUrl(this.currentEntry);

   68 

   69                 return new LiteralControl("<a href=\"http://www.technorati.com/search/" +

   70                     this.currentEntry.Title +

   71                     "\" class=\"" + cssStyle + "\">"

   72                     + linkText + "</a>");

   73             }

   74 

   75             return new LiteralControl("");

   76         }

   77     }

   78 }

Note that the signature in the constructor is required in order to let the macros work!
Besides the constructor I created 4 methods, which will be the macros eventually, the first one EmailIt is for creating a link with the url of the current item in the body so someone can easily mail it to someone whom (s)he thinks will also be interested in the article. The other 3 are for well known web 2.0 services: del.icio.us, digg and technorati.

The methods/macros take all 2 input parameters: the string to appear in the link and the css style that will go in the class attribute of the rendered tag. Separating content and layout has several benefits: it's easy to update in a single place and an external .css file can be cached on the client.

After compiling the source code, preferably in Release mode, and after that open windows explorer and navigate to where the .dll file is created. By default this will be the place where you created your project and in there the subfolders /bin/Release. Now copy the .dll file to the /bin subfolder of the dasBlog solution (this is the same folder where you got your references from).

Configure dasBlog:

We created our macros assembly, dropped it in the /bin folder of the dasBlog folder, but we still need to configure dasBlog in such a way that it knows of the existance of our macros. This is entirely done in the web.config file that can be found in the root folder of dasBlog. Open it with your favorite IDE and uncomment the following line at the top of the web.config:

<section name="newtelligence.DasBlog.Macros" type="newtelligence.DasBlog.Web.Core.MacroSectionHandler, newtelligence.DasBlog.Web.Core" />

Now navigate to the tag <newtelligence.DasBlog.Macros>, uncomment it and add this line:

<add macro="mymacros" type="MydasBlogMacros.MyMacros, MydasBlogMacros"/>

Remember I told in the previous part that you could name your solution somewhat else, well here that name comes into play. If you take a look at the previous line you can see this combination: type="TypeName, Name of the assembly". TypeName in this case is NameSpace.ClassName. The name in the macro attribute, in this example mymacros will be used when we want to use a specific macro.

Use the macro in your template:

So at this point we created our macros, configured dasBlog that they exist. Now comes the part where we embed, or better use, our macros so they become visible in the what a visitor can see by altering the templates in the themes. dasBlog ships with several themes out of the box and people can switch between them. You can however push visitors to only have one theme available by deleting the rest of the themes. If you don't this you'll need to do the next steps for every theme if you want those themes to also have your macros available.

Navigate to the theme folder of choice. There you'll see several .css files and 3 files that have the extension .blogtemplate. Because the macros will be used for every item, they contain specific information for a specific item, open the itemTemplate.blogtemplate file. Here you can call a macro with the following syntax:

<%EmailIt("Email it!", "mailLinkStyle")|mymacros%>.

The call can be easily identified, it's the first macro in our example EmailIt. The method takes 2 parameters. After the method call you see the | followed by the name we provided in the macro attribute when we configured the web.config. I also created a new external .css file where I put the specific styles. After that I imported the newly created file into the base.css file with this statement: @import url("mymacros.css");

Resources:

- (1): dasBlog download.
- (2): Compiling the dasBlog source code.
- The class FooMacros in the dasBlog total solution.
- Creating dasBlog macros.

Article by Grz, Kris. http://blog.krisvandermast.com/CreatingCustomMacrosForDasBlog.aspx

 

(This is now a History Post – Information is now depreciated)

How-To Setup DasBlog for Development Using Visual Studio 2005

1. Get the latest dasblog source.  See information here http://www.hanselman.com/blog/DasBlogMovedFromCVSToSVN.aspx
2. Setup your virtual directory for newtelligence.DasBlog.Web and set it to use ASP.NET 2.0
3. Open “DasBlog All.sln” in notepad and modify the url for the newtelligence.DasBlog.Web project to point to your virtual directory.
4. Download and install the Visual Studio 2005 Update to Support Web Application Projects.
5. Download and install the latest version of Visual Studio 2005 Web Application Projects.  You can read about it here http://weblogs.asp.net/scottgu/archive/2006/05/08/445742.aspx and here http://webproject.scottgu.com/.
6. Open Visual Studio 2005 and go to File->Open Project/Solution
7. In the dialog, browse to your “Dasblog All” solution file and open it.
8. The Visual Studio Conversion Wizard will pop up.
9. After hitting next you will have the option to have the wizard create a backup of your project.
10. Finish the wizard.  The wizard should complete successfully without any errors.
11. Go to your web.config file and add cookieless=”UseCookies” to the <forms> element.  Read here for more information http://www.hanselman.com/blog/NewFormsAuthenticationSignOutBehaviorInASPNET20.aspx
12. In the Solution Explorer in Visual Studio 2005 click the Show All Files icon.  In the newtelligence.DasBlog.Web project right-click on the StringTables folder and select Include in Project.  Do the same for the site.config file in the SiteConfig directory.  You also may want to include other folders such as bin, content, and logs.
13. Modify the site.config and site.config.deploy to point to your virtual directory
14. Modify siteSecurity.config to setup your admin account.
15. Set directory permissions as you would for any other dasblog setup.
16. Rebuild Solution.
17. Enjoy

 

(This is now a History Post – Information is now depreciated)

The DasBlog project on SourceForge has migrated to SubVersion.

To browse the project on the web, go to:

http://svn.sourceforge.net/viewcvs.cgi/dasblogce/

To retrieve and work with the code, you need a SubVersion client.

You can use the command-line client:

http://subversion.tigris.org/

Or you can use the TortoiseSVN Windows shell

extension:

http://tortoisesvn.tigris.org/

In either case, you must enable the ASP.NET "hack". It simply requires you set an environment variable before working with SubVersion:

set SVN_ASP_DOT_NET_HACK=1

For more information about the hack, read http://www.codefez.com/Home/tabid/36/ctl/ArticleView/mid/364/articleId/191/Subversion-and-the-ASP-NET-Hack.aspx

The rest of this document will assume the command-line client. The equivalent actions with TortoiseSVN should be fairly obvious.

The first thing you will notice is that the project root folder (dasblogce), has 3 subfolders:

[branches]

[tags]

[trunk]

These 3 folders are a common convention in Subversion repositories. You can read about them in the Subversion book http://svnbook.red-bean.com/. If you are new to Subversion, I highly recommend you read the first 3 chapters. If you are already familiar with Subversion and how to use these folders, you can skip down to the section labeled *DasBlog Specifics.

*TRUNK

All work is done from the trunk folder. All checkins/commits should be to the trunk folder. In fact, when working with the code, you should treat /dasblogce/trunk as the root folder (as opposed to /dasblogce).

For example, to checkout a working copy of the entire codebase, you would use the following command:

svn checkout

https://svn.sourceforge.net:443/svnroot/dasblogce/trunk

dasblogce

This will create a new folder on your filesystem named dasblogce which contains all of the data under the trunk folder. Nothing from branches or tags will be retrieved.

*TAGS

The tags folder is used to hold milestone snapshots of the repository. Typically, after each release, you will create a new "tag", so that it is easy to retrieve the codebase corresponding to that release.

You create a new tag by copying the trunk folder to a new named subfolder of the tags folder.

For example, to take a snapshot of the codebase after making the 1.9.6180.1 release, you would run:

svn copy

https://svn.sourceforge.net:443/svnroot/dasblogce/trunk

https://svn.sourceforge.net:443/svnroot/dasblogce/tags/1.9.6180.1

If you forget to tag after a release, you can always reference the previous state if you know the revision number.

For example, I created a tag for the state of the codebase after the CVS migration (revision 410), even though the code had been modified since.

svn copy -r 410

https://svn.sourceforge.net:443/svnroot/dasblogce/trunk

https://svn.sourceforge.net:443/svnroot/dasblogce/tags/FinalCVSVersion

Note: There is nothing that technically limits you from checking out a working copy from the tags folder, and then committing changes. However, it is a VERY BAD IDEA. The tags folder should just contain snapshots in time. Make all changes to the trunk or a branch.

*BRANCHES

The branches folder is used to create alternate branches of the source base. The process for creating a branch is the same as creating a new tag. Just copy the trunk folder to a new subfolder of the branches folder. You can then checkout and commit your changes to the branched folder, and then merge it back into the trunk when appropriate.

 

*DasBlog Specifics

The DasBlog trunk folder has the following layout:

[docs]

[lib]

[source]

[tools]

package.bat

The source folder contains only the source code and automated unit tests created by the DasBlog development team. Under CVS, this folder held all files related to the project. The following sections will describe the new location for files that are not considered part of the DasBlog source code, but are still kept with the project.

The docs folder contains all documention and reference material (URL links). This includes the readme, license, and release notes.

The lib folder contains all compiled 3rd party assemblies referenced by the source code projects.

These files used to be in the source\Assemblies folder. The projects under the source folder have been updated to reference the files in the lib folder (which is why it is important to checkout the entire trunk, and not just the source subfolder, when working on code).

The tools folder contains all of the executables needed to support the development and packaging of DasBlog (not including the .NET Framework itself). For example, the tools\nunit folder contains all of the nunit executables required to run the DasBlog unit tests. Note that the nunit.framework.dll referenced by the test projects is copied to the lib folder - source code should not reference files in the tools folder directly. Keeping the tools stored with the project helps ensure that all developers on the project always use the same version. (You will want to remove NUnit from your GAC to avoid overriding the project copies.) For more information about this strategy, check out Mike Robert's excellent article "How to setup a .NET Development Tree":

http://www.mikebroberts.com/blog/archive/Tech/ArticlesandPapers/Howtosetupa.NETDevelopmentTreeWrapup.html

The CreateDasBlogVdir.vbs file is also in the tools folder, and has been updated so that it works properly from that location.

package.bat is the sole file in the root of the project (arguably, it could have been placed in the tools folder). It is used to create the release files to post on SourceForge. A number of changes have been made to the script, although the resulting release files are equivalent to files created with the previous version.

Most importantly, the script will now automatically determine the release version number based on the AssemblyVersion attribute in the source\AssemblyInfo.cs file. While you still have to manually update AssemblyInfo.cs when the time comes, you no longer need to modify package.bat for each release.

package.bat now takes an optional command-line argument. You can specify ALL (the default), WEB, or SOURCE. If you specify WEB or SOURCE, it will only create the one zip file.

All release files are created in the build subfolder.

The build subfolder is considered a temporary folder, so it is wiped out every time package.bat is executed, and Subversion has been set to ignore the folder (via the svn:ignore property).

 

Coding Standards

Summary : Documents the coding standards and conventions for DasBlog. This topic is very much in the works and under discussion as of 1/19/2004

Project Structure

·       All files for a particular namespace should be in their own folder.

·       A single project can contain multiple namespaces assuming the above rule is followed.

Naming conventions

·       Local variables will be in camelCase with no prefix such as underscore.

·       Fields (member variables) will begin with an underscore and then follow the camelCase convention. All non-private fields will be wrapped with properties.

o   shouldn't we use the "When in Rome" philosphy here? Some files use underscore, some just use camelCase, some use this.fieldName. -- OmarShahine

o   I think we should change it where we can. Without this convention, it can get mighty confusing in there. -- MichaelEarls

·       All non-private members will use PascalCase

Class Members

·       There shall be no public fields unless the entire class is used for XML serialization and contains no code.

 

 

Source Control Rules

The rules of engagement for the source control system are easy, but I'll kick out everyone (independent of celebrity or other honorary status) not following them. (Omar Shahine)

1.   If you are not sure whether you should/could/may add or change something, ask on the Developer Mailing List. Behave like a professional software developer, please -- even if you aren't one.

2.   Learn how to use CVS. ALWAYS DO A CVS UPDATE before checking in.

3.   All work is done in the "source" subtree. When we plan to turn "source" into a new release we will tag the source

4.   Unit Tests ALWAYS pass.

5.   If you want to add a feature or fix a bug, we expect that you understand what you're doing. If you have a big feature in the work you must add it here:  TBD

6.   Checked-In items compile, work as expected and add features, not remove features. The checked-in code ALWAYS builds. Checking in functionality that doesn't build should be avoided at all costs.

7.   Any new feature that you add must be configurable. So, either you extend the macros classes to allow a user to embed (or not to embed) your new element or if you change the engine behavior, add an appropriate switch to site.config and an appropriate handler. The default value for switches for new features is "false" (unless there is a compelling reason for it to be true, ask an admin if you are not sure). if you want that users can easily switch it on, add it to the appropriate section in the configuration page.

8.   If you have GPL code in your pocket coming in, leave it at the door, please.

9.   This list may grow!

 

 

(This is now a History Post – Information is now depreciated)

Developing DasBlog

DasBlog sources, bug database, and message board can be found on the DasBlogCe SourceForge Project http://sourceforge.net/projects/dasblogce/ The GoDotNet Workspace is deprecated as we have moved to SourceForge.

If you wish to contribute to the project, consider Applying to the SourceForge Project.

Read the Source Control Rules and Coding Standards before you think about applying to be a developer.

Getting set up on SourceForge

1.     Developers will only be considered if you have source code and changes to contribute. You can get the source code from CVS by using anonymous access with a CVS client (see instructions in the next section). Email your changes to shahineo@hotmail.com.

2.     Download PuTTy

3.     Download TortoiseCVS

4.     Create a local folder for your sources like D:\dasBlog\

5.     Follow the instructions here for configuring TortoiseCVS and optionally PuTTy for using a private/public key to authenticate (rather than entering your password all the time).

a.  Once you have a key youy can get pageant.exe to load it by using the following command line: "C:\Program Files\PuTTY\pageant.exe keyname.ppk"

6.     The info to connect to the CVS server is:

a.  CVSROOT: :ext:[username]@cvs.sourceforge.net:/cvsroot/dasblogce

b.  MODULE: source

7.     Once you get set up you can CVC Checkout and get all the sources. ALWAYS do a CVS Update before checking in.

Retrieve the code via anonymous access and TortoiseCVS

1.     Download PuTTy

2.     Download TortoiseCVS

3.     Create a local folder for your sources like D:\dasBlog\

4.     Right-click on the new folder (D:\dasBlog) and choose "CVS Checkout..."

5.     For CVSROOT, put :pserver:anonymous@cvs.sourceforge.net:/cvsroot/dasblogce (This should automatically set the protocol to Password server :pserver:, the Server to cvs.sourceforge.net, the Repository folder to /cvsroot/dasblogce, and the username to anonymous. If not, set those values.)

6.     For Module, put source (note: the Fetch list... button does not seem to work for anonymous access)

7.     Click OK. A subfolder will be created (D:\dasBlog\source) containing all of the files.

8.     If you make changes to code retrieved via anonymous access, email them to shahineo@hotmail.com

Mailing Lists

 A Mailing List for dasBlog Developers: http://lists.sourceforge.net/mailman/listinfo/dasblogce-developers

 Mailing list for CVS commit messages: http://lists.sourceforge.net/mailman/listinfo/dasblogce-cvs

 

The following is the list of macros supported by DasBlog.

homeTemplate Macros

<%macroname%>

Description

Output

<%title%>

Weblog 'Title' as defined through the tag <Title> in the configuration file of the Web application.

Plain text

<%subtitle%>

Weblog 'SubTitle' as defined through the tag <Subtitle> in the configuration file of the Web application.

Plain text

<%radioBadge%>

Emits text 'newtelligence DasBlog (version)' and version number.

Plain text

<%rssLink%>

Hyperlink to the main RSS feed.

HTML hyperlinked HTML image

<%atomLink%>

Hyperlink to the Atom feed.

HTML Hyperlink

<%year%>

Current year.

Plain text

<%month%>

Current month.

Plain text

<%day%>

Current day.

Plain text

<%today%>

Current day formatted as short date.

Plain text

<%now%>

Current time (UTC).

Plain text

<%time%>

Current time formatted as short time.

Plain text

<%authorName%>

Copyright owner as defined through the tag <Copyright> in the configuration file of the Web application.

Plain text

<%bodytext%>

Placeholder for rendering page content.

HTML

<%titleList%>

List of entry titles that are displayed on the current page.

HTML

<%frontPageTitleList%>

List of entry titles that appear on the current front page. Uses the same CSS classes as TitleList.

HTML

<%siteName%>

Weblog 'Title' as defined through the tag <Title> in the configuration file of the Web application. Same as <%title%>.

Plain text

<%description%>

Site description as defined through the tag <Description> in the configuration file of the Web application.

Plain text

<%navigatorLinks%>

Renders a list of user-definable hyperlinks.

HTML

dayTemplate Macros

<%macroname%>

Description

Output

<%archiveLink%>

Hyperlink to archived entries. Works hand in hand with <%longDate%>

HTML hyperlinked HTML image

<%longDate%>

Protected field DayMacros.day formatted as long date. Works hand in hand with <%archiveLink%>

Plain text

<%items%>

Placeholder for rendering weblog entries.

HTML

itemTemplate Macros

<%macroname%>

Description

Output

<%itemText%>

The text of a single weblog entry.

Plain text

<%itemTitle%>

The title of a single weblog entry.

Plain text

<%itemDescription%>

The Description of a single weblog entry.

Plain text

<%when%>

The DateTime (formatted like in GMT) the entry was created.

Plain text

<%permaLink%>

A placeholder for rendering a permanent hyperlink for the current weblog entry.

HTML

<%commentLink%>

An HTML hyperlink to view comments on weblog entries.

HTML

<%trackbackLink%>

An HTML hyperlink to the Trackback endpoint.

HTML hyperlink

<%trackbackList%>

A placeholder to render a list of hyperlinks with referrers, trackbacks and pingbacks.

HTML hyperlinks

<%categoryLinks%>

Renders a list of links to the categories this item belongs to.

HTML

<%editButton%>

A placeholder for accessing the edit and delete buttons when logged in.

HTML

<%itemauthor%>        

A author of a single weblog entry.                                                                                  

HTML                 

Radio Userland compatible Macros

<%macroname%>

Description

Output

<%radio.macros.imageUrl(relativeUrl)%>

Returns an absolute URL to an image based on a partial URL contained in a design template.

Plain text

<%radio.macros.imageRef(relativeUrl)%>

Returns an absolute URL to an image based on a partial URL relative to the Radio system path. Renders one <img> tag.

HTML image

<%radio.macros.headlinks()%>

This macro renders a set of <link> and <meta> tags for including in the <head> section of the page.

HTML

<%radio.macros.blogroll(opmlFileUrl)%>

This macro renders an OPML outline. The outline is displayed as an hierarchical list.

HTML

<%radio.macros.weblogUrl()%>

The URL of this weblog.

Plain text

<%radio.macros.editThisPageButton()%>

Ignored in this version.

|Nothing

<%radio.macros.editorsOnlyMenu()%>

Renders the administrator bar (AdminNavBar.ascx), if the user is logged and is member of the "admin" role.

HTML

<%radio.macros.xmlCoffeeMug()%>

Generates a text link to the (equivalent of) the Radio coffee mug.

HTML hyperlink

<%radio.macros.mailTo()%>

Generates a link to the author's email address or some page providing feedback capability. Renders one <a> tag with the CSS class "mailToStyle" and an embedded <img> tage with the CSS class "mailToImageStyle".

HTML

<%radio.macros.getLastUpdate()%>

Renders the time of the last site update, expressed in GMT.

Plain text

<%radio.macros.staticSiteStatsImage()%>

Not used in this version.

Nothing

<%radio.macros.googleIt(expression)%>

Renders a search hyperlink, pointing to Google.com. The search expression is the title as passed the macro.

HTML hyperlink

<%radio.macros.weblogEditBox()%>

Renders (Placeholder) the EditEntryBox control.

HTML

<%radio.macros.weblogRecentPosts()%>

Creates an empty placeholder (?)

Nothing

<%radio.macros.cloudLinks()%>

Renders plain text: 'cloud links'.

Plain text

<%radio.macros.statusCenter()%>

Renders plain text: 'status center'.

Plain text

<%radio.macros.supportCenter()%>

Renders plain text: 'support center'.

Plain text

<%radio.weblog.getUrl()%>

Returns an empty string (?)

Plain text

<%radio.weblog.drawCalendar()%>

Renders the WeblogCalendar control

HTML

DasBlog Macros

<%macroname%>

Description

Output

<%newtelligence.drawCategories()%>

Renders the hyperlinks for all category pages available in the weblog

HTML

<%newtelligence.drawSubCategories()%>

Currently not used

Nothing

<%newtelligence.adminBar()%>

Renders the administrator bar, if logged in

HTML

<%newtelligence.loginBox()%>

Renders the login box, if not logged in

HTML

<%newtelligence.drawArchiveMonths()%>

Renders Category Months                                                                    

HTML