Understanding the DotNetNuke Core Architecture

Exclusive offer: get 50% off this eBook here
Building Websites with DotNetNuke 5

Building Websites with DotNetNuke 5 — Save 50%

Quickly build and deploy your own feature-rich website with DotNetNuke 5, VB.NET, and C#

$26.99    $13.50
by Michael Washington | April 2010 | Web Development

In this article series by Ian Lackey and Michael Washington, we will be exploring the core functionality of the DotNetNuke architecture. We will be using the Source Code version of DotNetNuke 5.2.2 that can be downloaded from the DotNetNuke CodePlex site. We will start with an overview of the architecture, touching on key concepts employed by DotNetNuke. After this, we will examine some of the major sections that make up the framework. Finally, after we learn about the objects that make up the core, we will follow a request for a page through this process to find out how each page is dynamically created.

Architecture overview

As opposed to traditional web applications that may rely on a multitude of web pages to deliver content, DotNetNuke uses a single main page called Default.aspx. The content for this page is generated dynamically by using a tabID value to retrieve the skin and modules needed to build the page requested, from the DotNetNuke database. Before we move on, we should discuss what is meant by a tab and a page. As you read this article, you will notice the word "tab" is sometimes used when referring to pages in your DotNetNuke portal. In the original IBuySpy application, pages were referred to as tabs because they resembled tabs when added to the page.

IBuySpy application, the skeleton ASP.NET Framework, was created by Microsoft to demonstrate ASP.NET features, and DotNetNuke was originally derived from it.

This continued in the original versions of the DotNetNuke project. Starting with version 3.0, and continuing with version 5.2.x, there has been an ongoing effort to rename most of these instances to reflect what they really are: pages. Most references to "tabs" have been changed to "pages", but the conversion is not complete. For this reason, you will see both—tabs and pages—in the database, in the project files, and in this text. We will use these terms interchangeably throughout this text as we look into the core architecture of DNN.

We will begin with a general overview of what happens when a user requests a page on your DotNetNuke portal. The process for rendering a page in DotNetNuke works like this: a user navigates to a page on your portal; this calls the Default.aspx page, passing the tabid parameter in the querystring to let the application identify the page being requested. The example http://www.dotnetnuke.com/Default. aspx?tabid=476 demonstrates this.

DotNetNuke 3.2 introduced something called URL rewriting. This takes the querystring shown above and rewrites it so that it is in a format that helps increase search engine hits. We will cover the HTTP module that is responsible for this in more detail later in this article. The rewritten URL would resemble http://localhost/DotNetNuke/Home.aspx. This assumes that the page name for tabid 476 is Home. While referring to URLs in this article we will be using the non-rewritten version of the URL. URL rewriting can be turned off in the friendly URL section of the Host Settings page.

The querystring value (?tabid=476) is sent to the database, where the information required for the page is retrieved, as shown in the following diagram:

The portal that the user is accessing can be determined in a number of ways, but as you can see from the Tabs table (see the following screenshot), each page/tab contains a reference to the portal it belongs to in the PortalID field. Once the server has a reference to the page that the user requested (using the tabID), it can determine what modules belong to that page.

Although there are many more tables involved in this process, you can see that these tables hold not only the page and modules needed to generate the page, but also what pane to place them on (PaneName) and what container skin to apply (ContainerSrc).

All of this information is returned to the web server, and the Default.aspx page is constructed with it and returned to the user who requested it along with the required modules and skins, as shown in the following diagram.

Now, this is of course a very general overview of the process, but as we work through this article, we will delve deeper into the code that makes this process work, and in the end, show a request work its way through the framework to deliver a page to a user.

Diving into the core

There are over 160,000 lines of code in the DotNetNuke application. There is no practical (or even possible) way to cover the entire code base. In this section, we will go in depth into what I believe are the main portions of the code base: the PortalSettings as well as the companion classes found in the portals folder; the web.config file including the HTTP Modules and Providers; and the Global.asax and Globals.vb files.

We will start our discussion of the core with two objects that play an integral part in the construction of the architecture. The Context object and the PortalSettings class will both be referred to quite often in the code, and so it is important that you have a good understanding of what they do.

Using the Context object in your application

ASP .NET has taken intrinsic objects like the Request and the Application objects and wrapped them together with other relevant items into an intrinsic object called Context.

The Context object (HttpContext) can be found in the System.Web namespace. In the following table, you will find some of the objects that make up the HttpContext object.



Title

Description

Application

Gets the HttpApplicationState object for the current HTTP request.

Cache

Gets the Cache object for the current HTTP request.

Current

Gets the HttpContext object for the current HTTP request. This is a static (shared in VB) property of the HttpContext class, through which you access all other instance properties discussed in this table, that together enable you to process and respond to an HTTP request.

Items

Gets a key-value collection that can be used to organize and share data between an IHttpModule and an IHttpHandler during an HTTP request.

Request

Gets the HttpRequest object for the current HTTP request. This is used to extract data submitted by the client, and information about the client itself (for example, IP ), and the current request.

Response

Gets the HttpResponse object for the current HTTP response. This is used to send data to the client together with other response-related information such as headers, cacheability, redirect information, and so on.

Server

Gets the HttpServerUtility object that provides methods used in processing web requests.

Session

Gets the HttpSessionState instance for the current HTTP request.

User

Gets or sets security information for the current HTTP request.

Notice that most of the descriptions talk about the "current" request object, or the "current" response object. The Global.asax file, which we will look at soon, reacts on every single request made to your application, and so it is only concerned with whoever is "currently" accessing a resource.

The HttpContext object contains all HTTP-specific information about an individual HTTP request. In particular, the HttpContext.Current property can give you the context for the current request from anywhere in the application domain. The DotNetNuke core relies on the HttpContext.Current property to hold everything from the application name to the portal settings and through this makes it available to you.

The PortalSettings class

The portal settings play a major role in the dynamic generation of your pages and as such will be referred to quite often in the other portions of the code. The portal settings are represented by the PortalSettings class which you will find in the Entities\Portal\PortalSettings.vb file. As you can see from the private variables in this class, most of what goes on in your portal will at some point needto access this object. This object will hold everything from the ID of the portal to the default language, and as we will see later, is responsible for determining the skins and modules needed for each page.

Private _PortalId As Integer
Private _PortalName As String
Private _HomeDirectory As String
Private _LogoFile As String
Private _FooterText As String
Private _ExpiryDate As Date
Private _UserRegistration As Integer
Private _BannerAdvertising As Integer
Private _Currency As String
Private _AdministratorId As Integer
Private _Email As String
Private _HostFee As Single
Private _HostSpace As Integer
Private _PageQuota As Integer
Private _UserQuota As Integer
Private _AdministratorRoleId As Integer
Private _AdministratorRoleName As String
Private _RegisteredRoleId As Integer
Private _RegisteredRoleName As String
Private _Description As String
Private _KeyWords As String
Private _BackgroundFile As String
Private _GUID As Guid
Private _SiteLogHistory As Integer
Private _AdminTabId As Integer
Private _SuperTabId As Integer
Private _SplashTabId As Integer
Private _HomeTabId As Integer
Private _LoginTabId As Integer
Private _UserTabId As Integer
Private _DefaultLanguage As String
Private _TimeZoneOffset As Integer
Private _Version As String
Private _ActiveTab As TabInfo
Private _PortalAlias As PortalAliasInfo
Private _AdminContainer As SkinInfo
Private _AdminSkin As SkinInfo
Private _PortalContainer As SkinInfo
Private _PortalSkin As SkinInfo
Private _Users As Integer
Private _Pages As Integer

The PortalSettings class itself is simple. It is filled by using one of the constructors that accepts one or more parameters. These constructors then call the private GetPortalSettings method . The method is passed a tabID and a PortalInfo object. You already know that the tabID represents the ID of the page being requested, but the PortalInfo object is something new. This class can be found in the same folder as the PortalSettings class and contains the basic information about a portal such as PortalID, PortalName, and Description.

However, from the PortalSettings object, we can retrieve all the information associated with the portal. If you look at the code inside the constructors, you will see that the PortalController object is used to retrieve the PortalInfo object. The PortalInfo object is saved in cache for the time that is specifi ed on the Host Settings page.

A drop-down box on the Host Settings page (DesktopModules\Admin\HostSettings\HostSettings.ascx) is used to set the cache.

  • No caching:0
  • Light caching:1
  • Moderate caching:3
  • Heavy caching:6

The value in this dropdown ranges from 0 to 6; the code in the DataCache object takes the value set in the drop-down and multiplies it by 20 to determine the cache duration. Once the cache time is set, the method checks if the PortalSettings object already resides there. Retrieving these settings from the database for every request would cause your site to run slowly, so placing them in a cache for the duration you select helps increase the speed of your site. Recent versions of DotNetNuke have focused heavily on providing an extensive caching service. An example of this can be seen in the following code:

Dim cacheKey As String = String.Format(DataCache.PortalCacheKey,
PortalId.ToString())
Return CBO.GetCachedObject(Of PortalInfo)
(New CacheItemArgs(cacheKey, DataCache.PortalCacheTimeOut,
DataCache.PortalCachePriority, PortalId),
AddressOf GetPortalCallback)

We can see in the previous code that the CBO object is used to return an object from the cache. CBO is an object that is seen frequently throughout the DotNetNuke core. This object's primary function is to return the populated business object. This is done in several ways using different methods provided by CBO. Some methods are used to map data from an IDataReader to the properties of a business object. However, in this example, the Get CachedObject method handles the logic needed to determine if the object should be retrieved from the cache or from the database. If the object is not already cached, it will use the GetPortalCallback method passed to the method to retrieve the portal settings from the database. This method is located in the PortalController class (Entities\Portal\PortalController.vb) and is responsible for retrieving the portal information from the database.

Dim portalID As Integer = DirectCast(cacheItemArgs.ParamList(0),
Integer)
Return CBO.FillObject(Of PortalInfo)(DataProvider.Instance _
.GetPortal(portalID, Entities.Host.Host.ContentLocale.ToString))

This will fi ll the PortalInfo object (Entities\Portal\PortalInfo.vb), which as we mentioned, holds the portal information. This object in turn is returned to the GetCachedObject method. Once this is complete, the object is then cached to help prevent the need to call the database during the next request for the portal information. There is also a section of code (not shown) that verifi es whether the object was successfully stored in the cache and adds an entry to the event log if the item failed to be cached.

' if we retrieved a valid object and we are using caching
If objObject IsNot Nothing AndAlso timeOut > 0 Then
' save the object in the cache
DataCache.SetCache(cacheItemArgs.CacheKey, objObject, _
cacheItemArgs.CacheDependency, Cache.NoAbsoluteExpiration, _
TimeSpan.FromMinutes(timeOut), cacheItemArgs.CachePriority, _
cacheItemArgs.CacheCallback)

End If

After the portal settings are saved, the properties of the current tab information are retrieved and populated in the ActiveTab property. The current tab is retrieved by using the tabID that was originally passed to the constructor. This is handled by the VerifyPortalTab method and done by getting a list of all of the tabs for the current portal. Like the portal settings themselves, the tabs are saved in cache to boost performance. The calls to the caching provider, this time, are handled by the TabController (Entities\Tabs\TabController.vb). In the last VerifyPortalTab method, the code will loop through all of the host and non-host tabs, returned by the TabController, for the site until the current tab is located.

' find the tab in the portalTabs collection
If TabId <> Null.NullInteger Then
If portalTabs.TryGetValue(TabId, objTab) Then
'Check if Tab has been deleted (is in recycle bin)
If Not (objTab.IsDeleted) Then
Me.ActiveTab = objTab.Clone()
isVerified = True
End If
End If
End If
' find the tab in the hostTabs collection
If Not isVerified AndAlso TabId <> Null.NullInteger Then
If hostTabs.TryGetValue(TabId, objTab) Then
'Check if Tab has been deleted (is in recycle bin)
If Not (objTab.IsDeleted) Then
Me.ActiveTab = objTab.Clone()
isVerified = True
End If
End If
End If

If the tab was not found in either of these collections, the code attempts to use the splash page, home page, or the fi rst page of the non-host pages. After the current tab is located, further handling of some of its properties is done back in the GetPortalSettings method. This includes formatting the path for the skin and default container used by the page, as well as collecting information on the modules placed on the page.

Me.ActiveTab.SkinSrc = _
SkinController.FormatSkinSrc(Me.ActiveTab.SkinSrc, Me)
Me.ActiveTab.SkinPath = _
SkinController.FormatSkinPath(Me.ActiveTab.SkinSrc)

For Each kvp As KeyValuePair(Of Integer, ModuleInfo) In _
objModules.GetTabModules(Me.ActiveTab.TabID)
' clone the module object _
( to avoid creating an object reference to the data cache )
Dim cloneModule As ModuleInfo = kvp.Value.Clone
' set custom properties
If Null.IsNull(cloneModule.StartDate) Then
cloneModule.StartDate = Date.MinValue
End If
If Null.IsNull(cloneModule.EndDate) Then
cloneModule.EndDate = Date.MaxValue
End If
' container
If cloneModule.ContainerSrc = "" Then
cloneModule.ContainerSrc = Me.ActiveTab.ContainerSrc
End If
cloneModule.ContainerSrc = _
SkinController.FormatSkinSrc(cloneModule.ContainerSrc, Me)
cloneModule.ContainerPath = _
SkinController.FormatSkinPath(cloneModule.ContainerSrc)
' process tab panes
If objPaneModules.ContainsKey(cloneModule.PaneName) = False Then
objPaneModules.Add(cloneModule.PaneName, 0)
End If
cloneModule.PaneModuleCount = 0
If Not cloneModule.IsDeleted Then
objPaneModules(cloneModule.PaneName) = _
objPaneModules(cloneModule.PaneName) + 1
cloneModule.PaneModuleIndex = _
objPaneModules(cloneModule.PaneName) - 1
End If
Me.ActiveTab.Modules.Add(cloneModule)
Next

We have now discussed some of the highlights of the PortalSettings object as well as how it is populated with the information it contains. In doing so, we also saw abrief example of the robust caching service provided by DotNetNuke. You will see the PortalSettings class referenced many times in the core DotNetNuke code, so gaining a good understanding of how this class works will help you to become more familiar with the DNN code base. You will also fi nd this object to be very helpful while building custom extensions for DotNetNuke.

The caching provider itself is a large topic, and reaches beyond the scope of this article. However, simply understanding how to work with it in the ways shown in these examples should satisfy the needs of most developers. It is important to note that, you can get any type of object cached by DNN by passing in a key for your object to DataCache.SetCache method, together with the data, and some optional arguments.

While fetching the object back from DataCache.GetCache, you pass in the same key, and check the result. A non-null (non-Nothing in VB) return value means you have fetched the object successfully from the cache, otherwise you would need to fetch it from the database.

Building Websites with DotNetNuke 5 Quickly build and deploy your own feature-rich website with DotNetNuke 5, VB.NET, and C#
Published: April 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

Working with the configuration files

Next, we will continue our exploration of the DotNetNuke architecture by looking at a couple of fi les in the main DotNetNuke folder. The DotNetNuke Source Code version download is broken up into many different projects. This has been done so that you can open up only the fi les that you are concerned with. In this section, we will work with the website project along with the Providers used by the core. If you open the solution fi le in the Source Code download, you will fi nd that the website project will start with http://localhost/DotNetNuke_Community.

Expand the website project to expose two very important files, the web.config file, and the Global.aspx file. You will need to rename the release.config file to web.config before we begin.

If this is the fi rst time you have worked with the download, you will notice that there is no web.config fi le. The web.config file will originally be called release.config. This has been done to help ensure that during an upgrade you don't overlay the original web.config. As DotNetNuke uses encryption keys to store user passwords in the database, if you overlay this fi le your users will not be able to log in.

It is a recommended strategy to always back up your entire site including the web.config fi le for your production installation in a secure place after installation, and after each upgrade to the core.

The web.config file

The web.config file is an XML-based file that contains confi guration information that is specific to your web application. At runtime, ASP.NET stores this confi guration information in cache so that it can be easily retrieved by your application. If changes are made to this fi le, ASP.NET will detect the changes and automatically apply the new confi guration. The web.config file is very extensible; it allows you to defi ne new confi gurations and write handlers to process them. DotNetNuke takes full advantage of this ability, which we will discover as we move through this file.

Please be aware that any modification to web.config fi le leads ASP.NET to recycle the complete application domain for your website together with all cached data (possibly), and rebuild it from scratch, which can take a significant time for the fi rst request after the app-domain was recycled.

We will only touch on the areas of the web.config file that are specifically used in DotNetNuke. In the DotNetNuke website project, open up the web.config file, which was renamed from release.config. The first section in the file is the local configuration settings. Here we find the settings for our provider models. For our providers to work, we need a configuration section and confi guration section handler.

Configuring the providers used in DotNetNuke

< configSections > is broken into separate groups. The group named < dotnetnuke >, describes the providers that are available to the application, as shown in the following code snippet:

<sectionGroup name="dotnetnuke">
<!-- the requirePermission attribute will cause a syntax warning -
please ignore - it is required for Medium Trust support-->
<section name="data"
requirePermission="false"
type="DotNetNuke.Framework.Providers.
ProviderConfigurationHandler, DotNetNuke"/>
<section name="logging"
requirePermission="false"
type="DotNetNuke.Framework.Providers.
ProviderConfigurationHandler, DotNetNuke"/>
<section name="scheduling"
requirePermission="false"
type="DotNetNuke.Framework.Providers.
ProviderConfigurationHandler, DotNetNuke"/>
<section name="htmlEditor"
requirePermission="false"
type="DotNetNuke.Framework.Providers.
ProviderConfigurationHandler, DotNetNuke"/>
<section name="navigationControl"
requirePermission="false"
type="DotNetNuke.Framework.Providers.
ProviderConfigurationHandler, DotNetNuke"/>
<section name="searchIndex"
requirePermission="false"
type="DotNetNuke.Framework.Providers.
ProviderConfigurationHandler, DotNetNuke"/>
<section name="searchDataStore"
requirePermission="false"
type="DotNetNuke.Framework.Providers.
ProviderConfigurationHandler, DotNetNuke"/>
<section name="friendlyUrl"
requirePermission="false"
type="DotNetNuke.Framework.Providers.
ProviderConfigurationHandler, DotNetNuke"/>
<section name="caching"
requirePermission="false"
type="DotNetNuke.Framework.Providers.
ProviderConfigurationHandler, DotNetNuke"/>
<section name="authentication"
requirePermission="false"
type="DotNetNuke.Framework.Providers.
ProviderConfigurationHandler, DotNetNuke"/>
<section name="members"
requirePermission="false"
type="DotNetNuke.Framework.Providers.
ProviderConfigurationHandler, DotNetNuke"/>
<section name="roles"
requirePermission="false"
type="DotNetNuke.Framework.Providers.
ProviderConfigurationHandler, DotNetNuke"/>
<section name="profiles"
requirePermission="false"
type="DotNetNuke.Framework.Providers.
ProviderConfigurationHandler, DotNetNuke"/>
<section name="permissions"
requirePermission="false"
type="DotNetNuke.Framework.Providers.
ProviderConfigurationHandler, DotNetNuke"/>
<section name="moduleCaching"
requirePermission="false"
type="DotNetNuke.Framework.Providers.
ProviderConfigurationHandler, DotNetNuke"/>
<section name="outputCaching"
requirePermission="false"
type="DotNetNuke.Framework.Providers.
ProviderConfigurationHandler, DotNetNuke"/>
</sectionGroup>

This custom confi guration section handles the different providers integrated into the framework. Providers give the developer the ability to have a pluggable architecture. The data provider, for example, lets us decide which data store to use (Access or SQL Server), while the logging provider allows us to decide what logger we would like to use for our web application. The framework separates the act of logging from the type of logger being used. To change the logging, or any of the other providers, you would need to write your own provider to handle the functions as you see fi t (or choose from the providers that ship with the core).

The first declaration states the name that you will use when you refer to this section in your confi guration file. In other words, you will need the following tag to look for in your web.config file in order to see the providers that will handle this functionality:

name="data"

It also includes the type, which is the confi guration section handler. This should include the Global Assembly Cache (GAC) location information for the class.

type="DotNetNuke.Framework.Providers.ProviderConfigurationHandler,
DotNetNuke"

The type declaration follows the following configuration:

type="configuration section handler class, assembly"

The providers serve some of the following functions:

  • The data provider: Gives the ability to decide which datastore type you would like to use. The DotNetNuke framework is prepackaged with SQL, but there are others, such as MySQL and Oracle, which are available from third-party providers.
  • The logging provider: Used for all logging associated with the core framework. This handles, among other things, exception logging.
  • The scheduling provider: One of the newer features; along with the logging, this provider helps to facilitate recurring functionality.
  • The htmlEditor provider: The default HTML WYSIWYG editor is the FCKEditor. This confi guration setting allows you to substitute other rich textbox components for the FCKEditor.
  • The searchIndex provider: The default provides, if implemented, the ability to search the content of the modules located on your portal.
  • The searchDataStore provider: The default provides the ability to search for information inside the datastore you have selected as your data provider.
  • The friendlyUrl provider: The default provides the ability to rewrite the URL in a manner that is friendly to search engines.

Handling the providers

The configuration section only tells the application where each provider will be handled. The confi guration section has a companion section in the web.config file. This defi nes the confi guration section handlers. You will fi nd two handler sections in the web.config file, one for each group we just described. The fi rst handler section we will look at is the < dotnetnuke > section. This corresponds to the sectionGroup name in the confi guration section.

The < dotnetnuke > group

Within the < dotnetnuke> section (as shown in the next code snippet), we see the handlers for our individual providers, beginning with the HTML provider. The fi rst node in this section defi nes the default provider. The defaultProvider attribute is advised, but is optional. If it's left out, the fi rst provider in the list will serve as the default. The default provider for the htmlEditor is the FckHtmlEditorProvider.

The next node starts the provider section; it is followed by a < clear/ > node. This node is used to clear out the providers from the confi guration settings that may have been added in the machine.config fi le. The fi nal node is the < add/> node. This node is used to add our provider to the list of available providers. This list is used by the DotNetNuke core to tell it what is handling each section that uses a provider. DNN chooses one of the providers based on the defaultProvider attribute, if specifi ed, or the fi rst one, for each section in web.config that uses the provider model. Inside this node, we need to defi ne a few attributes that are as follows:

  • name: This is the friendly name of our provider. This can be any name that you like, preferably something meaningful.
  • type: This again follows the [namespace.class],[assembly name] format.
  • providerPath: This attribute points to where the provider class can be found within the application structure.

After the end of the < add/> node, the structure is completed with the closing tags for add, providers, and htmlEditor.

<dotnetnuke>
<htmlEditor defaultProvider="FckHtmlEditorProvider">
<providers>
<clear/>
<add name="FckHtmlEditorProvider"
type="DotNetNuke.HtmlEditor.
FckHtmlEditorProvider.FckHtmlEditorProvider, DotNetNuke.
FckHtmlEditorProvider"
providerPath="~/Providers/
HtmlEditorProviders/Fck/"
CustomConfigurationPath="~/Providers/
HtmlEditorProviders/Fck/custom/FCKConfig.js"
EnhancedSecurityDefault="false"
SecureConfigurationPath="~/Providers/
HtmlEditorProviders/Fck/custom/FCKConfigSecure.js"
ImageGalleryPath="~/Providers/
HtmlEditorProviders/Fck/fckimagegallery.aspx"
ImageUploadPath="~/Providers/HtmlEditorProviders/
Fck/fckimagegallery.aspx"
ImageAllowedFileTypes="gif,png,bmp,jpg"
FlashGalleryPath="~/Providers/
HtmlEditorProviders/Fck/fckimagegallery.aspx"
FlashUploadPath="~/Providers/HtmlEditorProviders/
Fck/fckimagegallery.aspx"
FlashAllowedFileTypes="fla,swf"
LinksGalleryPath="~/Providers/
HtmlEditorProviders/Fck/fcklinkgallery.aspx"
DynamicStylesGeneratorPath="~/Providers/
HtmlEditorProviders/Fck/FCKStyles.aspx"
DynamicStylesCaseSensitive="true"
DynamicStylesGeneratorFilter="controlpanel|
filemanager|mainmenu|wizard"
StaticStylesFile="~/Providers/
HtmlEditorProviders/Fck/FCKeditor/fckstyles.xml"
StylesDefaultMode="Static"
DynamicCSSGeneratorPath="~/Providers/
HtmlEditorProviders/Fck/FCKCSS.aspx"
StaticCSSFile="~/Providers/HtmlEditorProviders/
Fck/FCKeditor/editor/css/fck_editorarea.css"
CSSDefaultMode="static"
spellCheck="ieSpell"
AvailableToolbarSkins="Office2003,Silver"
DefaultToolbarSkin="Office2003"
AvailableToolBarSets="DNNDefault,Default,
NoGallery,Basic"
DefaultToolbarSet="DNNDefault"
DefaultImageGallerySkin="Default"
DefaultFlashGallerySkin="Default"
DefaultLinksGallerySkin="Default"
FCKDebugMode="false"
UseFCKSource="false"
OptionsOpenMode="ShowModalDialog"
CustomOptionsDialog="Admin"/>
</providers>
</htmlEditor>

This is followed by the < navigationControl > handler. This allows you to decide what control you would like to use for your menu navigation. The default is SolpartMenu.

The next two confi guration handlers are for the search facility built into the DotNetNuke framework. The searchIndex and searchDataStore follow the same confi guration as the htmlEditor. This is followed by the data provider.

<data defaultProvider="SqlDataProvider">
<providers>
<clear/>
<add name="SqlDataProvider"
type="DotNetNuke.Data.SqlDataProvider, DotNetNuke.
SqlDataProvider"
connectionStringName="SiteSqlServer"
upgradeConnectionString=""
providerPath="~\Providers\DataProviders\SqlDataProvider\"
objectQualifier=""
databaseOwner="dbo"/>
</providers>
</data>

The data provider has some additional attributes, which we did not see in the HTML provider. They are as follows:

  • connectionStringName: This provides the name of the connection string you will use for your portal. This string can be found in the < appSettings > section of the web.config file. < appSettings > section for connection string is used by only legacy modules. DNN core together with most modules now use the connection strings defi ned in the < connectionString > section in web.config.
  • upgradeConnectionString: This connection string is used for installation and updates. It is only used to run the upgrade scripts. This can be used to run the updates using a database user with more privileges.
  • objectQualifier: The objectQualifier is used to allow multiple DotNetNuke installations to run inside the same database. For example, if you added CC1 in the object qualifi er before you installed DotNetNuke, all the tables and stored procedures would be prefi xed with CC1. This would allow you to run another DotNetNuke implementation inside the same database by setting the object qualifier in the second one to CC2. Inside the database, you would have two of every stored procedure and table. Each pair would be named according to the pattern CC1_users, CC2_users, which would keep them separate. While developing your custom modules, you would also need to take care of this, and prefi x each database object reference with the object qualifier.
  • databaseOwner: The databaseOwner is set to dbo. This is the default database owner in SQL Server. Some hosting companies will require you to change this to refl ect your user.

The next configuration handler is for the logging provider. The logging provider handles all logging, including errors, associated with the portal.

<logging defaultProvider="DBLoggingProvider">
<providers>
<clear/>
<add name="DBLoggingProvider"
type="DotNetNuke.Services.Log.EventLog.
DBLoggingProvider.DBLoggingProvider, DotNetNuke.Provider.
DBLoggingProvider"
providerPath="~\Providers\LoggingProviders\
DBLoggingProvider\"/>
</providers>
</logging>

This is followed by the handler for the DNNScheduler:

<scheduling defaultProvider="DNNScheduler">
<providers>
<clear/>
<add name="DNNScheduler"
type="DotNetNuke.Services.Scheduling.
DNNScheduling.DNNScheduler, DotNetNuke.DNNScheduler"
providerPath="~\Providers\SchedulingProviders\
DNNScheduler\"
debug="false"
maxThreads="1"/>
</providers>
</scheduling>

The scheduler has a few additional attributes which we have not seen so far. They are as follows:

  • debug: When set to true, it will add additional log entries to aid in debugging scheduler problems.
  • maxThreads: This sets the maximum number of thread-pool threads to be used by the scheduler (1-10). Setting it to -1 tells the scheduler to determine this on its own.

The next handler for this section is for handling friendly URLs. We will be looking further into this functionality when we discover the HTTP modules that DotNetNuke employs, later in this article.

<friendlyUrl defaultProvider="DNNFriendlyUrl">
<providers>
<clear/>
<add name="DNNFriendlyUrl"
type="DotNetNuke.Services.Url.FriendlyUrl.
DNNFriendlyUrlProvider, DotNetNuke.HttpModules"
includePageName="true"
regexMatch="[^a-zA-Z0-9 _-]"
urlFormat="humanfriendly"/>
</providers>
</friendlyUrl>

The following handlers in this section are mainly concerned with authentication and caching. We will be looking further into the authentication functionality later in this article.

The < system.web> group

The < system.web > section of the web.config file is where most of the configuration of your ASP.NET web application is placed. However, the most common configurations are added to the machine.config when the .NET Framework is installed. The confi gurations will be automatically applied unless overridden in the web.config file.

You should take particular care while specifying HttpModules, and HttpHandlers in this section. IIS 6 and earlier use < system.web >, whereas IIS uses < system.webServer > sections for the purpose. A good rule of thumb is to specify your HttpHandlers and HttpModules in both sections to make sure they run on any version of IIS.

A discussion of ASP.NET confi guration is far beyond the scope of this book. If you would like to have a better understanding of how the framework handles the confi guration settings, please check MSDN for the latest information.

We will be discussing some of the information that can be contained in this section (including the HTTP modules) but for now, we'll concentrate on the providers that are defi ned in this section. As we saw in the < dotnetnuke > section earlier, here we see the information needed to confi gure the ASP.NET providers. One of the providers we find in the < system.web > section is the AspNetSqlMembership provider. The setup is similar to those we have already seen with the exception of the additional attributes.

This section may also contain the configuration for the members, roles, and profile providers. They all follow the same pattern as the Membership provider, inheriting from the Microsoft provider and overriding the ApplicationName property using the corresponding XML attribute.

HTTP modules

Located at the beginning of the < system.web > section is the HttpModules section, as shown in the following screenshot:

HTTP modules give you the ability to intercept the request for a page and modify the request in some way. In DotNetNuke, they have been added to abstract some of the code that used to reside inside the Global.asax.vb file, which is located in the App_Code folder of the website. This gives a greater degree of modularity and allows developers to change behavior without affecting the core architecture. An HTTP module is a class that implements the IHttpModule interface. This interface has the following two methods that you need to implement:

  1. Init: T his method allows an HTTP module to register its event handlers to the events in the HttpApplication object.
  2. Dispose: This method gives the HTTP module an opportunity to perform any cleanup before the object gets garbage collected.

These methods are called when they are hooked into the HTTP pipeline. The HTTP pipeline refers to the path followed by each request made to your application. The following diagram shows the path that a typical request takes through the pipeline:

For more information on how HTTP modules work within the HTTP pipeline, check out this great MSDN article by George Sheperd at http://msdn.microsoft.com/en-us/magazine/cc301362.aspx.

HTTP modules plug themselves into the ASP.NET request process by adding entries into the web.config file. This allows them to intercept the request before it is returned in order to modify the request to perform certain actions. DotNetNuke uses this process for a number of things.

To see an example of this, we will look at the Exception module, shown in the following code snippet. It is declared in the web.config file, along with the other HTTP modules.

The last line of code will place the ExceptionModule in the HTTP pipeline, allowing it to intercept each request. Let's take a look at the ExceptionModule class found in the DotNetNuke.HttpModules project, along with the other core HTTP modules. As we learned earlier, the Init method i s called when the module is hooked into the pipeline with a declaration in the web.config file. In this method, we add an event handler to the application.Error event that is raised whenever an unhandled exception happens in your application, as shown in the following code snippet:

<add name="Exception" type="DotNetNuke.HttpModules.Exceptions.
ExceptionModule, DotNetNuke.HttpModules"/>

The OnErrorRequest me thod is then called and the error is passed to the Error provider designated in the web.config file. The actual logging of the error is done by the logging provider. The default implementation of DotNetNuke comes with a DBLoggingProvider, but you may write your own provider to fi t your needs.

Public Class ExceptionModule
Implements IHttpModule
Public ReadOnly Property ModuleName() As String
Get
Return "ExceptionModule"
End Get
End Property
Public Sub Init(ByVal application As HttpApplication) _
Implements IHttpModule.Init
AddHandler application.Error, AddressOf Me.OnErrorRequest
End Sub

The UrlRewrite module is quite extensive. The fi rst thing that is needed is a designation in the HttpModules section of the web.config file.

Public Sub OnErrorRequest(ByVal s As Object, ByVal e As EventArgs)
Try
Dim Context As HttpContext = HttpContext.Current
Dim Server As HttpServerUtility = Context.Server
Dim Request As HttpRequest = Context.Request
'exit if a request for a .net mapping that isn't a
content page is made i.e. axd
If Request.Url.LocalPath.ToLower.EndsWith(".aspx") =
False _
AndAlso Request.Url.LocalPath.ToLower.
EndsWith(".asmx") = False _
AndAlso Request.Url.LocalPath.ToLower.
EndsWith(".ashx") = False Then
Exit Sub
End If
Dim lastException As Exception = Server.GetLastError()
'HttpExceptions are logged elsewhere
If Not (TypeOf lastException Is HttpException) Then
Dim lex As New Exception("Unhandled Error: ",
Server.GetLastError)
Dim objExceptionLog As New Services.Log.EventLog.
ExceptionLogController
Try
objExceptionLog.AddLog(lex)
Catch
End Try
End If
Catch ex As Exception
' it is possible when terminating the request for the
context not to exist
' in this case we just want to exit since there is
nothing else we can do
End Try
End Sub
Public Sub Dispose() Implements IHttpModule.Dispose
End Sub
End Class

As pointed in the beginning of this action, please ensure that you register your module in both the < system.web > and < system.webServer > sections.

If you are using Windows Vista, Windows 7, or Window Server 2008, then you defi nitely need the module registered in the < system.webServer > section.

You can view the UrlRewriteModule by looking in the DotNetNuke.HttpModules project under the UrlRewrite folder. This class is responsible for taking a URL and querystring that looks like this:

http://www.dotnetnuke.com/Default.aspx?tabid=476

and converting it to look like this:

http://localhost/DotNetNuke/Home.aspx

There are a few reasons why you would want to rewrite your URLs; among them are a cleaner appearance or hiding the physical page names, but probably the most important reason for DotNetNuke is to increase traffi c to your site. Search engines crawl your site with bots that look to catalog your pages. Search bots prefer non-dynamic web pages with descriptive URLs. By using URL rewriting, you can increase the popularity of your links on the major search engines.

As you look at this module, you can see that although the code that does the URL rewriting is extensive, it is hooked into the pipeline in the same fashion as the other modules. The Init method is used to add an event handler to Application. BeginRequest, which fi res every time a user requests a page on your site, so that on every request to your site the OnBeginRequest method is called and the URL is rewritten before it is sent on its way.

<add name="UrlRewrite" type="DotNetNuke.HttpModules.UrlRewriteModule,
DotNetNuke.HttpModules"/>

The rest of the HTTP modules follow this same pattern, and although they differ in complexity, they all accomplish their task by intercepting the request.

Application settings

Let's look at one of the remaining sections of web.config. Below < configSettings > you will fi nd a section called < appSettings >. This section holds three items that are of interest to us—SiteSqlServer, InstallProcedure, and InstallTemplate:

Public Sub Init(ByVal application As HttpApplication) _
Implements IHttpModule.Init
AddHandler application.BeginRequest, _
AddressOf Me.OnBeginRequest
End Sub

The SiteSqlServer is used for backwards compatibility for older modules. It holds the connection string for your data store. In .NET 2.0 and later versions, these settings are now held in the < connectionStrings > section. The next few keys help you decide how your portal is installed. IntallTemplate allows you to set which template to use when your portal is created.

The AutoUpgrade key allows you to determine if the application will automatically upgrade your portal if the database version is different than your fi le version. If this is set to false, you will have to manually navigate to the install URL

So if the hosting environment will not allow you to run the scripts necessary to install the membership provider on your own, you can use this key to turn this off so that the scripts can be run by your hosting provider manually.

The rest of the keys allow you to customize your portal to work in special environments.

>> Continue Reading Understanding the DotNetNuke Core Architecture- An Extension

If you have read this article you may be interested to view :

Building Websites with DotNetNuke 5 Quickly build and deploy your own feature-rich website with DotNetNuke 5, VB.NET, and C#
Published: April 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

About the Author :


Michael Washington

Michael Washington is a Website developer and an ASP.NET, C#, and Visual Basic programmer. He is a DotNetNuke Core member and has been involved with DotNetNuke for over 3 years. He is the author of numerous DotNetNuke modules and tutorials. He is one of the founding members of the Southern California DotNetNuke Users group. He has a son, Zachary and resides in Los Angeles with his wife Valerie.

Books From Packt

jQuery 1.4 Reference Guide
jQuery 1.4 Reference Guide

jQuery UI 1.7: The User Interface Library for jQuery
jQuery UI 1.7: The User Interface Library for jQuery

Drupal 6 Attachment Views
Drupal 6 Attachment Views

Joomla! 1.5: Beginner's Guide
Joomla! 1.5: Beginner's Guide

Grok 1.0 Web Development
Grok 1.0 Web Development

Apache MyFaces 1.2 Web Application Development
Apache MyFaces 1.2 Web Application Development

Magento 1.3: PHP Developer's Guide
Magento 1.3: PHP Developer's Guide

Drupal 7 First look
Drupal 7 First look

Your rating: None Average: 4.3 (4 votes)

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
M
j
Z
5
s
j
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software