Custom Module Development in DotNetNuke
Inleiding
Zoals de oplettende bezoeker misschien gemerkt heeft is SDN sinds enkele maanden overgestapt op een nieuwe website. Er is gekozen voor DotNetNuke, een open source content management systeem dat op verzoek van Microsoft ontwikkeld is door Perpetual Motion.
Dit artikel gaat in op het ontwikkelen van zogenaamde ‘Custom Modules’ die dynamisch toegevoegd kunnen worden aan DotNetNuke. Belangrijk is wel om te weten dat dit artikel gebaseerd is op DotNetNuke versie 3.x, die momenteel alleen nog als beta versie te downloaden is. De module definitie in deze versie verschilt namelijk van die in versie 2.x.
IBuySpy
IBuySpy is het eerste (open source) CMS initiatief van Microsoft, gebaseerd op VB.NET. Dit systeem werd ontwikkeld om de adoptie van ASP.NET te versnellen en te vereenvoudigen. Het gaf een aardige indruk hoe je met ASP.NET een website (en zelfs een webshop) zou kunnen ontwikkelen. IBuySpy had echter een behoorlijk procedureel georiënteerde opzet en de verschillende technische layers van de applicatie waren behoorlijk met elkaar verweven. IBuySpy had daarnaast nog verschillende andere nadelen waaronder de onmogelijkheid om zelf ontwikkelde modules te uploaden in de kernel van IBuySpy. Dat had als gevolg dat uitbreidingen in dat systeem dus in de source van IBuySpy zelf ontwikkeld moesten worden. Niet echt handig op moment dat er een update van IBuySpy zou komen. Alle aanpassingen moeten dan bepaald worden en uit de oude source worden overgezet in de nieuwe versie.
IBuySpy had echter een behoorlijk procedureel georiënteerde opzet en de verschillende technische layers van de applicatie waren behoorlijk met elkaar verweven
Nog een belangrijke beperking van IBuySpy: de database aansturing vond direct vanuit de applicatie plaats. Er was een keuze gemaakt voor SQL Server. Mocht je om moverende redenen liever een andere database willen gaan gebruiken, dan was er een behoorlijk aanpassing van de code nodig.
DotNetNuke
DotNetNuke is een/de opvolger van IBuySpy. Geheel object georiënteerd en met verschillende layers leent het systeem zich alleen om die reden al veel meer voor aanpassingen van delen van de applicatie. DotNetNuke heeft echter een nog veel mooiere feature: het uploaden van in eigen beheer ontwikkelde uitbreidingen (modules). Er bestaat de mogelijkheid om een ZIP bestand samen te stellen met daarin een installatiescript, de databasescriptcode, de ontwikkelde assemblies, ascx/aspx bestanden en natuurlijk de bijbehorende graphics. Als dit bestand geupload is, zal DotNetNuke het uitpakken en verwerken tot een direct bruikbare module.
Alle in DotNetNuke geregistreerde modules worden in een speciale balk bovenin het scherm getoond en vanuit die balk kan een module geselecteerd worden en toegevoegd worden aan de huidige pagina.

Figuur 1: Werkbalk in DotNetNuke voor toevoegen van module aan website
SQL Server en Virtual PC
Omdat ik bij het schrijven van dit artikel net een nieuwe laptop in gebruik genomen heb, had ik niet direct de beschikking over SQL Server. Om DotNetNuke te kunnen gebruiken kan er standaard gekozen worden tussen Access en SQL Server als dataprovider. Om verschillende redenen ligt mijn voorkeur bij SQL Server. Het is me echter opgevallen dat installatie van SQL Server op een laptop deze enorm vertraagt, zelfs als SQL Server uitgeschakeld is. Microsoft promoot al langere tijd het gebruik van Virtual PC. Dit was dan ook een uitstekend moment om een poging te doen om SQL Server op een Virtual PC image te installeren.
Bug (hidden feature?) bij het gebruik van SQL Server op Virtual PC
De installatie verliep redelijk probleemloos, maar het benaderen van SQL server op de Virtual PC vanaf mijn laptop gaf behoorlijk wat problemen. Virtual PC kreeg om te beginnen al geen IP adres van mijn DHCP server. Klik om dat te verhelpen met een rechter muis op het netwerk icoon onder in de werkbalk van het Virtual PC scherm en kies voor Networking Settings. Kies vervolgens bij Adapter 1 de netwerkkaart die je ook in je eigen PC gebruikt om op het netwerk te komen. In mijn geval was dat de Broadcom NetXtreme kaart. Vanaf dat moment had mijn Virtual PC ook een eigen uniek IP adres. Na deze handeling bleek SQL Server echter nog steeds niet te benaderen te zijn. Dit blijkt een bug (hidden feature?) bij het gebruik van SQL Server op Virtual PC. Er moet namelijk een trusted verbinding bestaan tussen de Virtual PC en het host systeem waar Virtual PC op draait. Het doet er niet toe dat je SQL Server wilt benaderen via een non-Windows SQL Server login! Om dit op te lossen heb ik een share aangemaakt op Virtual PC en daar vanuit mijn laptop verbinding mee gemaakt. Vanaf dat moment bleek SQL Server ook te benaderen.

Figuur 2: Instellen netwerk adapter 1 in Virtual PC
Installatie van DotNetNuke
Na het downloaden van DotNetNuke via www.dotnetnuke.com en het uitpakken van het ZIP-bestand onder de InetPub\wwwRoot map kan DotNetNuke gestart worden via de default.aspx pagina. Let op: DotNetNuke versie 3.0.8 (waarmee dit artikel op geschreven is) kan absoluut niet tegen een zogenaamde ‘virtuele directory verwijzing’ waarbij je DotNetNuke bijvoorbeeld in een map als C:\DotNetNuke installeert!
Bij het starten van DotNetNuke zal het systeem zelf diverse zaken controleren en zonodig waarschuwingen geven van aanpassingen die in het hostsysteem uitgevoerd moeten worden. Over het algemeen moeten er wat rechten aangepast worden binnen Internet Information Services. De enige melding die wat minder duidelijk is, is de melding dat DotNetNuke geen verbinding kan krijgen met de database.
Maak met de SQL Enterprise Manager een database aan voor DotNetNuke en noem deze DotNetNuke. Open nu met een editor het bestand Web.Config en zoek daarin bij naar de SiteSqlServer key. Vermeld daar de naam van de SQL Server instance en de database login credentials.
key="SiteSqlServer"
value="Server=(local);Database=DotNetNuke;_
uid=;pwd=;" />
key="SiteSqlServer2"
value="Server= _
NEDFOX-VTYK7IB6;Database=DotNetNuke;_
Integrated Security=False;Uid=sa;Pwd=test" />
Als alternatief heb ik een SiteSqlServer2 key vermeld waarbij Integrated Security uit staat en er expliciet ingelogd wordt op de SQL Server met het SA account. Het hangt maar net af van de instelling van de SQL Server hoe er op ingelogd moet worden. Wanneer er gebruik gemaakt wordt van Integrated Security, dan logt DotNetNuke met hetzelfde account in op SQL Server als het account waar IIS op draait.

Figuur 3: Aanpassen user account van Word Wide Web-publisher via Windows Control Panel
Dat account is aan te passen via ‘Services’ in het Windows Control Panel. Verander van de World Wide Web-Public service het account van Local System naar het te gebruiken Windows account.
Modules
Het idee achter de flexibiliteit van DotNetNuke is het gebruik van modules. Er worden er standaard een stuk of 25 meegeleverd waarmee tekst kan worden getoond, files geupload en discussies gevoerd, en diverse andere features mogelijk worden. Al deze modules worden in de werkbalk (zie figuur 1) getoond en kunnen op die manier aan elke pagina worden toegevoegd. Een standaard pagina telt 3 verschillende kolommen waar modules in geplaatst kunnen worden.
De verticale volgorde van modules binnen een kolom is uiteraard ook aanpasbaar en per module kunnen diverse eigenschappen worden ingesteld zoals de groepen van gebruikers die rechten hebben om de module content te zien en groepen van gebruikers die rechten hebben om de content van een module te wijzigen.
Elke module in DotNetNuke dient een afgeleide te zijn van de klasse PortalModuleBase. In die klasse worden verschillende zaken al voor je geregeld, waaronder de autorisatie en navigatie als gevolg van keuzes in je module. In dit artikel maken we een Customer tabel die toegevoegd wordt aan de DotNetNuke database.
Namespace DotNetNuke.Modules.DemoWebApplication
Public Class WebUserControl Inherits
DotNetNuke.Entities.Modules.PortalModuleBase
Om eigen modules te kunnen maken is het van belang om te starten met een eigen separate solution. Elke solution dient te bestaan uit een (Sql)DataProvider project en een project met de werkelijke implementatie. Er worden in beide projecten diverse references gemaakt naar de DotNetNuke kernel. Belangrijk is wel om een eigen solution een unieke namespace te geven. De standaard conventie die DotNetNuke hanteert is ‘DotNetNuke.Modules.’. In dit artikel is de namespace DotNetNuke.Modules.DemoWebApplication gekozen. Elk DataProvider project verzorgt de werkelijke implementatie van de interface tussen de applicatie en de gekozen dataprovider in de Web.Config.

Figuur 4: DemoWebApplication Solution
Let op: deactiveer bij elke DotNetNuke reference de property ‘Copy local’. Het is namelijk niet nodig om deze assemblies te kopiëren naar de nieuwe solution: de nieuwe solution wordt straks gekopieerd naar DotNetNuke, waar de DotNetNuke assemblies zich al bevinden. Bovendien zorgt het deactiveren van de Copy Local setting dat er ‘Circular References’ ontstaan: de compiler zal blijven protesteren over versieverschillen tussen de verschillende builds van de DotNetNuke assemblies.
In de bij dit artikel te downloaden voorbeeldbestanden is te zien hoe een Customers.ascx module is aangemaakt met een list-element waarin Customers getoond worden. Hiervoor wordt gebruik gemaakt van een functie GetCustomers uit de CustomerController klasse.
Dim CustomerController As New CustomersController
lstCustomers.DataSource =
CustomerController.GetCustomers()
De data die geretourneerd wordt uit GetCustomers() is niet een DataSet, zoals je misschien zou verwachten in .Net, maar een arrayList met op elke rij een Customers object. Dit is kenmerkend voor DotNetNuke: om verschillende redenen is er voor gekozen om geen gebruik te maken van DataSets. In plaats daarvan worden allerlei gegevens via objecten verstuurd die zich in arrays bevinden.
Deployment
Nu de Customer module in zijn meest eenvoudige vorm bestaat is het zaak om de gehele solution om te zetten naar een ZIP bestand die rechtstreeks ingelezen kan worden in DotNetNuke. Om dat voor elkaar te krijgen moet er nog een aantal bestanden worden toegevoegd aan de DemoWebApplication. De belangrijkste daarvan is een soort datadictionary waarin staat welke bestanden zich in de ZIP zullen bevinden en hoe die geregistreerd moeten worden in DotNetNuke. De extensie van dit scriptbestand is .dnn. Een beperkt overzicht van de inhoud van dit bestand:
NedFox – DemoWebApplication
Customers.ascx
View
Edit
Edit customer
EditCustomer.ascx
Edit
Customers.ascx
EditCustomer.ascx
DemoWebApplication.dll
DemoWebApplication.SqlDataProvider.dll
01.00.00.SqlDataProvider
Uninstall.SqlDataProvider
Belangrijk in het .DNN scriptbestand is de aanduiding van de manier waarop de controls geregistreerd moeten worden. De module Customers.Ascx wordt hier als component van het type ‘View’ geregistreerd. Dit houdt in dat wanneer deze module ergens binnen DotNetNuke geplaatst wordt, de module Customers.Ascx standaard getoond zal worden. Zodra er binnen de module een Edit commando gegenereerd wordt, dan wordt de module EditCustomer gestart. Over het edit commando verder op in dit artikel meer.
Een ander belangrijk bestand is het script dat moet zorgen voor aanmaak van de juiste tabellen en stored procedures in de database om deze applicatie goed te laten functioneren. Dit bestand bevindt zich in het (SQL)DataProvider project. Een vrij logische plek: de inhoud ervan hangt immers af van de gekozen type database. In dit geval bevindt zich in de voorbeeld applicatie een bestand 01.00.00.SqlDataProvider met daarin TSQL scriptcode. Door middel van dit bestand wordt er een tabel Customers gemaakt in de SQL Server database en een tweetal Stored Procedures, GetCustomers en GetSingleCustomer. Naast het script bestand om de juiste gegevens aan te maken bestaat ook de mogelijkheid om een UnInstall script mee te leveren. Die wordt uitgevoerd bij het verwijderen van de module uit DotNetNuke.
Nu alle bestanden bestaan, kan hiervan een ZIP bestand aangemaakt worden. Het ZIP bestand moet alle bestanden uit het hierboven genoemde script bevatten, aangevuld met de DataProvider-scripts, het .DNN-script en alle assemblies. In geval van deze DemoWebApplication zal het dus gaan om de volgende bestanden:
- Customers.ascx
- EditCustomer.ascx
- 01.00.00.SqlDataProvider
- UnInstall.SqlDataProvider
- DemoWebApplication.dnn
- DemoWebApplication.dll
- DemoWebApplication.SqlDataProvider.dll
Tip: Nadat eenmaal het ZIP bestand gemaakt is, is het vrij eenvoudig up-to-date te houden. Gebruik daarvoor de Freshen functie zoals die onder andere in WinZip bestaat. WinZip controleert dan per bestand of er een nieuwere versie van bestaat.
Upload en Installatie in DotNetNuke
Nu het ZIP- file bestaat, kan deze worden geupload naar de DotNetNuke website. Log in op de website met het ‘host’ account en ga naar Host, Module Definitions. Kies daar voor ‘Upload new module’ en voeg de ZIP file toe aan de lijst van te installeren modules.
StartJob Starting Installation
StartJob Reading files
Info Loading DemoWebApplication.dll
Info File demowebapplication.dll read successfully
Info Loading DemoWebApplication.dnn
Info File demowebapplication.dnn read successfully
Info Loading EditCustomer.ascx
Info File editcustomer.ascx read successfully
Info Loading Customers.ascx
Info File customers.ascx read successfully
Info Loading Uninstall.SqlDataProvider
Info File uninstall.sqldataprovider read successfully
Info Loading DemoWebApplication.SqlDataProvider.dll
Info File demowebapplication.sqldataprovider.dll read
successfully
Info Loading 01.00.00.SqlDataProvider
Info File 01.00.00.sqldataprovider read successfully
EndJob Reading files done.
StartJob Reading DNN file
Info DNN file is in valid 2.0 format.
Info ...
Info Loading files info
Info Loading Modules info
Info Loading Control info for 'NedFox –
DemoWebApplication' module
EndJob Dnn load finished successfully
StartJob Begin Sql execution
Info Executing 01.00.00.sqldataprovider
StartJob Start Sql execution:
01.00.00.sqldataprovider file
EndJob End Sql execution: 01.00.00.sqldataprovider file
EndJob Finished Sql execution
StartJob Creating files
Info Created c:\inetpub\wwwroot\dnn308plato\
DesktopModules\NedFox –
DemoWebApplication\customers.ascx
Info Created c:\inetpub\wwwroot\dnn308plato\
DesktopModules\NedFox –
DemoWebApplication\editcustomer.ascx
Info Created c:\inetpub\wwwroot\dnn308plato\
bin\demowebapplication.dll
Info Created c:\inetpub\wwwroot\dnn308plato\
bin\demowebapplication.sqldataprovider.dll
Info Created c:\inetpub\wwwroot\dnn308plato\
DesktopModules\NedFox –
DemoWebApplication\Providers\DataProviders\
sqldataprovider\01.00.00.sqldataprovider
Info Created c:\inetpub\wwwroot\dnn308plato\
DesktopModules\NedFox –
DemoWebApplication\uninstall.sqldataprovider
Info Created c:\inetpub\wwwroot\dnn308plato\
DesktopModules\NedFox –
DemoWebApplication\demowebapplication.dnn
EndJob Files created
StartJob Registering DesktopModule
Info Registering Definitions
Info Registering Controls
EndJob Registering finished
EndJob Installation successfull.
In bovenstaand logfile is goed te zien hoe de ZIP file verwerkt is op basis van het DemoWebApplication.Dnn script. De volledige upload is succesvol uitgevoerd, zoals te zien is aan de laatste regels. Er kan nu een nieuwe pagina worden aangemaakt waar de module ‘NedFox – DemoWebApplication’ aan toegevoegd kan gaan worden.
In het volgende deel van dit artikel ga ik verder in op het resultaat van het toevoegen van de module, en de manier waarop andere zaken zoals Edit, Delete en Insert worden afgehandeld binnen het DotNetNuke framework.