03 September 2008

Writing DNN custom modules

This is the last of three blog entries that make up a full introduction to DotNetNuke (DNN) from a developer's point of view. This time I cover Writing Custom Modules to add your own functionality to a DNN web site. Previously I gave an Introduction to DNN and showed how to Write a simple DNN Skin. A concise version of the complete article first appeared on 1 July 2008 in UK programming magazine VSJ.

The phdcc.CodeModule module described in this article can be downloaded from here.

DNN5 has a new extension/package structure for custom modules and skins - however 'legacy' DNN3 and DNN4 module zips will install in DNN 5.


Custom DNN modules can be as complex as you want. I want to get started by analysing our freeware phdcc.CodeModule module which is available at dnn.phdcc.com and contains the full source. This module makes it easier to add your own functionality without having to write a whole new module. Your code has access to the database and the ASP.NET and DNN APIs.

phdcc.CodeModule simply renders your own user control. Once the module is installed, write your own code, eg in file intro.ascx. Upload the file to the DesktopModules/phdcc.CodeModule/ directory. Add an instance of the phdcc.CodeModule module to the desired DNN page and configure it to use intro.ascx. intro.ascx can contain normal HTML, ASP.NET code and DNN calls - phdcc.CodeModule will display this whenever requested.

phdcc.CodeModule's initial display:

Enter your control filename in the Settings:
Suppose intro.ascx contains this HTML and code to say hello to the current user:
<%@ Control Language="VB" ClassName="intro" %>
<%@ Import Namespace="DotNetNuke.Entities.Users" %>
Hello <% =UserController.GetCurrentUserInfo.Username%>

Then this is the output, within the SimpleContainer that we made earlier:
As stated earlier, you can switch off the container header so it simply says "Hello host". The code simply says "Hello" if no user is logged in.

Development environment

To develop for DNN, download the latest Starter kit vsi file for Visual Web Developer Express or Visual Studio 2005. Double click on this and the Visual Studio Content Installer creates a few DNN-related templates. To create a whole new DNN site, select [File][New][Web site...], "Visual Basic" and the "DotNetNuke Web Application Framework" template. After the site has been created, an instructions page is shown. You can simply compile and run if you have SQL Server 2005 Express installed. But wait...

To use the full version of SQL Server, create an empty new database, typically with a SQL Server owner login, and put the connection string in Web.Config in two places as instructed. I also set the only instance of "objectQualifier" to eg "DNN_" so that all DNN database tables etc have this prefix. I also usually increase authentication+forms-timeout from 60 (seconds) to let users stay logged in for longer, also setting slidingExpiration to "true". The last task that I might do before running is to convert from Visual Studio's built-in web server to use the local IIS - using an IIS virtual directory seems to work OK. This lets me test how the site looks in FireFox etc.

I then compile and run. With all the above already set up, you can select the "Auto" install option instead of the "Typical" wizard. If installed using "Auto", your first task will be to login as host and admin to change the passwords. Then go to [Host][Host Settings] eg to set the SMTP Server, and then set up the site/portal using [Admin][Site Settings]. Go back to Home and delete all the module instances - then off you go.

The created project has the 'code' half of DNN supplied as DLLs in the /bin/ directory. The web pages, controls, their code-behind and other resources are installed as web site source. All this lot can take a while to compile, which can be a bit frustrating when working on your own module - I did attempt once to convert DNN to a faster Web Project but I couldn't get it to work.


Use [Host][Module Definitions] then "Install New Module". Browse to find phdccCodeModule_01_00_02.zip and click "Install New Module". Check the installation log for errors then press "Return". The following files will have been installed under the existing root DesktopModules directory.
+ phdcc.CodeModule
+ App_LocalResources
+ Edit.ascx.resx
+ Settings.ascx.resx
+ View.ascx.resx
Edit.ascx, Edit.ascx.vb
Settings.ascx, Settings.ascx.vb
View.ascx, View.ascx.vb

The module zip also contains a manifest file phdcc.CodeModule.dnn that tells DNN where to install each file - in addition, it says that there are three controls: a View, Edit and Settings.

The View control displays the normal module output to users. The Settings control is at the bottom of the module settings page - visible to admin users. The Edit control is not used by phdcc.CodeModule yet but will typically be shown to admin users to set up the module content. You can have more user controls if need be.


View.ascx primarily contains the following placeholder into which your user control will be inserted. The view contains additional elements which are used to give instructions and show errors.
<asp:PlaceHolder ID="ViewControl" runat="server" />

The View.ascx.vb codebehind class is based on DotNetNuke.Entities.Modules.PortalModuleBase which is in turn derived from DotNetNuke.Framework.UserControlBase and eventually System.Web.UI.UserControl. These base classes contain many crucial DNN properties and objects, ranging from the PortalId to the current UserId. The View Page_Load uses PortalModuleBase.Settings to retrieve your control filename before adding it to the ViewControl PlaceHolder:

Dim ControlName = CStr(Settings("control"))

If you have not specified your control yet, the code shows an asp:label and a "Settings" asp:button. If this button is clicked then you are redirected to the module's Settings - the DNN NavigateURL global method is used to create the correct URL to see the Settings. In DNN parlance, each page is called a "tab" so the TabID selects the page; there may be more than one module on a page, so the correct one is selected using the ModuleId:
Response.Redirect(DotNetNuke.Common.Globals.NavigateURL(PortalSettings.ActiveTab.TabID, "Module", "moduleid", ModuleId.ToString()), False)

phdcc.CodeModule could be improved by adding an "Edit Control" option to the module menu (to let an admin user create or edit the control in a text area edit box). The existing View implements the IActionable interface to do this job. The ModuleActions get property must return a DNN ModuleActionCollection with a new Action added using localised text. DNN sets up this action so that selecting it redirects to the Edit control.


The module settings page has a common user interface at the top of the page - our content is shown lower down, as shown above. The Settings.ascx user control primarily shows a labelled text box for you to type in your control filename.
<asp:textbox id="txtControlName" cssclass="NormalTextBox" width="200" runat="server" />

The codebehind Settings class is derived from DotNetNuke.Entities.Modules.ModuleSettingsBase. The LoadSettings method fills the text box with the current setting on first entry. ModuleSettingsBase.TabModuleSettings gets the same information that is retrieved by the view using PortalModuleBase.Settings. Please see my blog on DNN module and tab-module settings for full details of the different settings available.

If Not Page.IsPostBack Then
Dim ControlName = TabModuleSettings("control")
txtControlName.Text = ControlName
End If

When the Settings page Update button is pressed, the UpdateSettings method is called to store the new control filename and refresh the DNN in-memory cache:

Dim objModules As New DotNetNuke.Entities.Modules.ModuleController
objModules.UpdateTabModuleSetting(TabModuleId, "control", txtControlName.Text)


The only remaining element of phdcc.CodeModule is the localisation files in the App_LocalResources directory. In this module, only the Settings.ascx.resx file is used. In Settings.ascx, the dnn:label control is used for the filename prompt:
<dnn:label id="lblControlName" runat="server" controlname="txtControlName" suffix=":">

This shows a help question mark followed by a label, with the actual text picked up from the resource file "lblControlName.Text" and "lblControlName.Help" strings. Within DNN you can edit these strings or create a new resource file for a different locale. DNN looks at the logged-in user's UserInfo.Profile.PreferredLocale property to determine which resource to use.

Tip 1

We recently wrote a simple phdcc.CodeModule user control that would not save its ViewState, eg:
<% If Not IsPostBack Then lblGiven.Text = "init" %>
<asp:Label ID="lblGiven" runat="server" />
If a button was pressed then lblGiven would not contain "init" on postback. The problem turned out to be that embedded code blocks <% %> are run in the PreRender phase, after the ViewState had been saved. The solution was to set the label in the Page_Load method.

Tip 2

In a phdcc.CodeModule control, it is useful to have access to the current DNN PortalModuleBase instance. The following code achieves this:

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim ViewControl As Control = Me.TemplateControl.Parent
Dim View As Control = ViewControl.Parent
If TypeOf (View) Is PortalModuleBase Then
Dim pmb As PortalModuleBase = CType(View, PortalModuleBase)
Dim ps As PortalSettings = pmb.PortalSettings
End If
End Sub

Tip 3

Sometimes it is not clear whether to use DNN or ASP.NET functions. If in doubt, rummage around in the DNN source to see how they do it. For example, to determine if the user is logged in, I use ASP.NET Request.IsAuthenticated. In another case, I wanted to get someone's password given their UserId. After getting the Username using DNN APIs, I used the ASP.NET GetUser method to return a MembershipUser that is used to get the password.

UserInfo ui = UserController.GetUser( PortalId, UserId, true);
MembershipUser user = Membership.GetUser(ui.Username);
string pwd = user.GetPassword();

Database Modules

More substantial modules will typically want to store their own information in the database. The following example module shows a list of Text/HTML items (in an asp:datalist data bound list). There are admin options to Add Content items and define a template in Settings.

In Visual Studio, right click on the project name and select [Add New Item...], choose "DotNetNuke Dynamic Module" for VB or C#, enter a name such as "TestMod", then press OK. You will have to do two directory renames as per the shown instructions. If you chose C# then you will have to add to the main Web.Config codeSubDirectories element.

In [Host][Module Definitions] click on "Import Module Definition". In the Manifest list, select "TestMod.dnn" and click "Import Manifest". The TestMod module can now be put on a page but will show a ModuleLoadException until the database has been set up.

The new module will have code classes created in the \App_Code\TestMod\ directory. File TestModController.vb represents your business logic and provides access to the database from your user controls. The Text/HTML items are each represented by a TestModInfo.vb object, each of which is stored as a row in a database table. File DataProvider.vb describes a generic database interface, while SqlDataProvider.vb proves an actual implementation of this interface.


The generated TestModController class has a GetTestMods method that returns a list of TestModInfo objects. It finds the current data provider and calls its GetTestMods method, passing the current module instance id ModuleId. The data provider GetTestMods returns an IDataReader. The DNN Custom Business Object utility class CBO method FillCollection is used to create the TestModInfo list - it sees what fields have been returned in each IDataReader record and fills the corresponding properties in each TestModInfo instance automatically - quite a mouthful but certainly a useful tool. There is a similar method CBO.FillObject to fill just one object.

Public Function GetTestMods(ByVal ModuleId As Integer) As List(Of TestModInfo)
Return CBO.FillCollection(Of TestModInfo)(DataProvider.Instance().GetTestMods(ModuleId))
End Function

The controller also contains further methods GetTestMod, AddTestMod and UpdateTestMod which work with a single TestModInfo object, using matching functionality in the data provider.

The controller class also implements the DNN ISearchable and IPortable interfaces, to support searching and import/export of the module content into XML.

Database SQL

When a module is installed, DNN looks at the manifest version number and compares it to certain filenames in the zip. File 01.00.00.SqlDataProvider contains the SQL instructions to create any tables, stored procedures etc required to bring the database up to version 01.00.00. A script 01.01.03.SqlDataProvider would take the database to version 01.01.03. When installing as new, then both scripts will be run. If you are upgrading from say version 01.00.01 then only the second one is run.

Because you have created a module from a template, the database has not have been created. To set this up, you need to run the 01.00.00.SqlDataProvider script in SQL Server Management Studio, though you may want to rename some of the tables etc first. You should also first replace {databaseOwner} with "dbo." and {objectQualifier} with the "objectQualifier" that you used, ie nothing by default.

The generated TestMod SQL script creates a table called YourCompany_TestMod (for TestModInfo objects) and various stored procedures that correspond to the data provider GetTestMods, GetTestMod, AddTestMod and UpdateTestMod methods. The YourCompany_TestMod table contains a ModuleId field that corresponds to the unique module identifier with the same name in the DNN Modules table.

When you add a TestMod module instance to a page there is no event raised to let you populate the database. The View code knows its ModuleId, so it calls GetTestMods to obtain all TestModInfo objects for the current module instance. If it finds that there are no such objects, then it creates a default TestModInfo and adds it to the database.
Dim objTestMods As New TestModController
Dim colTestMods As List(Of TestModInfo)
colTestMods = objTestMods.GetTestMods(ModuleId)
If colTestMods.Count = 0 Then
Dim objTestMod As TestModInfo = New TestModInfo
colTestMods = objTestMods.GetTestMods(ModuleId)
End If

There is no event raised when a module is deleted from a page. So when is your per-module-instance data deleted? DNN has a Recycle Bin for pages and modules that have been deleted. When a module is finally deleted from this bin, the module instance row in the Modules tables is deleted - our YourCompany_TestMod table has a cascade delete relation on this row, thereby deleting the right rows in our table. Unfortunately, there is no programmer event that corresponds to this final delete.

Finally, the generated module also contains another SQL script file Uninstall.SqlDataProvider that is run if the module is uninstalled from the system in [Host][Module Definitions..]. The SQL in there naturally deletes all tables etc that were created in the database.

I will leave an exploration of the rest of the code as an exercise for you dear reader. There are no imposed limitations on how you use the database, so you can create whatever tables you want. Your code has access to all DNN and ASP.NET data, not to mention bog standard Session variables etc, so the world is your oyster.

And more...
If you develop a module and want to keep your source private then follow the documentation instructions. Another option is to make the App_Code section of your module into a separate DLL class library project (while keeping the web site controls with full source). Include the project DLL in your module's ZIP so that it installs on other systems in the /bin/ directory.

Module code also has full access to the web site file system. It is common to store files relating to a site in the relevant portal directory, eg /Portals/0/. It would be sensible if each module worked within a suitably named sub-directory.

There is stack of DNN functionality and namespaces which I haven't touched upon. However I hope that I have given you a flavour of what DNN is and how to extend it with your code – in a simple way using phdcc.CodeModule, or by writing a full-blown custom module.

Writing DNN Skins

This is the second of three blog entries that make up a full introduction to DotNetNuke (DNN) from a developer's point of view. This time I cover writing a skin and a container to change the appearance of a DNN web site. Last time, I gave an Introduction to DNN - next will be Writing Custom Modules. A concise version of the complete article first appeared on 1 July 2008 in UK programming magazine VSJ.

The simple skin and container used in this blog can be downloaded here.

DNN5 has a new extension/package structure for custom modules and skins - however 'legacy' DNN3 and DNN4 skins will install in DNN 5 - select Skin as the legacy skin type.


This time, I look at how to create a skin that defines the appearance of a site and write custom modules that provide content on a page. The figure below shows a typical DNN layout: the skin defines the page layout, including one or more panes. An admin user can place one or more modules in a pane, with each module wrapped in a container.


A skin package defines how DNN presents its content, ie the overall HTML of the page, all the CSS styles, and various parameters for the breadcrumb and menu screen elements. A container package defines how each module container looks in a similar way. If you install a ‘skin’ it typically contains both skin and container packages. An individual skin package may contain several different layouts, eg fixed width and full-screen instances.

DNN seems to have a preference for fixed-width skins and fixed size fonts. I presume that this is an attempt to achieve a perfect appearance on the page. However, it is best to make use of all the screen width and make the page work well as font sizes are changed by the user. Fixed sizes may achieve the desired effect in Internet Explorer, as long as the user doesn't Zoom. However in FireFox, changing the text size also changes fixed point sizes in the same way as IE Zoom. For more details, see my previous blog entries: DotNetNuke Internet Explorer fixed size fonts and DotNetNuke Internet Explorer font scaling.

These CSS files are used by DNN, in this order, with the Portal CSS included last so its definitions take precedence over any earlier ones.

  1. Portal default CSS (in /portals/_default/default.css)
  2. Current skin CSS
  3. Current container CSS
  4. Portal CSS (eg in /Portals/0/portal.css)
The ‘portal default CSS’ defines styles for most generic HTML elements (H1, TD etc) though strangely not P – using fixed-point font sizes in most cases; it also defines CSS classes for all the standard DNN elements.

The ‘portal CSS file’ contains blank elements to let you know what the standard definitions are – this file can be updated in the [Admin][Site Settings] menu.

Skin and container development

If you have installed the DNN Starter Kit into Visual Studio, you can create a skin and container using [File][New][File] - "DotNetNuke Skin" template. However, to illustrate a basic skin and container, I have developed a simple example which you can download. These are the files that I used to create the example:



The files in the skins directory are zipped up to make skins.zip, ditto for containers. Then these two are zipped together to make simple.zip that contains both the skin and container packages.

Each site has one current skin and one current container. When you install a skin, the files are unzipped and a skin user control is created - when chosen as the current skin, this user control is inserted into the main page output. A skin has pane elements - DNN inserts the right modules into each pane, each wrapped in a container. The current container is also a user control with a ContentPane that contains the actual module output.

If you install a skin from the [Admin] menu, then the packages will be installed in directory \portals\0\skins\simple\ and \portals\0\containers\simple\. The file simpleskin.htm contains various template tokens, such as [LOGO], that are expanded on installation into file simpleskin.ascx – the ASP.NET user control that is included in the DNN output. If you update the in-situ simpleskin.htm, then click on "Parse Skin Package" in [Admin][Skins] to recreate simpleskin.ascx to see your changes. (Don't include any ascx files in your final skin/container zip package.)

The SimpleSkin.htm skin template defines the basic HTML of the main DNN output, typically using tables for layout. Various tokens appear in square brackets, replaced by DNN at install/runtime. The main output panes are defined in this example as table cells with the predefined correct id names. If you are better at XHTML than I am, change this template to avoid tables.

<table class="ss_header" width="100%">

<table class="ss_menurow" width="100%">
<td class="ss_menu">[SOLPARTMENU]</td>
<td class="ss_menu_user">[USER] [LOGIN]</td>

<table class="ss_main" width="100%">
<td class="ss_crumb">[BREADCRUMB]</td>
<td class="ss_date">[CURRENTDATE]</td>

<table class="ss_content" width="100%">
<td id="LeftPane" runat="server" />
<td id="ContentPane" runat="server" />

The skin.css file contains all the definitions you want (not forgetting to override the DNN defaults if required), eg simply:
The skin.xml file defines parameters that are used by DNN. The first one shown tells DNN to use the » character as a separator between the breadcrumb page names. The second set of parameters makes the menu horizontal, etc.
<Value><![CDATA[ » ]]></Value>
The SkinContainer.htm container template looks similar to the skin template, with tokens replaced when the container is rendered. The main module output is in the ContentPane. The container.css file contains definitions for the CSS classes used in the container template. Similarly, container.xml defines various container-level parameters.
<table width="100%" class="c_all">

<td class="c_header" colspan="2">
<table width="100%">
<td style="width:100%;" class="c_header_title">[TITLE]</td>

<td class="c_content" id="ContentPane" runat="server" colspan="2" />


There are many more tokens and options that you can use. Ideally you should also include a preview of your skin and container by including in each zip a JPG with same name as your template file.

02 September 2008

DNN Introduction

This is the first of three blog entries that make up a full introduction to DotNetNuke (DNN) from a developer's point of view, with the following pieces covering Skins and then Writing Custom Modules. A concise version of the complete article first appeared on 1 July 2008 in UK programming magazine VSJ.


DotNetNuke is not a good name for software, but don't let that put you off. Call it DNN, and think of it as a programmable content management system that's open source and runs on ASP.NET 2+ servers. Ie it lets you create and maintain a web site easily.

Although you may be familiar with the basic idea of a CMS, this first article will introduce you to DNN features, terminology and usage before getting stuck into new skins and programmable modules next time.

If you want to use Microsoft technology, DNN lets you deliver a working site with relative ease - it can be handed over to a non-technical site administrator who can do all the regular site updating, eg adding pages, editing text, making announcements etc. Web space at our preferred host Crystaltech starts at US$35 per year for a small site. At that price everyone can have a web site: I set up a badminton club site for a friend and he's now running it with no intervention from me.

There are some problems running DNN in Windows Server 2008 in Medium Trust.

When trying to decide between various systems, you will want to know:
  • Is it reliable? We are now running a number of DNN sites with many thousands of users and they seem solid.
  • Is it maintained? There are regular fixes and improvements for DNN, eg it now uses AJAX in places.
  • Does it have the features you want? DNN handles users well, has a good framework to add functionality, and there are lots of add-on modules available.
  • Can I learn it easily? It will always take a while to get in-depth understanding of a new system. With DNN you can set up a basic site on day one, but it might take months to get fully to grips with writing modules. DNN was a bit easier for us as we are used to ASP, ASP.NET and Microsoft hosting. To handle development, staging, production and backup servers, make sure you are able to copy all content and users to another site.
DNN is not perfect. The Text/HTML Editor is not good enough for serious use. Cute Editor and other plug-in editors may be better. They all suffer from not being clever enough at handling complex reformatting - what you see is seldom what you get. Note that users must have cookies enabled to be able to register and login at DNN.


Supplied Modules
Account login
Banner adverts
Feed explorer
Google Adsense
Search Input
Search Results
User Account

DNN serves most content using modules, eg a text module comes as standard, along with the others listed below. There's a thriving third-party market for modules, some for free but largely at low cost - usually listed and bought at SnowCovered.com. At phdcc, it is crucial that we can develop custom modules to provide the unique functionality that some web sites need. We have also released some freeware and commercial modules. Custom modules are written as a set of standard ASP.NET user controls, using extra DNN APIs as needed, with the end result bundled into a ZIP for distribution. Custom modules are usually written in Visual Basic like DNN itself, but C# is possible.

If you like to hedge your bets, code in a DNN module could be written to run on a plain ASP.NET system. Or perhaps do it the other way round: for example, the YetAnotherForum.net open source software will run as a standalone web app, but they have added some code and packaged it as a DNN module.

DNN's presentation is determined by skins which define the appearance of the whole site and each module container. Various skins are provided for free, while others are available for purchase at SnowCovered - you can write your own relatively easily. DNN skins tend to use fixed point size CSS definitions so it doesn't scale in Internet Explorer as you change text size - more on this next time and in these previous blog entries: DotNetNuke Internet Explorer fixed size fonts and DotNetNuke Internet Explorer font scaling.


It is worth saying right now that DNN is almost entirely database and ASP.NET driven. All DNN output is generated from a single ASP.NET page that dynamically loads whatever content needs to be shown, using many levels of ASP.NET .ascx user controls. So the site will not be as fast as from static content, but this is an acceptable price.

Although all DNN requests are run through the root default.aspx, it has a friendly-URL HttpModule that shows a unique URL with pertinent text for each page. Note that the standard menu system is implemented in JavaScript so it does not provide hard links. So make sure that you provide hard links somewhere so that search engines can trundle through your site.

The database can be in SQL Server Express or the full SQL Server. Strictly speaking, the code has been written in a generic way using a provider pattern that allows other database types to be used, but in practice I have only ever seen the Microsoft databases supported.

Doing backups in DNN can be complicated. There are facilities to export and import your site as a template in XML - but I am not confident that this gets a whole site design – and does not store the users. Doing a database backup will probably get most data. However to be certain, you will also need to backup the entire file system as some modules store their data in files.

DNN uses standard ASP.NET forms authentication to handle its users (recently, Windows LiveID as well). After a fresh install, the 'host' account lets you configure the entire site, while the 'admin' account has a reduced set of permissions that is suitable to give to a non-technical site administrator. One "host" DNN instance can have one or more "portals" (one for each site/domain name), so there is one admin account for each portal. We wouldn't recommend having more than one portal - it's not worth the fuss when web space is so cheap. Things go wrong if you attempt to run DNN from a sub-directory, so always make sure that it runs at the root of a domain name - one approach is to set up a sub-domain such as dnn.phdcc.com. On our shared host, we did this by adding an extra DNS Host Record (A) for "dnn" that points to the IP address of a separate hosted web space.

DNN has built-in support for internationalisation, so you can download language packs for DNN itself so that all DNN management will be done in your preferred language, including email templates. Well written modules will use the same techniques but will usually only have English text provided. As I understand it, there is no direct support for showing a particular module (eg French intro text) if the user's browser setting or preferred locale is French.

It is helpful to understand a little of the DNN directory structure. As well as /bin/ and /App_Code/ directories, each supported site has a directory, so the first site portal (with a programmer PortalID of zero) has its file store at /Portals/0/. [Admin][File Manager] opens at this directory. If, with your super powers, you FTP a new file into this directory, then some of the DNN code may not initially see it. There is an option in File Manager to synchronize with the actual files present - don't forget to tick the Recursive box to sync all the sub-directories. You can also synchronise programmatically using the DNN FileSystemUtils.Synchronize method. Finally, the directory /Portals/_default/ contains definitions that are available for all portal sites, eg skins and containers.

DNN has a basic search built in, using the search information provided by each module. However the search will not index file documents such as PDFs.


You can get the latest version of DNN, now 4.8.4, from http://www.dotnetnuke.com/ once you have registered. The "Install" package is for production use. Get the "Starter Kit" and "Documentation" packages if you are doing module development - there is a full "Source" release as well. For installation, your primary requirement is a connection string for a database, and you will need to make sure that DNN ASP.NET has full read, write and delete access to the file system. An installation wizard will take you through these options and set up the host and admin accounts. There's also an "Upgrade" package - but make sure that you have done a full backup before using this. When upgrading, you must carefully merge the existing DNN Web.Config file with the new one supplied in Release.Config, in particular keeping the existing ‘machineKey’ element, ‘SiteSqlServer’ connection strings and ‘objectQualifier’ value.

I have one of the standard books, 'Professional DotNetNuke ASP.NET Portals' for old DNN 3. This aims to cover setting up and administering a site, as well as writing skins and modules. I didn't find it very helpful and it is hopeless as a programmer reference as the index does not list the things I looked for. The "Documentation" download has various useful documents, but I seem to have missed a trick somewhere as I haven't found or generated a full DNN API help file. That said, it is great having the full DNN source available so you can look up methods and see how they work.

I haven't ever wanted to alter the main DNN code which is just as well if you want to track upgrades. There's a large developer community at work in the DNN help forums. I made one paltry contribution to sorting out one bug. I have however updated the wiki module to send me an email whenever a wiki entry is updated; I was pleased to be able to compile the wiki project, understand the code, and make my changes with relative ease.

Using DNN

Here's a simple overview of how to use DNN, without endless screen shots. A DNN page is typically laid out as shown below. The current skin defines various panes on the screen where you can place one or more modules. After you have added a module, it appears in a container, a rectangle with a title bar in a style determined by the container skin. DNN is generally very configurable, eg you can switch off the title bar for each container.
When logged in as 'host' or 'admin' you get a Control Panel at the top of the page as shown below - most functions are pretty obvious.
DNN supports various roles that determine which users can do what. Roles can be assigned to the view and edit visibility permissions for each page and module; the File Manager can set up view and write permissions for portal directories. Users who have the "Administrators" role can access everything. The other standard roles are 'All Users', 'Registered Users', 'Subscribers' and 'Unauthenticated Users'. You can set up new roles, for example, a fee-paying role that might be used to allow access to privileged content for say 3 months. DNN has built in support for several payment providers, including PayPal.

Below is an amalgamated screen shot that shows the menu options available to admin and all-powerful host users. Below is a typical Text/HTML module shown with its container title - and a module menu visible to admin users with edit permissions. When you write a module, you can add functionality to the module Settings page, and also add items to the menu itself - in the same way as "Edit Text" as shown.

DNN maintains a profile for each registered user, ie a set of properties of various types. As well as the basic profile properties of Username, FirstName, LastName, DisplayName and Email, DNN has many default properties for your Address, Contact Info, Biography, Time Zone and Preferred Locale. You can delete or add properties and mark individual properties as being required if desired. At program level, each user has a unique UserID; if a user joins with Username 'chris' then unregisters and subsequently someone else joins with the same Username 'chris', then these two users will have different UserIDs.
DNN has a rather fixed user interface for registration and setting your profile. For this reason, our phdcc.Data module has a form generator that lets you build custom alternatives to these facilities.

In conclusion, DNN provides a useful set of CMS/multi-user facilities for Microsoft-technology web sites. Any limitations can often be overcome using one of the many modules available. Everything DNN outputs is code and database driven which makes it harder to backup and understand what is going on. Next time, we'll look in detail at how to set up new skins and program modules.