Find a post...

Rapid Module Development

Over the last months I developed a lot of DNN modules and in this blog I will show you how I do that. I’ll show you some of my tools I’m using and what helps me to do my work in a timely manner.

Database Design with XCase

Every new project starts for me by designing the database. Which entities do I need, how are there relations ? This task is assisted by a tool named XCase written by a guy from Isreal named Elie Muyal. XCase let you visually create your entities, views and relations and generates the needed SQL code to modify the database. Adding a field or constraint and applying the change to the database is easy going. If the module is ready for shipment, Xcase generates the whole needed SQL script for me. Code generation could be customized and I tweaked it for the generation of {databaseOwner} and {objectQualifier} placeholders (in 95% of cases. Some small editing after generation is needed). I’m working since over 10 years with XCase now and I think it is worth its money. If you are interested in it please let me know, I can provide some discount to the original price on !


Collecting ideas and tasks with Trello

A very important tool for me is Trello which is a free card board system. For every project I have my own board where in make notes, collect ideas or eventually communicate with the customer who has his own Trello account sharing the board with me.


Module Setup


The next step for me is the generation of the module. Here I use a template that is created by myself. If you want to use it for yourself you need to change my default namespace and some other information but feel free to use it by yourself: Download template

Beside all needed references, the module template generates the following parts:

    1.) The controller class ready to use all the DAL2 stuff.

    2.) The Installation subdirectory. Contains all to create installation + sourcecode packages (see for further information, made by Ernst Peter Tamminga and myself).  Can handle multiple packages & multiple modules. My XCase generated SQL code goes here

    3.) Original PetaPoco containes these .tt-Files to generate POCOs from the entities in the database. I tweaked this code a little bit to work inside a DNN module

    4.) Everything needed to expose your methods as webapi methods is in the services subdir

    DAL 2 methods

    Writing all this data access stuff is a really annoying task because you have to write the same thing over and over again. Because I’m al lazy bone I sat down and wrote a little tool that generates all I need for a given entity of my database: The “CRUD Generator” :


    Now I can select my database and the table I want CRUD methods for and hit the “GO” button and the rest is copy and paste. But the CRUD generator does something more. Often I need a standard form to edit some table data. Selecting a record from a grid, clicking on the row to edit this line and the edit form is also something that is manually done a time consuming task. Which fields do I need to show ? What are the datatypes? Which control for this field? The CRUD generator does the main work for me and I only have to do some sorting of fields or tweaking special cases. Even the Resource file for all the labels + header text is generated.


    If you want to use the CRUD generator for yourself, here is the project. Feel free to use for yourself. But if you add interesting generation methods please let me know! Download CRUD-Generator

    Re-Using my own controls

    For the most common use cases I have build a set of controls. So I don’t have to write the same functionality over and over again. Instead I insert the needed control and a few lines in code to integrate them and thats it! Explaining these in detail goes among the borders of this blog post but will be part of another blog post later:


    <bb:TabSelectControl ID="urlLigaModulePage" runat="server" Width="200" />

    This control is needed to select a page, e.g. if you need to select a target page when clicking on an item in the module



    <bb:SelectFolderControl runat="server" ID="cboProductGroupImageDir" Permission="admin"/>

    Selecting a folder e.g. as “Save folder” for product images. Possibility to add a new folder if not existing.



    <bb:TemplateControl ID="tplTemplate" runat="server" Key="Product" ViewMode="View" EditorControl="Texteditor"/>

    This control allows me to select or create tokenreplace templates which are implemented in nearly all my modules and allowes the user to select and define templates on host / portal / language level (like resource files). A thumbnail of the template is always generated to allow the user to identify the template easily.



    <bb:LanguageEditor ID="lngProducts" runat="server" InternalType="Bitboxx.DNNModules.BBStore.ProductLangInfo"/>

    All my modules are multilanguage enabled. Editing the text of different languages (eg. productdetails in english, german if those two languages are enabled in the portal) is easy now because automatically handled by the LanguageEditorControl.

    3918 - Kopie

    There are some other controls I frequently use, like the GMap-Control, the ItemImagesControl, the ImageScrollerControl and more!

    GLocation_GMap GLocationDetail_Edit


    If an algorithm is more complicated or I need some documentation for my customer, the PAP-Designer (Flow Charts) is a very useful tool. Unfortunately it is only availiable in German language, but it is free for download and easy to use. It helps a lot in visualization and engineering your code.



    Very helpful when working with other API’s (like e.g. the Twitter API) is the JSON Viewer. This tool is also free and helps a lot understanding foreign json data


    Over the time, I have collecting this toolset and tried to bring the coding effort to some point of perfection. There is still something to do (like always), but in opposite to my module developer beginner times it allows me to write custom build modules in really short time.

    I hope some of the hints were useful to you and perhaps you have some additions or good ideas to win some hours of lifetime? Let me know!

    Crossposted from my personal blog on

    I'm developer. Born in 1965, grown up in a small village near Hamburg. Studied IT in Hamburg and moved to Hanover in the late 90's. Married 24 years now and having 2 childs. After developing projects several years in desktop and web applications in Visual Foxpro I changed in 2007 to dotnet / C# / ASP.NET & DotNetNuke. Since then I'm addicted to DNN and made it my main hobby and profession. My latest hobbyhorse is doing DNN with client site programming
    Tony Henrich
    Tony Henrich  Thanks for posting this. I went through several pumps to install the template. First I needed to install it. When I ran it it didn't find some msbuild component because I was using a newer version of VS (2013) so I had to edit the csproj file and create a new zip and reinstall. Then I didn't have the MSBuild Community Tasks msi installed so I had to find it on the web and install it. yes I never used it before. Then there was another dependency MSBuildDNNtcTasks and I had to search and install it. I spent a lot of time just trying to run it from the point of of downloading it.
    · reply · 0 0 0
    Torsten Weggen
    Torsten Weggen  Hi Tony, sorry for your troubles. I inserted a link to the page where all this stuff is explained - and thought this was enough. Perhaps this link helps too: It references another template but setup action is the same
    · reply · 0 0 0
    Henner Ungethüm
    Henner Ungethüm  Hi Torsten, thanks for this very interesting post. Reading this, I remember talking about Trello with you and Stefan in Berlin. I will try it out soon. May be, we can talk about this during the flight to italy. best regards
    · reply · 0 0 0
    David Poindexter
    David Poindexter  Thanks for the article! There are some really helpful tips and tools here. Much appreciated.
    · reply · 0 0 0
      Good night, I'm testing the LanguageEditorControl Dnn module with version 7.3. When changing language tab rises an error. The problem is that when the server returns the ViewState is null. Have you ever had this problem? Do you know the solution? Thank you very much in advance. Best regards, Francisco.
    · reply · 0 0 0
    Peter Donker
    Peter Donker  Great stuff, Torsten. Very inspiring.
    · reply · 1 0 0
    Torsten Weggen
    Torsten Weggen  Thank you Peter!
    · reply · 0 0 0
    Declan Ward
      Nice article Torsten. It is always good to see how others approach development problems.
    · reply · 0 0 0
    David Poindexter
    David Poindexter  @Torsten - I am attempting to utilize your CRUD generator and will not connect to my database. Following is the exception I'm seeing. Any ideas? Does it matter that my database is SQL Server 2012? ************** Exception Text ************** System.NullReferenceException: Object reference not set to an instance of an object. at CRUDGenerator.frmConnect.cmdOK_Click(Object sender, EventArgs e) in c:\Sourcen_tfs\CRUDGenerator\frmConnect.cs:line 80 at System.Windows.Forms.Control.OnClick(EventArgs e) at System.Windows.Forms.Button.OnClick(EventArgs e) at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ButtonBase.WndProc(Message& m) at System.Windows.Forms.Button.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    · reply · 0 0 0

    Hosting liberally provided by

    Geoff Barlow 148 1
    Philipp Becker 4816 7
    DNN-Connect 424 6
    Peter Donker 3693 23
    Martijn Goedings 5 1
    Ionut Grecu 52 1
    Christopher Hammond 518 2
    Olivier Jooris 279 1
    Daniel Mettler 10201 87
    Jos Richters 64 1
    James Rosewell 142 2
    Will Strohl 1197 26
    Ernst Peter Tamminga 225 3
    Barry Waluszko 221 1
    Gifford Watkins 699 9
    Torsten Weggen 920 2