Now that you have the properties defined for your objects, you need to populate the objects with values from your database. Object population begins with the Controller class. In this case, the controller is contained in the EventsController.vb class file in the module project. Open the file and review its contents.
Again, at the top of the file are the library imports:
Imports DotNetNuke.Services.Search Imports System Imports System.Configuration Imports System.Data Imports System.XML
Following this you again have to specify your namespace:
Next, you implement a couple of interfaces after you define your class (see Listing 14-4). In this module, you implement the Entities.Modules.ISearchable and Entities.Modules.IPortable interfaces. These are two interfaces that provide your module with the capability to tie into the search mechanism and the capability to export data from your module and import it into another instance of your module on another page within the portal. These interfaces are covered in more detail later in this chapter.
Listing 14-4: Defining the Controller Class for the Events Module
Public Class EventController Implements Entities.Modules.ISearchable Implements Entities.Modules.IPortable
Listing 14-5 shows the public methods within the Controller class that are used to populate an ArrayList of objects from the record set received from your abstraction class.
Listing 14-5: Public Methods of the EventsController Class
#Region "Public Methods" Public Sub AddEvent(ByVal objEvent As EventInfo) _ DataProvider.Instance().AddEvent(objEvent.ModuleId, _ objEvent.Description, objEvent.DateTime, objEvent.Title, _ objEvent.ExpireDate, objEvent.CreatedByUser, objEvent.Every, _ objEvent.Period, objEvent.IconFile, objEvent.AltText) End Sub Public Sub DeleteEvent(ByVal ItemID As Integer) DataProvider.Instance().DeleteEvent(ItemID) End Sub Public Function GetEvent(ByVal ItemId As Integer, _ ByVal ModuleId As Integer) As EventInfo Return CType(CBO.FillObject(DataProvider.Instance().GetEvent(ItemId, _ ModuleId), GetType(EventInfo)), EventInfo) End Function Public Function GetEvents(ByVal ModuleId As Integer, _ ByVal StartDate As Date, ByVal EndDate As Date) As ArrayList If (Not Common.Utilities.Null.IsNull(StartDate)) And _ (Not Common.Utilities.Null.IsNull(EndDate)) Then Return _ CBO.FillCollection(DataProvider.Instance().GetEventsByDate(ModuleId, _ StartDate, EndDate), GetType(EventInfo)) Else Return _ CBO.FillCollection(DataProvider.Instance().GetEvents(ModuleId), _ GetType(EventInfo)) End If End Function Public Sub UpdateEvent(ByVal objEvent As EventInfo) DataProvider.Instance().UpdateEvent(objEvent.ItemId, _ objEvent.Description, objEvent.DateTime, objEvent.Title, _ objEvent.ExpireDate, objEvent.CreatedByUser, objEvent.Every, _ objEvent.Period, objEvent.IconFile, objEvent.AltText) End Sub #End Region
In Listing 14-5, notice that AddEvent, DeleteEvent, GetEvent, GetEvents, and UpdateEvent are all methods in the Data Abstraction class (DataProvider.vb) in the Events module project of the solution. Each method creates an instance of the DataProvider class, and calls its corresponding event. Recall from Chapter 13 that each method in the abstraction class (DataProvider.vb in the Events module project) also has a corresponding method in the physical provider (the SQLDataProvider project) as a wrapper to the stored procedures contained in the SQL Server database. Each method accepts a value that corresponds to values passed to parameters contained in the stored procedure. For example, the DeleteEvent stored procedure contains a parameter of ItemID for specifying the primary key of the event contained in the Events table. As such, Sub DeleteEvent in the Controller class accepts an ItemID of type Integer.
As an item of note here, DotNetNuke provides the Custom Business Object (CBO) helper class. The class file is located in the <webroot>\Components\Shared\CBO.vb class file.
This class provides several methods, but for this area of concern, you want to focus on two:
FillObject: Creates an object with one item as in the case with the GetEvent method in Listing 14-5.
FillCollection: Creates an ArrayList of objects from matching records returned from the database.
The last code region in the EventsController class is the Optional Interfaces region. Contained in this region are methods for interacting with the ISearchable and IPortable interfaces provided by DotNetNuke. You do not have to use these methods, but it is recommended to provide a fully functional module that is capable of exposing all the features of DotNetNuke.
Listing 14-6 defines properties of the individual events from your module to be placed in the search catalog of the DotNetNuke index.
Listing 14-6: Defining Search Items of the Module for DotNetNuke Search
Public Function GetSearchItems(ByVal ModInfo As Entities.Modules.ModuleInfo) As _ Services.Search.SearchItemInfoCollection Implements _ Entities.Modules.ISearchable.GetSearchItems Dim SearchItemCollection As New SearchItemInfoCollection Dim Events As ArrayList = GetEvents(ModInfo.ModuleID, _ Convert.ToDateTime(Common.Utilities.Null.NullDate), _ Convert.ToDateTime(Common.Utilities.Null.NullDate)) Dim objEvents As Object For Each objEvents In Events Dim SearchItem As SearchItemInfo With CType(objEvents, EventInfo) Dim UserId As Integer = Null.NullInteger If IsNumeric(.CreatedByUser) Then UserId = Integer.Parse(.CreatedByUser) End If SearchItem = New SearchItemInfo(ModInfo.ModuleTitle & _ " - "& .Title, .Description, UserId, .CreatedDate, _ ModInfo.ModuleID, .ItemId.ToString, .Description, "Itembackground-color:d9d9d9"> .ItemId.ToString) SearchItemCollection.Add(SearchItem) End With Next Return SearchItemCollection End Function
Listing 14-6 contains a function called GetSearchItems, which will return a type of SearchItemInfoCollection that contains the values from the Events module when you call the GetEvents method. You loop through the events returned from calling GetEvents and create a new object of SearchItem. You then define the properties of the SearchItem by using the SearchItemInfo. You'll pass the values for the object to the SearchItem, which will be populated into the DotNetNuke catalog for searching. If you do not want to make the items searchable in the portal, do not implement the interface and exclude the GetSearchItems function.
This should sound very familiar after getting to this point in the book. Module development closely mirrors the architecture of DotNetNuke. Not only does the core application support abstraction classes and the Provider Model extensively, but you should also duplicate this methodology in your own development. This ensures your development is consistent with other modules contained in DotNetNuke and also eases the process of upgrading for future versions of DotNetNuke.
Note that the SearchItemInfo class exposes properties for the SearchItem object, similar to the Events class. This structure is consistent throughout the DotNetNuke architecture and in module development as well.
Another DotNetNuke interface that the Events module implements is IPortable. This interface provides the module with the capability to export the data contained for that module instance to another module instance.
Listing 14-7 looks at how you export data from the module instance.
Listing 14-7: The Function for the EventsController Class
Public Function ExportModule(ByVal ModuleID As Integer) As _ String Implements Entities.Modules.IPortable.ExportModule Dim strXML As String = "" Dim arrEvents As ArrayList = GetEvents(ModuleID, _ Convert.ToDateTime(Common.Utilities.Null.NullDate), _ Convert.ToDateTime(Common.Utilities.Null.NullDate)) If arrEvents.Count <> 0 Then strXML += "<events>" Dim objEvent As EventInfo For Each objEvent In arrEvents strXML += "<event>" strXML += "<description>" & XMLEncode(objEvent.Description) & _ "</description>" strXML += "<datetime>" & XMLEncode(objEvent.DateTime.ToString) & _ "</datetime>" strXML += "<title>" & XMLEncode(objEvent.Title) & "</title>" strXML += "</event>" Next strXML += "</events>" End If Return strXML End Function
Again as in the population of the search catalog, you call the GetEvents method to obtain all events for this particular instance of the module. You then loop through the results and generate an XML string, which will be returned by the function. In your user layer, you will implement the method that will then be called based on the user action.
Listing 14-8 looks at how you import the data from the previously generated XML string.
Listing 14-8: The ImportModule Function for the EventsController Class
Public Sub ImportModule(ByVal ModuleID As Integer, ByVal Content As String, _ ByVal Version As String, ByVal UserId As Integer) _ Implements Entities.Modules.IPortable.ImportModule Dim xmlEvent As XmlNode Dim xmlEvents As XmlNode = GetContent(Content, "events") For Each xmlEvent In xmlEvents.SelectNodes("event") Dim objEvent As New EventInfo objEvent.ModuleId = ModuleID objEvent.Description = xmlEvent.Item("description").InnerText objEvent.DateTime = Date.Parse(xmlEvent.Item("datetime").InnerText) objEvent.Title = xmlEvent.Item("title").InnerText objEvent.CreatedByUser = UserId.ToString AddEvent(objEvent) Next End Sub
As you can see in Listing 14-8, the XML generated by the ExportModule routine in Listing 14-7 is processed. This time, you call the AddEvent method of the EventController to populate an event for an element in the XML file.