|
|||||||||||||||||||||
|
|||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionI migrated a part of a big site (> 500 pages) to DotNetNuke which is an Open Source .NET CMS. After migration, the loading of each page was very slow (10 sec!). After investigating, I found out that the Important: BackgroundDotNetNuke is an open source .NET Content Management System. It is derived from the IBuySpyPortal, which is a best practice from Microsoft to show the capabilities of ASP.NET. Currently, DotNetNuke (DNN) is in version 4 which is based on the new ASP.NET 2.0 and is programmed in VB.NET. Because of its big community support, MS is supporting the DNN project. DNN is programmed by a core team, lead by Shaun Walker. Features
Using the codeI did a bit of over-commenting inline of the code, so that anyone can understand what each step is doing. Basically, the code is straightforward. All the data and the business logic is in the App_Code folder, and the UI code is in the ViewDnnSiteMap.ascx.cs file. In the data layer, you will find the following functions: /// <summary>
/// Gets all tabs that have no ParentId
/// and are not deleted and visible
/// </summary>
/// <returns>IDataReader: TabId (int), TabName (string),
/// Children (int)</returns>
public abstract IDataReader GetRootNodesFromDb();
/// <summary>
/// Gets all tabs that are children of the specified tab
/// </summary>
/// <param name="parentTabId">TabId of the parent tab</param>
/// <returns>IDataReader: TabId (int), TabName (string),
/// Children (int)</returns>
public abstract IDataReader GetChildNodesFromDb(int parentTabId);
/// <summary>
/// Gets parent tab for specified tab
/// </summary>
/// <param name="childTabId">TabId of the child tab</param>
/// <returns>IDataReader: ParentTabId (int), ParentName (string);
/// (should be max one row)</returns>
public abstract IDataReader GetParentFromDb(int childTabId);
/// <summary>
/// Gets the Tab, that hosts the given module
/// </summary>
/// <param name="tabModuleId">TabModuleId of the module</param>
/// <returns>IDataReader: ParentTabId (int), ParentName (string);
/// (should be max one row)</returns>
public abstract IDataReader GetTabViaTabModuleIdFromDb(
int tabModuleId);
/// <summary>
/// Gets node with specified TabId from Db
/// </summary>
/// <param name="nodeTabId">TabId for node</param>
/// <returns>IDataReader: TabId (int), TabName (string),
/// Children (int)</returns>
public abstract IDataReader GetNodeFromDb(int nodeTabId);
You can find the implementation of these functions in the SqlDataProvider.cs file. They are basically simple SQL The business layer can be found in the controller class in DnnSiteMapController.cs. The functions are: /// <summary>
/// Retrieves all visible root nodes from Db
/// </summary>
/// <returns>List of root nodes as ExtendedTreeNode
/// </returns>
public List<ExtendedTreeNode> GetRootNodesFromDb()
/// <summary>
/// Retrieves Child Nodes from Db for given Node
/// </summary>
/// <param name="parentNode">ParentNode,
/// for which the children should be retrieved</param>
/// <returns>List of children as ExtendedTreeNode
/// </returns>
public List<ExtendedTreeNode> GetChildNodesFromDb(
TreeNode parentNode)
/// <summary>
/// Gets the navigation path for a given Tab to the root
/// </summary>
/// <param name="childTab">Tab for
/// which the path should be retrieved</param>
/// <returns>List of Tabs, begining with the root
/// and ending with the Child</returns>
public List<Structs.Tab> GetNavigationPathFromDb(
Structs.Tab childTab)
/// <summary>
/// Gets the Tab, that hosts the given module
/// </summary>
/// <param name="tabModuleId">TabModuleId of the module
/// </param>
/// <returns>Dnn TabId</returns>
public Structs.Tab GetTabViaTabModuleIdFromDb(int tabModuleId)
/// <summary>
/// Gets node with specified TabId from Db
/// </summary>
/// <param name="nodeTabId">TabId for node</param>
/// <returns>Specified node; null if node is not found
/// </returns>
public ExtendedTreeNode GetNodeFromDb(int nodeTabId)
The UI code is in the ViewDnnSiteMap.ascx.cs file. In the protected void Page_Load(System.Object sender,
System.EventArgs e)
{
try
{
if (!IsPostBack)
{
// controller class
DnnSiteMapController objDnnSiteMaps =
new DnnSiteMapController();
// config settings
ConfigurationSettings settings =
new ConfigurationSettings(this.Settings);
// set show lines
this.TreeView1.ShowLines = settings.ShowLines;
// set image set
this.TreeView1.ImageSet = settings.ImageSet;
// set node wrap
this.TreeView1.NodeWrap = settings.NodeWrap;
// set show controls
this.pnlControls.Visible = settings.ShowControls;
// set node indent
this.TreeView1.NodeIndent = settings.NodeIndent;
// fill root nodes or specified rootNode
this.FillRootNodes(settings.RootNode);
// get current TabId from DNN and expand to it
this.ExpandToTab(this.TabId);
}
}
catch (Exception exc) //Module failed to load
{
Exceptions.ProcessModuleLoadException(this, exc);
}
}
In the protected void TreeView1_TreeNodeExpanded(object sender,
TreeNodeEventArgs e)
{
// if node has DummyNode, else data was
// already retrieved from Db
if (NodeHelper.HasDummyNode(e.Node))
{
// controller class
DnnSiteMapController objDnnSiteMaps =
new DnnSiteMapController();
// clear child nodes
e.Node.ChildNodes.Clear();
// for all child nodes
foreach (ExtendedTreeNode childNode in
objDnnSiteMaps.GetChildNodesFromDb(e.Node))
{
// if root has children, add dummy node
if (childNode.HasChildren)
{
NodeHelper.AddDummyNode(childNode);
}
// add children to expanded node
e.Node.ChildNodes.Add(childNode);
}
}
// select current node
this.SelectCurrentNode();
}
The private void ExpandToTab(int tabId)
{
// controller class
DnnSiteMapController objDnnSiteMaps =
new DnnSiteMapController();
// collapses all nodes; IMPORTANT to use this function
// instead directly TreeView.CollapseAll(), because
// it can loose all nodes
this.CollapseAll();
// find node in tree view (no roundtrip to Db)
TreeNode node =
NodeHelper.GetNode(this.TreeView1.Nodes, tabId);
// check if node is already in tree view
if (node != null)
{
TreeNode currentNode = node;
// expand to node
while (currentNode != null)
{
currentNode.Expand();
currentNode = currentNode.Parent;
}
}
else // get parent path from Db
{
List<Structs.Tab> parentTabs =
objDnnSiteMaps.GetNavigationPathFromDb(
new Structs.Tab(tabId, String.Empty));
TreeNode currentNode = null;
// expand all nodes along path
foreach (Structs.Tab nodeTab in parentTabs)
{
currentNode =
NodeHelper.GetNode(this.TreeView1.Nodes,
nodeTab.TabId);
if (currentNode != null)
{
currentNode.Expand();
}
}
}
// select current node
this.SelectCurrentNode();
}
Points of interestDNN installation instructionsStep 1: Install the module via DNNLogin in as host, and select in the Host menu "Module Definitions". At the bottom of the page, press "Upload new module". Then, select the .zip file, add it, and then upload it. Step 2: Alter web.config file (without this, DNN won't work anymore)The module is written in C#, you must include the following lines in your web.config file, in the <codeSubDirectories>
<add directoryName="DnnSiteMap"/>
</codeSubDirectories>
Value property of the TreeNode classBecause every tab (page) in DNN has a ExtendedNode classThe DummyNodesThe ConfigSettingsI encapsulated the settings in the class RoadmapNew features can be: using stored procedures; defining custom CSS classes .... So, there is still lots to do. CopyrightDNNSiteMap, Copyright (c) 2006 by BitConstruct, Halanek & Co KEG (BitConstruct). Permission is hereby granted, free of charge, to any person obtaining a copy of this software and the associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation of the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
History
| ||||||||||||||||||||