Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Creating a Super-Fast and Super-Easy DotNetNuke® Module - for Absolute Beginners!

4.93/5 (21 votes)
28 Jun 2006BSD13 min read 2   785  
This tutorial will show you how to create a DotNetNuke module using the new DAL+, an extended feature set of the DotNetNuke Data Access Layer.

Image 1

Introduction

Let's say your boss just gave you an assignment to create a "Trading Post" type of module for the company intranet that is running on DotNetNuke. In the past, you would have spent nearly half an hour just setting up the development environment, and hours creating the Data Access Layer (DAL) and the code.

All that has changed with the recent enhancements to DotNetNuke and the DAL, in the creation of the DAL+.

This tutorial will show you how to create a DotNetNuke module using the new DAL+, an extended feature set of the DotNetNuke Data Access Layer (DAL).

What you will need

To use this tutorial, you need:

  1. Visual Studio Express (download)
  2. SQL Server Express (download)
  3. DotNetNuke Starter Kit 4.x (download) (Note: When you download it, it may change the file extension to ".zip". After downloading, change this to ".vsi", and then you can double-click on the file to install the templates.)

The module

The goal of this tutorial is to show how DotNetNuke module development is now super-fast and super-easy. The sample module consists of only four files:

  • A Web User Control
  • A code-behind file for the Web User Control
  • A simple class file to hold the data
  • A "controller" class to connect to the database

Setup

  1. Install Visual Studio Express if you haven't already done so (download)
  2. Install SQL Server Express if you haven't already done so (download)
  3. Follow the directions here to install the DotNetNuke Starter Kit and to create a DotNetNuke website
  4. In Visual Studio, select "Build", then "Build Solution". You must be able to build it without errors before you continue

Are you ready to create the module?

You must have a DotNetNuke 4 website up and running to continue. If you do not, you can use this link and this link to find help. DotNetNuke is constantly changing as it evolves, so the best way to get up-to-date help and information is to use the DotNetNuke message board.

DAL vs. DAL+

Image 2

From: "DotNetNuke Module Developers Guide". Copyright © 2003-2005 Perpetual Motion Interactive Systems, Inc. All Rights Reserved.

Using the normal DotNetNuke Data Access Layer (DAL) design, we would create a database provider class that communicates with the database and overrides methods in an abstract class (data provider). This class sits between the database provider class and the Business Logic Layer (BLL). This would have allowed us to substitute an alternate database provider class to communicate with other databases.

In this tutorial, we will be demonstrating DAL+. The DAL+ is an alternative method of communicating with the database. This method will still allow us to communicate with an alternate database if DotNetNuke is running using an alternate provider that supports DotNetNuke 4.1 or higher (or DotNetNuke 3.3 or higher).

However, unlike the traditional DAL, the DAL+ is not 100% "portable" to other data sources. It is best used for modules that will not be distributed to other DotNetNuke sites that may need to run on databases other than Microsoft SQL Server. For those situations, it is best to use the traditional DAL that is described in this tutorial.

The sample module this tutorial covers, demonstrates most of the functions you would need, including: "Select", "Delete", "Update", and "Insert". This tutorial also shows you how to use Object Data Sources. Using the techniques in this tutorial, you will save a massive amount of code that you would have to write if you wrote the exact same module in ASP.NET 1.1.

Setting up the module

We will create the module using the following steps:

  • Create DAL+
    • Create the "info class"
    • Create the "controller class"
  • Create the "View" control
    • Create the grid view and form view
    • Create the code-behind
  • Create the tables and stored procedures
  • Register the module in DotNetNuke

Create the directories

Open your DotNetNuke website in Visual Studio:

Image 3

A DotNetNuke module resides in two directories. The Web User Controls and their associated code-behind files reside in the "DesktopModules" directory, and all other code (Data Access Layer and Business Logic Layer code) resides in the "App_Code" directory.

Create DAL+

First, we will create the Data Access Layer using the DAL+ method. This is the class that communicates with the database.

Create the "info class"

Right-click on the "App_Code" folder and select "New Folder".

Image 4

Name the new folder "ThingsForSale":

Image 5

Right-click on the "ThingsForSale" folder you just created, and select "Add New Item".

Image 6

In the "Add New Item" box that opens, click on "Class" under "Visual Studio Installed Templates", enter "ThingsForSaleInfo.vb" in the "Name" box, and click the "Add" button.

Image 7

The class will now open up in the designer:

Image 8

Replace all the code with the following code:

VB
Namespace YourCompany.Modules.ThingsForSale

Public Class ThingsForSaleInfo

    Private _ModuleId As Integer
    Private _ID As Integer
    Private _UserID As Integer
    Private _Category As String
    Private _Description As String
    Private _Price As Double

    ' initialization
    Public Sub New()
        MyBase.New()
    End Sub

    ' <summary>
    ' Gets and sets the Module Id
    ' </summary>
    Public Property ModuleId() As Integer
        Get
            Return _ModuleId
        End Get
        Set(ByVal value As Integer)
            _ModuleId = value
        End Set
    End Property

    ' <summary>
    ' Gets and sets the Item ID
    ' </summary>
    Public Property ID() As Integer
        Get
            Return _ID
        End Get
        Set(ByVal value As Integer)
            _ID = value
        End Set
    End Property

    ' <summary>
    ' Gets and sets the UserID
    ' </summary>
    Public Property UserID() As Integer
        Get
            Return _UserID
        End Get
        Set(ByVal value As Integer)
            _UserID = value
        End Set
    End Property

    ' <summary>
    ' Gets and sets the Category
    ' </summary>
    Public Property Category() As String
        Get
            Return _Category
        End Get
        Set(ByVal value As String)
            _Category = value
        End Set
    End Property
    
    ' <summary>
    ' Gets and sets the Description
    ' </summary>
    Public Property Description() As String
        Get
            Return _Description
        End Get
        Set(ByVal value As String)
            _Description = value
        End Set
    End Property

    ' <summary>
    ' Gets and sets the Price
    ' </summary>
    Public Property Price() As Double
        Get
            Return _Price
        End Get
        Set(ByVal value As Double)
            _Price = value
        End Set
    End Property

End Class

End Namespace
What did we just do?

We created a simple class file. This class, when instantiated, becomes an object, and that object will be used to pass the data between the Data Access Layer that we are constructing and the Web User control that we will create later. If you are unfamiliar with Object Oriented Programming, here is a good site for reference.

Notice that this class has one property for each field of data that we will need to transfer back and forth.

Create the "controller class"

Right-click on the "ThingsForSale" folder and select "Add New Item".

Image 9

In the "Add New Item" box that opens, click on "Class" under "Visual Studio Installed Templates", enter "ThingsForSaleController.vb" in the "Name" box, and click the "Add" button.

Image 10

The class will now open up in the designer:

Image 11

Replace all the code with the following code:

VB
Imports System
Imports System.Collections.Generic
Imports System.Data

Namespace YourCompany.Modules.ThingsForSale

Public Class ThingsForSaleController

    <DataObjectMethod(DataObjectMethodType.Insert)> _
    Public Shared Sub ThingsForSale_Insert(ByVal _
                  ThingsForSaleInfo As ThingsForSaleInfo)
        DataProvider.Instance().ExecuteNonQuery("ThingsForSale_Insert", _
               ThingsForSaleInfo.ModuleId, GetNull(ThingsForSaleInfo.UserID), _
               GetNull(ThingsForSaleInfo.Category.ToString), _
               GetNull(ThingsForSaleInfo.Description.ToString), _
               GetNull(ThingsForSaleInfo.Price))
    End Sub

    <DataObjectMethod(DataObjectMethodType.Delete)> _
    Public Shared Sub ThingsForSale_Delete(ByVal _
                  ThingsForSaleInfo As ThingsForSaleInfo)
    DataProvider.Instance().ExecuteNonQuery(_
                 "ThingsForSale_Delete", ThingsForSaleInfo.ID)
    End Sub

    <DataObjectMethod(DataObjectMethodType.Update)> _
    Public Shared Sub ThingsForSale_Update(ByVal _
                  ThingsForSaleInfo As ThingsForSaleInfo)
        DataProvider.Instance().ExecuteNonQuery("ThingsForSale_Update", _
               ThingsForSaleInfo.ID, ThingsForSaleInfo.ModuleId, _
               GetNull(ThingsForSaleInfo.UserID), _
               GetNull(ThingsForSaleInfo.Category.ToString), _
               GetNull(ThingsForSaleInfo.Description.ToString), _
               GetNull(ThingsForSaleInfo.Price))
    End Sub

    <DataObjectMethod(DataObjectMethodType.Select)> _
    Public Shared Function ThingsForSale_SelectAll(ByVal _
           ModuleId As Integer) As List(Of ThingsForSaleInfo)
        Return CBO.FillCollection(Of ThingsForSaleInfo)_
               (CType(DataProvider.Instance().ExecuteReader(_
               "ThingsForSale_SelectAll", ModuleId), IDataReader))
    End Function

    Private Shared Function GetNull(ByVal Field As Object) As Object
        Return Null.GetNull(Field, DBNull.Value)
    End Function

End Class

End Namespace
What did we just do?

This time, we did a lot. However, we did a lot without using a lot of code.

We have constructed a class called "ThingsForSaleController" that has four public methods. Each of these methods uses one of the new methods of the DAL+ to execute stored procedures:

Image 12

We haven't created the stored procedures yet. We will do that in a later step. For now, we have simply created a method for each task we will need to perform with the database:

  • Delete - ThingsForSale_Delete
  • Insert - ThingsForSale_Insert
  • Select - ThingsForSale_SelectAll
  • Update - ThingsForSale_Update

Note: A protected method, "GetNull", is used to pass the proper null value to the database for any values that could be empty.

The Delete, Insert, and Update methods accept the "ThingsForSaleInfo" class that was created previously as a parameter.

Image 13

The SelectAll method takes an integer as a parameter and returns a "ThingsForSaleInfo" class.

Image 14

Image 15

The DAL+ is comprised of three methods used to execute stored procedures. The methods are:

  • ExecuteNonQuery - Used to execute a stored procedure that will not return a value.
  • ExecuteReader - Used to execute a stored procedure that will return multiple records.
  • ExecuteScalar - Used to execute a stored procedure that will return a single value.

The Delete, Insert, and Update methods use the ExecuteNonQuery method of the DAL+, and the SelectAll method uses the ExecuteReader method of the DAL+ (the ExecuteScalar method of the DAL+ is not used in this tutorial).

Image 16

Below is an explanation of the format used to implement the DAL+. The ExecuteReader method that is used in the "ThingsForSale_SelectAll" method is used in this example:

Image 17

Complete the code

Remember, a DotNetNuke module resides in two directories:

  • The Web User Controls and their associated code-behind files reside in the "DesktopModules" directory.
  • All other code resides in the "App_Code" directory.

Image 18

We have created the DAL+ code in the "App_Code" directory. We will now complete the module by creating the Web User Control in the "DesktopModules" directory.

Create the directory

Right-click on the "DesktopModules" folder and select "New Folder".

Image 19

Name the new folder "ThingsForSale".

Image 20

Create the "View" control

Right-click on the "ThingsForSale" folder you just created, and select "Add New Item".

Image 21

In the "Add New Item" box that opens:

  • Click on "Web User Control" under "Visual Studio Installed Templates".
  • Enter "ViewThingsForSale.ascx" in the "Name" box.
  • Make sure the "Place code in a separate file" box is checked.
  • Click the "Add" button.

Image 22

The "ViewThingsForSale.ascx" file will be created in the "ThingsForSale" folder under the "DesktopModules" folder.

Clicking the "plus" icon next to the file will display the associated code-behind file "ViewThingsForSale.ascx.vb".

Image 23

Create the grid view and form view

Double-click on the "ViewThingsForSale.ascx" file, and it will open up in the main editing window. Right now the page will be blank. Click the "Source" button at the bottom of the page to switch to source view.

Image 24

Replace all the code with the following code:

ASP.NET
<%@ Control language="vb" 
    Inherits="YourCompany.Modules.ThingsForSale.ViewThingsForSale" 
    CodeFile="ViewThingsForSale.ascx.vb" 
    AutoEventWireup="false" Explicit="True" %>

<%@ Register Assembly="DotNetNuke.WebUtility" 
    Namespace="DotNetNuke.UI.Utilities" TagPrefix="cc1" %> 

<%@ Register TagPrefix="dnn" TagName="Audit" 
    Src="~/controls/ModuleAuditControl.ascx" %> <br />

<asp:ObjectDataSource ID="ObjectDataSource_ThingsForSale" 
     runat="server" 
     DataObjectTypeName="YourCompany.Modules.ThingsForSale.ThingsForSaleInfo"
     DeleteMethod="ThingsForSale_Delete" 
     InsertMethod="ThingsForSale_Insert" 
     OldValuesParameterFormatString="original_{0}" 
     OnInit="Page_Load" SelectMethod="ThingsForSale_SelectAll" 
     TypeName="YourCompany.Modules.ThingsForSale.ThingsForSaleController" 
     UpdateMethod="ThingsForSale_Update">
  <SelectParameters> 
     <asp:Parameter DefaultValue="00" Name="ModuleId" Type="Int32" /> 
  </SelectParameters>
</asp:ObjectDataSource> 

<asp:GridView ID="GridView1" runat="server" 
     AllowPaging="True" AutoGenerateColumns="False" 
     DataSourceID="ObjectDataSource_ThingsForSale" 
     DataKeyNames="ID,UserID,ModuleId" CellPadding="4" 
     CellSpacing="1" EnableViewState="False"> 
  <Columns> 
    <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" /> 
    <asp:BoundField DataField="UserID" HeaderText="UserID" 
                    SortExpression="UserID" Visible="False" /> 
    <asp:BoundField DataField="ModuleId" 
                    HeaderText="ModuleId" 
                    SortExpression="ModuleId" Visible="False" /> 
    <asp:BoundField DataField="ID" HeaderText="ID" 
                    SortExpression="ID" Visible="False" /> 
    <asp:BoundField DataField="Category" 
                    HeaderText="Category" SortExpression="Category" /> 
    <asp:BoundField DataField="Price" HeaderText="Price" 
                    SortExpression="Price" 
                    DataFormatString="{0:c}" HtmlEncode="False" /> 
    <asp:BoundField DataField="Description" 
                    HeaderText="Description" SortExpression="Description" /> 
  </Columns> 
  <EmptyDataTemplate> 
    There are no Things 4 Sale 
  </EmptyDataTemplate> 
</asp:GridView> 

<br />
<asp:LinkButton ID="Add_My_Listing_LinkButton" runat="server" 
     EnableViewState="False">Add My Listing</asp:LinkButton><br /> 
<br /> 

<asp:FormView ID="FormView1" runat="server" DataKeyNames="ID" 
     DataSourceID="ObjectDataSource_ThingsForSale" 
     DefaultMode="Insert" BorderColor="DarkGray" 
     BorderStyle="Solid" BorderWidth="1px" CellPadding="4" Visible="False"> 
  <EditItemTemplate> 
  </EditItemTemplate> 
  <InsertItemTemplate> 
    Category: <asp:DropDownList ID="DropDownList1" 
               runat="server" DataSource='<%# Eval("Category") %>' 
               SelectedValue='<%# Bind("Category") %>' 
               EnableViewState="False"> 
                 <asp:ListItem>Home</asp:ListItem>
                 <asp:ListItem>Office</asp:ListItem>
                 <asp:ListItem>Electronics</asp:ListItem>
                 <asp:ListItem>Misc.</asp:ListItem>
              </asp:DropDownList>

    Price: $ <asp:TextBox ID="PriceTextBox" runat="server" 
               Text='<%# Bind("Price") %>'
               Width="56px" CausesValidation="True" 
               EnableViewState="False">
             </asp:TextBox><br /> 

    <asp:RangeValidator ID="RangeValidator1" runat="server" 
         ControlToValidate="PriceTextBox" 
         ErrorMessage="Price must be greater than 0" 
         MaximumValue="99999" MinimumValue="1"></asp:RangeValidator> 

    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" 
         runat="server" ControlToValidate="PriceTextBox" 
         ErrorMessage="A price is required"></asp:RequiredFieldValidator><br /> 

    Description:<br />

    <asp:TextBox ID="DescriptionTextBox" runat="server" 
         Text='<%# Bind("Description") %>' MaxLength="499" 
         TextMode="MultiLine" Width="286px" 
         EnableViewState="False"> </asp:TextBox><br /> 

    <asp:LinkButton ID="InsertButton" runat="server" 
         CausesValidation="True" CommandName="Insert" 
         Text="Insert" OnClick="InsertButton_Click"></asp:LinkButton> 

    <asp:LinkButton ID="InsertCancelButton" runat="server" 
         CausesValidation="False" CommandName="Cancel" 
         Text="Cancel" OnClick="InsertCancelButton_Click"></asp:LinkButton> 

    <asp:TextBox ID="ModuleIdTextBox" runat="server" 
         Text='<%# Bind("ModuleId") %>' 
         Width="14px" Visible="False"></asp:TextBox> 

    <asp:TextBox ID="IDTextBox" runat="server" 
         Text='<%# Bind("ID") %>' Width="13px" 
         Visible="False"></asp:TextBox> 

    <asp:TextBox ID="UserIDTextBox" runat="server" 
         Text='<%# Bind("UserID") %>' Width="10px" 
         Visible="False"></asp:TextBox> 
  </InsertItemTemplate> 
  <ItemTemplate> 
  </ItemTemplate> 
</asp:FormView>

Click the "Design" button at the bottom of the design window, and the screen will look like this:

Image 25

What did we just do?

We placed four controls on the page:

  • ObjectDataSource
    • This is at the top of the image on the right. It is labeled "ObjectDataSource". This control is bound to the "ThingsForSaleController" class created in the earlier step.
  • GridView
    • This control is immediately under the "ObjectDataSource" control. This control is bound to the "ObjectDataSource" control and is configured to Select, Update, and Delete.
  • LinkButton
    • This is a simple LinkButton that will display messages, and when clickable, will allow the FormView control below it to display.
  • FormView
    • This control will allow a user to enter an item into the database. It is also bound to the "ObjectDataSource" control and is configured to Insert.

A little more about the ObjectDataSource control

Hover the mouse over the "ObjectDataSource" control until the small black arrow appears.

Image 26

Click on it, and the configuration menu will appear. Click on "Configure Data Source".

Image 27

The "ThingsForSaleController" class is configured as the Object Data Source.

Image 28

Click the "Next >" button.

The next screen shows four tabs (Select, Update, Insert, and Delete). Clicking on each tab reveals that a different method of the "ThingsForSaleController" class is configured to handle each function.

Image 29

Click the "Next >" button.

The final screen shows the configuration for the parameter that is passed to the Select method. Here, we indicate "ModuleId" with a default value of "00". This is just a "place holder". The actual value will be supplied at run-time by code in a later step.

Image 30

In the properties window of the "ObjectDataSource" control, we see that the "DataObjectTypeName" is set to our "ThingsForSaleInfo" class that was created in a previous step.

This is how we indicate that this class will be used to pass data between the "ObjectDataSource" control and the "ThingsForSaleController" class.

Image 31

Create the code-behind

Double-click on the "ViewThingsForSale.ascx.vb" file so that it opens up in the design window.

Image 32

Replace all the code with the following code:

VB
Imports DotNetNuke
Imports System.Web.UI
Imports System.Collections.Generic
Imports System.Reflection
Imports DotNetNuke.Security.PortalSecurity
 
Namespace YourCompany.Modules.ThingsForSale
    Partial Class ViewThingsForSale
            Inherits Entities.Modules.PortalModuleBase
        Dim ThingsForSaleInfo_data As New ThingsForSaleInfo

        Protected Sub Page_Load(ByVal sender As System.Object, _
                  ByVal e As System.EventArgs) Handles MyBase.Load
            If IsInRole("Registered Users") Or _
               IsInRole("Administrators") Then
                Add_My_Listing_LinkButton.Enabled = True
            Else
                Add_My_Listing_LinkButton.Text = _
                   "You must be logged in to add a Listing"
                Add_My_Listing_LinkButton.Enabled = False
            End If
        End Sub

        Protected Sub SetModuleId(ByVal sender As Object, ByVal e As _
                  System.Web.UI.WebControls.ObjectDataSourceSelectingEventArgs) _
                  Handles ObjectDataSource_ThingsForSale.Selecting
            e.InputParameters("ModuleId") = ModuleId.ToString
        End Sub

        Protected Sub InsertingItem(ByVal sender As Object, ByVal e As _
                  System.Web.UI.WebControls.FormViewInsertEventArgs) _
                  Handles FormView1.ItemInserting
            e.Values.Item("UserID") = _
               Entities.Users.UserController.GetCurrentUserInfo.UserID
            e.Values.Item("ModuleId") = ModuleId.ToString()
            e.Values.Item("ID") = 0
        End Sub

        Protected Sub InsertCancelButton_Click(ByVal sender _
                      As Object, ByVal e As System.EventArgs)
            Me.FormView1.Visible = False
        End Sub

        Protected Sub Add_My_Listing_LinkButton_Click(ByVal sender _
                  As Object, ByVal e As System.EventArgs) _
                  Handles Add_My_Listing_LinkButton.Click
            Me.FormView1.Visible = True
        End Sub

        Protected Sub InsertButton_Click(ByVal sender As Object, _
                                         ByVal e As System.EventArgs)
            Me.FormView1.Visible = False
            Add_My_Listing_LinkButton.Text = _
                   "Update Successful - Add Another Listing"
        End Sub

        Protected Sub HideEditButtons(ByVal sender As Object, _
                  ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) _
                  Handles GridView1.RowDataBound
            If e.Row.RowType = DataControlRowType.DataRow Then
                ThingsForSaleInfo_data = CType(e.Row.DataItem, _
                                         ThingsForSaleInfo)
                If IsInRole("Administrators") Or _
                 (Entities.Users.UserController.GetCurrentUserInfo.UserID _
                 = CInt(ThingsForSaleInfo_data.UserID)) Then
                    e.Row.Cells.Item(0).Enabled = True
                Else
                    e.Row.Cells.Item(0).Text = "&nbsp;"
                End If
            End If
        End Sub
    End Class
End Namespace
What did we just do?

We entered code that will handle:

  • Only allowing a person who is a registered user or an administrator to add an entry (IsInRole("Registered Users") Or IsInRole("Administrators"))
  • Only allowing a person to edit their own entries (Entities.Users.UserController.GetCurrentUserInfo.UserID = CInt(ThingsForSaleInfo_data.UserID)
  • Injecting the current "ModuleId" into the "ObjectDataSource" control.

Hopefully, this will help those using Object Data Sources with DotNetNuke. There is a problem of grabbing the current “ModuleId”.

This is a very important value that is exposed by the DotNetNuke core code. This value tells you which instance of the module you are working with. This is important because a person can place multiple instances of your module on a single page. You can’t have them click a button on one instance of the module and return data from another instance of the module.

You can see the solution in “ViewThingsForSale.ascx” and “ViewThingsForSale.ascx.vb”. In the “ViewThingsForSale.ascx” file, in the "ObjectDataSource" control, we indicate the “ModuleId” parameter as a “Select” parameter that will be passed to the “Select” method:

In “ViewThingsForSale.ascx.vb”, we have:

VB
Protected Sub SetModuleId(ByVal sender As Object, _
          ByVal e As System.Web.UI.WebControls.ObjectDataSourceSelectingEventArgs) _
          Handles ObjectDataSource_ThingsForSale.Selecting
 e.InputParameters("ModuleId") = ModuleId.ToString
End Sub

This event fires when the “Select” event is called in the "ObjectDataSource" control, but before the control passes the value to the “SelectAll” method in the "ThingsForSaleController" class. This allows you to pass the “ModuleId” to the "ThingsForSaleController" class (and on to the "ThingsForSale_SelectAll" stored procedure so it returns the proper data).

Compile and build the module

From the toolbar, select "Build" then "Build Solution".

Image 33

The site should build with no errors.

Image 34

In the Solution Explorer, right-click on the "Default.aspx" page and select Set As Start Page.

Image 35

From the toolbar, select Debug, then Start Without Debugging.

Image 36

The website should now come up:

Image 37

If you have problems, download the code from the link at the top of this article, and compare it to your code.

Remember: the module will not work yet because the table and stored procedures have not been created yet. However, the code should still compile at this point.

Complete the code

In the previous step, you will have opened your DotNetNuke website in the web browser, at this point.

Click Login.

Image 38

Log in as "host". The password (if you haven't already changed it) is "dnnhost".

Image 39

Create the tables and stored procedures

Click on the Host menu and select SQL.

Image 40

Paste the following script in the box:

SQL
/** Create Table **/
CREATE TABLE {databaseOwner}[{objectQualifier}ThingsForSale] (
[ID] [int] IDENTITY(1,1) NOT NULL,
[ModuleId] [int] NOT NULL,
[UserID] [int] NULL,
[Category] [nvarchar](25),
[Description] [nvarchar](500),
[Price] [float] NULL
) ON [PRIMARY]
ALTER TABLE {databaseOwner}[ThingsForSale] ADD
CONSTRAINT [PK_{objectQualifier}ThingsForSale] PRIMARY KEY CLUSTERED
([ID]) ON [PRIMARY]
GO

/** Create Stored Procedures **/
CREATE PROCEDURE {databaseOwner}[{objectQualifier}ThingsForSale_Delete]
@ID int
AS
DELETE FROM {objectQualifier}ThingsForSale
WHERE (ID = @ID)
RETURN
GO

CREATE PROCEDURE {databaseOwner}[{objectQualifier}ThingsForSale_Insert]
@ModuleId int,
@UserID int,
@Category nvarchar(25),
@Description nvarchar(500),
@Price float
AS
INSERT INTO {objectQualifier}ThingsForSale
(ModuleId, UserID, Category, Description, Price)
VALUES (@ModuleId,@UserID,@Category,@Description,@Price)
RETURN
GO

CREATE PROCEDURE {databaseOwner}[{objectQualifier}ThingsForSale_SelectAll]
@ModuleId int
AS
SELECT ID, ModuleId, UserID, Category, Description, Price
FROM {objectQualifier}ThingsForSale
WHERE (ModuleId = @ModuleId)
ORDER BY Category
RETURN
GO

CREATE PROCEDURE {databaseOwner}[{objectQualifier}ThingsForSale_Update]
@ID int,
@ModuleId int,
@UserID int,
@Category nvarchar(25),
@Description nvarchar(500),
@Price float
AS
UPDATE {objectQualifier}ThingsForSale
SET ModuleId = @ModuleId, UserID = @UserID, Category = @Category, 
    Description = @Description, Price = @Price
WHERE (ID = @ID)
RETURN
GO

Image 41

Select the "Run as Script" box, and click "Execute".

Watch the progress bar in your web browser because when the script has been run, the text in the window will shift, and then... nothing. Perhaps, we will get a "completed" message some day :).

Image 42

What did we just do?

We ran a SQL script that created the table and the stored procedures.

You will notice that the script is written like:

SQL
CREATE TABLE {databaseOwner}[{objectQualifier}ThingsForSale]

rather than the normal:

SQL
CREATE TABLE [dbo][ThingsForSale]

The script commands "{databaseOwner}" and "{objectQualifier}" indicate that they are to be replaced by configuration settings in the web.config file. Normally, "{databaseOwner}" is set to ".dbo" and "{objectQualifier}" is set to nothing (it would not have a setting). However, if alternate settings were indicated in the web.config file, those settings would be inserted into the script.

You must have the "Run as Script" box checked for this replacement to happen.

Register the module in DotNetNuke

While logged into your DotNetNuke site as "host" in the web browser, from the menu bar, select "Host". Then select "Module Definitions".

Image 43

Click the black arrow that is pointing down, to make the fly-out menu to appear. On that menu, select "Add New Module Definition".

Image 44

In the Edit Module Definitions menu:

  • Enter "ThingsForSale" for Module Name
  • Enter "ThingsForSale" for Folder Title
  • Enter "ThingsForSale" for Friendly Title
  • Enter "ThingsForSale" for Description
  • Enter "1.0" for Version

Then click Update.

Image 45

Enter "ThingsForSale" for New Definition.

Then click "Add".

Image 46

Next, click "Add Control".

Image 47

In the Edit Module Control menu:

  • Enter "ThingsForSale" for Title.
  • Use the drop-down to select "DesktopModule/ThingsForSale/ViewThingsForSale.ascx" for Source.
  • Use the drop-down to select "View" for Type.

Then click Update.

Image 48

In the upper left hand corner of the website, under the Page Functions menu, click Add.

Image 49

In the Page Management menu, under Page Details:

  • Enter "ThingsForSale" for Page Name
  • Enter "ThingsForSale" for Page Title
  • Enter "ThingsForSale" for Description
  • Click the View Page box next to All Users

Then click Update.

Image 50

From the Module drop-down, select "ThingsForSale".

Image 51

Then click Add.

Image 52

The module will now appear.

Image 53

What did we just do?

We have created a module definition and added the module to a page:

Image 54

License

This article, along with any associated source code and files, is licensed under The BSD License