Введение в технологии создания Интернет-узлов

Разработка модулей для DotNetNuke в Visual Studio 2005

Разбить на страницы
Показывать лекцию целиком

Теоретическое введение

Архитектура модулей DNN

Архитектура модулей DNN традиционно представляется в виде рис. 15.1.

(рис 15.1) Архитектура модулей DNN

Компоненты этой архитектуры соответствуют стандартной трехуровневой архитектурной модели приложений:

  • Presentation Layer (UI - User Interface) - уровень представления, пользовательский интерфейс. Предназначен для взаимодействия с пользователем - отображения информации и элементов управления.
  • Business Logic Layer (BLL) - уровень бизнес-логики, на котором размещается код, реализующий функциональность модуля.
  • Data Access Layer (DAL) - уровень доступа к данным, реализующий взаимодействие с источниками данных, используемыми уровнем бизнес-логики. Он состоит из Abstract Data Provider - Абстрактного провайдера данных, или нескольких Concrete Providers - Конкретных провайдеров, а также опциональных Data Access Application Blocks - Блоков доступа к данным приложения.
  • Структура модуля DNN

    Рассмотрим структуру типового модуля DNN на примере модуля Survey. Код модуля, соответствующий уровню представления (UI) и отвечающий за взаимодействие с пользователем, находится в каталоге DesktopModules\Survey (рис. 15.2).

    (рис 15.2) Код, соответствующий уровню представления

    Код, относящийся к уровням бизнес-логики (BLL) и доступа к данным (DAL) размещаются в каталоге App_Code.

    Создание модулей DNN в Visual Studio 2005

    Для создания новых модулей DNN оптимальным инструментом является Microsoft Visual Studio 2005. Модули, реализованные с помощью Visual Studio 2005, используют .NET Framework 2.0, и предназначены для DNN версии 4.0 и старше.

    В состав Visual Studio 2005 входит web-сервер Cassini, с помощью которого можно тестировать созданные страницы сайта, без необходимости настройки IIS.

    Для Visual Studio разработаны специальные программные дополнения - Starter Kits. Starter Kit встраивается в VS 2005. Starter Kits выполняет несколько специализированных функций, связанных с разработкой модуля, используя SDK и VS-шаблоны.

    Существует версия дистрибутива DotNetNuke, созданная в виде Starter Kit, чтобы программистам было легче ознакомится со структурой DNN. DNN Starter Kit можно загрузить с www.dotnetnuke.com/tabid/125/default.aspx.

    Практические задания

    Установка DotNetNuke Starter Kit

    В Visual Studio 2005 выберите пункт главного меню File | Open | File и выберите файл DotNetNuke_4.x_StarterKit.vsi. Откроется окно выбора устанавливаемых компонентов DNN Starter Kit (рис. 15.3).

    (рис 15.3) Окно выбора устанавливаемых компонентов DNN Starter Kit

    Следует оставить выделенными все компоненты. Далее появляется предупреждение о том, что у устанавливаемого Starter Kit отсутствует цифровая подпись (рис. 15.4).

    (рис 15.4) Предупреждение об отсутствии цифровой подписи

    Следует нажать кнопку Yes, и в окне с перечнем компонентов, подлежащих установке (рис. 15.5) нажать Finish.

    (рис 15.5) Перечень устанавливаемых компонентов

    В результате Starter Kit будет установлен.

    Установка DNN с использованием Starter Kit

    Для установки DNN с использованием Starter Kit следует запустить Visual Studio и выбрать пункт главного меню New | Web Site. Откроется диалоговое окно New web Site Templates (рис. 15.6).

    (рис 15.6) Выбор типа создаваемого сайта

    Выберите тип проекта DNN Web Application Framework. Будет создано web-приложение, содержащее все файлы, необходимые для установки DNN с использованием БД под управлением СУБД MS SQL Server Express.

    Далее следует нажать комбинацию клавиш Ctrl+F5, чтобы запустить процесс установки без включения режима отладки. Далее процедура установки аналогична описанной выше.

    Функции создаваемого модуля

    В данной лабораторной работе будет создан модуль GuestBook - "Гостевая книга", поскольку это позволит осветить большинство функций - выбор, обновление, удаление и вставку. Будет показано, как связать элемент управления GridView с источником данных, используя уровень доступа к данным (DAL).

    Создание нового модуля

    В окне Solution Explorer щелкните в корневом каталоге - это будет местом, в котором будет создаваться новый модуль. В главном меню выберите пункт File | New File.

    (рис 15.7) Выбор типа создаваемого модуля

    Следует выбрать шаблон DotNetNuke Module, переименовать модуль в GuestBook и нажать кнопку Add. Будет создана структура модуля (рис. 15.8).

    (рис 15.8) Структура файлов модуля

    Переименование каталогов модуля

    Кроме того, в главное окно Visual Studio будет загружен документ, указывающий, какие шаги необходимо сделать далее (рис. 15.9).

    (рис 15.9) Инструкция о выполнении дальнейших шагов при создании модуля

    Необходимо переименовать каталог /App_Code/ModuleName в /App_Code/GuestBook и каталог /DesktopModules/ModuleName в /DesktopModules/GuestBook.

    Далее в главном меню Visual Studio следует выбрать пункт Build | Build Web Site. Процедура должна пройти без ошибок.

    Указание страницы "по умолчанию"

    На следующем этапе необходимо указать, какая из страниц сайта будет использоваться в том случае, если пользователь обратится к сайту без указания имени страницы, то есть выбрать страницу "по умолчанию". Для этого в окне Solution Explorer следует щелкнуть правой кнопкой мыши по странице Default.aspx и в контекстном меню выбрать пункт Set as Start Page (рис. 15.10).

    (рис 15.10) Выбор страницы "по умолчанию"

    Создание поставщика данных

    Далее следует запустить проект в режиме "без отладки", нажав Ctrl+F5. Откроется стартовая страница портала (рис. 15.11).

    (рис 15.11) Стартовая страница портала

    Необходимо пройти аутентификацию под именем пользователя host. Пароль, используемый по умолчанию для этого пользователя - dnnhost.

    Далее следует выбрать пункт меню портала Host | SQL (рис. 15.12).

    (рис 15.12) Меню портала

    Откроется одноименная страница (рис. 15.13).

    (рис 15.13) Страница SQL

    Далее необходимо переключиться в Visual Studio и открыть файл DestopModules/GuestBook/ 01.00.00.SqlDataProvider (рис. 15.14).

    (рис 15.14) SQL-Скрипт для создания поставщика данных

    В данном файле хранится SQL-скрипт, предназначенный для создания поставщика данных для модуля GuestBook. Этот файл был автоматически создан при создании нового пустого модуля. Необходимо скопировать его содержимое в буфер обмена и вставить на страницу SQL в DNN (рис. 15.15).

    (рис 15.15) Страница SQL со вставленным SQL-скриптом

    Следует установить флажок "Run as Script" и выбрать ссылку Execute.

    Создание определения модуля

    Из меню портала следует выбрать пункт Host | Module Definitions. Далее необходимо нажать треугольную стрелку в левой верхней части страницы и их контекстного меню выбрать пункт Add New Module Definition (рис. 15.16).

    (рис 15.16) Меню страницы Module Definitions

    Откроется страница Edit Module Definitions (рис. 15.17). В раскрывающемся списке Module Manifest следует выбрать пункт GuestBook.dnn и нажать ссылку Install.

    (рис 15.17) Страница Edit Module Definitions

    Далее следует нажать кнопку Add в группе Page Functions панели инструментов DNN (рис. 15.18).

    (рис 15.18) Панель инструментов DNN

    На появившейся странице в поля ввода Page Name, Page Title и Description следует ввести "Guest Book", а также установить флажок в столбце View Page и строке All Users (рис. 15.19), после чего нажать ссылку Update.

    (рис 15.19) Страница Page Management

    В результате появится созданный модуль (рис. 15.20).

    (рис 15.20) Модуль GuestBook

    Структура файлов и каталогов созданного шаблона модуля

    За просмотр гостевой книги отвечает элемент управления ViewGuestBook.ascx, относящийся к уровню представления. Этот элемент управления загружается, когда ядро DNN отображает модуль GuestBook. Ассоциированный с ним файл ViewGuestBook.ascx.vb содержит следующий код:

    Dim objGuestBooks As New GuestBookController
    Dim colGuestBooks As List(Of GuestBookInfo)
    ' get the content from the GuestBook table
    colGuestBooks = objGuestBooks.GetGuestBooks(ModuleId)

    Этот код ссылается на файл GuestBookController, определенный в файле GuestBookController.vb, относящемуся к уровню бизнес-логики. Этот файл содержит следующий код:

    Public Function GetGuestBooks(ByVal ModuleId As Integer) As List(Of GuestBookInfo)
    Return CBO.FillCollection(Of GuestBookInfo)(DataProvider.Instance().GetGuestBooks(ModuleId))
    End Function

    В свою очередь, этот код ссылается на класс GuestBookInfo, содержащийся в файле GuestBookInfo.vb, который также относится к уровню бизнес-логики.

    Код

    DataProvider.Instance().GetGuestBooks(ModuleId)

    в классе GuestBookController ссылается на код

    ' return the provider
    Public Shared Shadows Function Instance() As DataProvider
    Return objProvider
    End Function

    в файле DataProvider.vb, который является частью уровня доступа к данным. Файл DataProvider.vb содержит код

    Public MustOverride Function GetGuestBooks(ByVal ModuleId As Integer) As IDataReader

    который ссылается на метод, переопределенный в файле SQLDataProvider.vb этим кодом:

    Public Overrides Function GetGuestBooks(ByVal ModuleId As Integer) As IDataReader
     Return CType(SqlHelper.ExecuteReader(ConnectionString, _ 
                GetFullyQualifiedName("GetGuestBooks"), ModuleId), _ 
                IDataReader)
    End Function

    Этот код использует Data Access Application Blocks и возвращает IDataReader.

    Таким образом, соответствие файлов модуля уровням приведенной модели может быть представлено в виде рис. 15.21.

    (рис 15.21) Соответствие файлов модуля уровням модели

    Этапы реализации уровня доступа к данным

    При создании уровня доступа к данным буду проделаны следующие операции:

  • создана таблица в БД;
  • созданы хранимые процедуры;
  • изменен файл SqlDataProvider.vb, в который будет помещен код, вызывающий хранимые процедуры;
  • изменен файл DataProvider.vb, в который будут добавлены методы (которые переопределяются в файле SqlDataProvider.vb ).
  • Подключение к БД

    Так как в данной лабораторной работе используется СУБД MS SQL Server Express, то подключение уже настроено. Для просмотра текущего подключения следует выбрать пункт главного меню Visual Studio View | Server Explorer. Откроется окно Server Explorer (рис. 15.22).

    (рис 15.22) Компонент Visual Studio Server Explorer

    Удаление демонстрационной таблицы и хранимых процедур

    При создании нового модуля автоматически была создана таблица YourCompany_GuestBook, а также ряд хранимых процедур:

  • YourCompany_AddGuestBook,
  • YourCompany_DeleteGuestBook,
  • YourCompany_GetGuestBook,
  • YourCompany_GetGuestBooks,
  • YourCompany_UpdateGuestBook.
  • Их необходимо удалить.

    Создание таблицы

    Для создания таблицы, в которой будут храниться используемые модулем данные, следует зарегистрироваться на сайте под учетной записью host, и выбрать в меню Host пункт SQL. При помощи открывшейся страницы следует выполнить следующий SQL-скрипт:

    IF EXISTS (SELECT * FROM dbo.sysobjects WHERE 
      id = object_id(N'{databaseOwner}[{objectQualifier}YourCompany_GuestBook]') 
      and OBJECTPROPERTY(id, N'IsTable') = 1)
    
    DROP TABLE {databaseOwner}[{objectQualifier}YourCompany_GuestBook]
    GO
    CREATE TABLE {databaseOwner}[{objectQualifier}YourCompany_GuestBook] (
    [ID] [int] IDENTITY (1, 1) NOT NULL ,
    [ModuleID] [int] NULL ,
    [Name] [nvarchar] (50) NULL ,
    [Email] [nvarchar] (50) NULL ,
    [Message] [nvarchar] (250) NULL ,
    [DateEntered] [datetime] NULL 
    ) ON [PRIMARY]
    
    ALTER TABLE {databaseOwner}[YourCompany_GuestBook] ADD 
    CONSTRAINT [PK_{objectQualifier}YourCompany_GuestBook] PRIMARY KEY CLUSTERED 
    (
    [ID]
    ) ON [PRIMARY]

    В результате будет создана следующая таблица YourCompany_GuestBook (рис. 15.23).

    (рис 15.23) Созданная таблица

    Создание хранимых процедур

    Аналогичным образом следует выполнить следующий SQL-скрипт, создающий хранимые процедуры:

    CREATE PROCEDURE {databaseOwner}[{objectQualifier}YourCompany_GuestBook_Delete] 
    (
    @ID int
    )
    AS
    DELETE FROM {objectQualifier}YourCompany_GuestBook
    WHERE (ID = @ID)
    RETURN
    GO
    
    CREATE PROCEDURE {databaseOwner}[{objectQualifier}YourCompany_GuestBook_GetAll] 
    (
    @ModuleID int 
    )
    AS
    SELECT ID, ModuleID, Name, Email, Message, DateEntered
    FROM {objectQualifier}YourCompany_GuestBook
    WHERE (ModuleID = @ModuleID)
    order by DateEntered DESC
    RETURN
    GO
    
    CREATE PROCEDURE {databaseOwner}[{objectQualifier}YourCompany_GuestBook_Insert] 
    (
    @ModuleID int,
    @Name nvarchar(50),
    @Email nvarchar(50),
    @Message nvarchar(250)
    )
    AS
    INSERT INTO {objectQualifier}YourCompany_GuestBook
    (ModuleID, Name, Email, Message, DateEntered)
    VALUES (@ModuleID,@Name,@Email,@Message,getdate())
    RETURN
    GO
    
    CREATE PROCEDURE {databaseOwner}[{objectQualifier}YourCompany_GuestBook_Update] 
    (
    @ID int,
    @Name nvarchar(50),
    @Email nvarchar(50), 
    @Message nvarchar(250),
    @DateEntered datetime
    )
    AS
    UPDATE {objectQualifier}YourCompany_GuestBook
    SET Name = @Name, Email = @Email, Message = @Message, DateEntered = @DateEntered
    WHERE (ID = @ID)
    RETURN
    GO

    В результате будут созданы хранимые процедуры, отвечающие за удаление записей, отображение всех записей, вставку новой записи и модификацию существующей записи в гостевой книге (рис. 15.24).

    (рис 15.24) Созданные хранимые процедуры

    Модификация файла SqlDataProvider.vb

    Содержимое файла SqlDataprovider.vb следует заменить следующим кодом:

    Imports System
    Imports System.Data
    Imports System.Data.SqlClient
    Imports Microsoft.ApplicationBlocks.Data
    Imports DotNetNuke.Common.Utilities
    Imports DotNetNuke.Framework.Providers
    
    Namespace YourCompany.Modules.GuestBook
    
      Public Class SqlDataProvider
        Inherits DataProvider
    
        Private Const ProviderType As String = "data"
        Private Const ModuleQualifier As String = ""
        Private _providerConfiguration As ProviderConfiguration = _
               ProviderConfiguration.GetProviderConfiguration(ProviderType)
        Private _connectionString As String
        Private _providerPath As String
        Private _objectQualifier As String
        Private _databaseOwner As String
    
        ' <summary>
        ' Constructs new SqlDataProvider instance
        ' </summary>
        Public Sub New()
          MyBase.New()
          'Read the configuration specific information for this provider
          Dim objProvider As Provider = _ 
              CType(_providerConfiguration.Providers(_providerConfiguration.DefaultProvider), Provider)
    
          ' This code handles getting the connection string from either the connectionString / 
          ' appsetting section and uses the connectionstring section by default if it exists. 
          ' Get Connection string from web.config
          _connectionString = Config.GetConnectionString()
    
          ' If above funtion does not return anything then 
          ' connectionString must be set in the dataprovider section.
          If _connectionString = "" Then
            ' Use connection string specified in provider
            _connectionString = objProvider.Attributes("connectionString")
          End If
    
          _objectQualifier = objProvider.Attributes("objectQualifier")
          If ((_objectQualifier <> "") _
          AndAlso (_objectQualifier.EndsWith("_") = False)) Then
            _objectQualifier = (_objectQualifier + "_")
          End If
          _databaseOwner = objProvider.Attributes("databaseOwner")
          If ((_databaseOwner <> "") _
          AndAlso (_databaseOwner.EndsWith(".") = False)) Then
            _databaseOwner = (_databaseOwner + ".")
          End If
        End Sub
    
        ' <summary>
        ' Gets and sets the connection string
        ' </summary>
        Public ReadOnly Property ConnectionString() As String
          Get
            Return _connectionString
          End Get
        End Property
    
        ' <summary>
        ' Gets and sets the Provider path
        ' </summary>
        Public ReadOnly Property ProviderPath() As String
          Get
            Return _providerPath
          End Get
        End Property
    
        ' <summary>
        ' Gets and sets the Object qualifier
        ' </summary>
        Public ReadOnly Property ObjectQualifier() As String
          Get
            Return _objectQualifier
          End Get
        End Property
    
        ' <summary>
        ' Gets and sets the database ownere
        ' </summary>
        Public ReadOnly Property DatabaseOwner() As String
          Get
            Return _databaseOwner
          End Get
        End Property
    
        ' -----------------------------------------------------------------------------
        ' <summary>
        ' Gets the fully qualified name of the stored procedure
        ' </summary>
        ' <param name="name">The name of the stored procedure</param>
        ' <returns>The fully qualified name</returns>
        ' -----------------------------------------------------------------------------
        Private Function GetFullyQualifiedName(ByVal name As String) As String
          Return (DatabaseOwner _
          + (ObjectQualifier _
          + (ModuleQualifier + name)))
        End Function
    
        ' -----------------------------------------------------------------------------
        ' <summary>
        ' Gets the value for the field or DbNull if field has "null" value
        ' </summary>
        ' <param name="Field">The field to evaluate</param>
        ' <returns></returns>
        ' -----------------------------------------------------------------------------
        Private Function GetNull(ByVal Field As Object) As Object
          Return Null.GetNull(Field, DBNull.Value)
        End Function
    
        Public Overrides Sub YourCompany_GuestBook_Insert(ByVal ModuleId As Integer, _
         ByVal Name As String, ByVal Email As String, ByVal Message As String)
          SqlHelper.ExecuteNonQuery(ConnectionString, _
         GetFullyQualifiedName("YourCompany_GuestBook_Insert"), _
         ModuleId, Name, Email, Message)
        End Sub
    
        Public Overrides Sub YourCompany_GuestBook_Delete(ByVal ID As Integer)
          SqlHelper.ExecuteNonQuery(ConnectionString, _
             GetFullyQualifiedName("YourCompany_GuestBook_Delete"), ID)
        End Sub
    
        Public Overrides Function YourCompany_GuestBook_GetAll(ByVal ModuleId As Integer) As IDataReader
          Return CType(SqlHelper.ExecuteReader(ConnectionString, _
            GetFullyQualifiedName("YourCompany_GuestBook_GetAll"), ModuleId), IDataReader)
        End Function
    
        Public Overrides Sub YourCompany_GuestBook_Update(ByVal ID As Integer, ByVal Name As String, _
           ByVal Email As String, ByVal Message As String, ByVal DateEntered As DateTime)
          SqlHelper.ExecuteNonQuery(ConnectionString, _
            GetFullyQualifiedName("YourCompany_GuestBook_Update"), ID, Name, Email, Message, DateEntered)
        End Sub
      End Class
    End Namespace

    Модификация файла DataProvider.vb

    Содержимое файла DataProvider.vb следует заменить следующим кодом:

    Imports System
    Imports DotNetNuke
    Imports System.Data
    Imports DotNetNuke.Framework
    
    Namespace YourCompany.Modules.GuestBook
    
      Public MustInherit Class DataProvider
        ' singleton reference to the instantiated object
        Private Shared objProvider As DataProvider = Nothing
    
        ' constructor
        Shared Sub New()
          CreateProvider()
    
        End Sub
    
        ' dynamically create provider
        Private Shared Sub CreateProvider()
          objProvider = CType(Reflection.CreateObject("data", "YourCompany.Modules.GuestBook", ""), DataProvider)
        End Sub
    
        ' return the provider
        Public Shared Function Instance() As DataProvider
          Return objProvider
        End Function
    
        Public MustOverride Sub YourCompany_GuestBook_Insert(ByVal ModuleId As Integer, _ 
                ByVal Name As String, ByVal Email As String, ByVal Message As String)
        Public MustOverride Function YourCompany_GuestBook_GetAll(ByVal ModuleId As Integer) As IDataReader
        Public MustOverride Sub YourCompany_GuestBook_Update(ByVal ID As Integer, ByVal Name As String, _ 
                ByVal Email As String, ByVal Message As String, ByVal DateEntered As DateTime)
        Public MustOverride Sub YourCompany_GuestBook_Delete(ByVal ID As Integer)
    
      End Class
    
    End Namespace

    Таким образом, создание уровня доступа к данным завершено. Переходим к уровню бизнес-логики.

    Этапы реализации уровня бизнес-логики

    Для построения уровня бизнес-логики буду произведены следующие действия:

  • модифицирован файл GuestBookInfo.vb ;
  • модифицирован файл GuestBookController.vb.
  • Модификация файла GuestBookInfo.vb

    В данном файле будет создан класс, предназначенный для хранения данных, диаграмма которого приведена на рис. 15.25.

    (рис 15.25) Диаграмма класса GuestBookInfo

    Для его реализации замените содержимое файла на следующее:

    Imports System
    Imports System.Configuration
    Imports System.Data
    
    Namespace YourCompany.Modules.GuestBook
    
      Public Class GuestBookInfo
    
        Private _ModuleId As Integer
        Private _ID As Integer
        Private _Name As String
        Private _Email As String
        Private _Message As String
        Private _DateEntered As DateTime
    
        ' 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 Name
        ' </summary>
        Public Property Name() As String
          Get
            Return _Name
          End Get
          Set(ByVal value As String)
            _Name = value
          End Set
        End Property
    
    
        ' <summary>
        ' Gets and sets the Email
        ' </summary>
        Public Property Email() As String
          Get
            Return _Email
          End Get
          Set(ByVal value As String)
            _Email = value
          End Set
        End Property
    
    
        ' <summary>
        ' Gets and sets the Message
        ' </summary>
        Public Property Message() As String
          Get
            Return _Message
          End Get
          Set(ByVal value As String)
            _Message = value
          End Set
        End Property
    
    
        ' <summary>
        ' Gets and sets the DateEntered
        ' </summary>
        Public Property DateEntered() As DateTime
          Get
            Return _DateEntered
          End Get
          Set(ByVal value As DateTime)
            _DateEntered = value
          End Set
        End Property
    
    
      End Class
    End Namespace

    Модификация файла GuestBookController.vb

    Содержимое файла следует заменить следующим кодом:

    Imports System
    Imports System.Collections.Generic
    Imports System.Configuration
    Imports System.ComponentModel
    Imports System.Data
    Imports System.Xml
    Imports System.Web
    Imports DotNetNuke
    Imports DotNetNuke.Common
    Imports DotNetNuke.Common.Utilities
    Imports DotNetNuke.Entities.Modules
    Imports DotNetNuke.Services.Search
    
    
    Namespace YourCompany.Modules.GuestBook
    
      Public Class GuestBookController
    
        <DataObjectMethod(DataObjectMethodType.Insert)> _
        Public Shared Sub GuestBook_Insert(ByVal objTest As GuestBookInfo)
          DataProvider.Instance.YourCompany_GuestBook_Insert(objTest.ModuleId, objTest.Name, 
                    objTest.Email, objTest.Message)
        End Sub
    
        <DataObjectMethod(DataObjectMethodType.Delete)> _
        Public Shared Sub GuestBook_Delete(ByVal objTest As GuestBookInfo)
          DataProvider.Instance.YourCompany_GuestBook_Delete(objTest.ID)
        End Sub
    
        <DataObjectMethod(DataObjectMethodType.Select)> _
        Public Shared Function GuestBook_GetAll(ByVal ModuleId As Integer) As List(Of GuestBookInfo)
          Return CBO.FillCollection(Of GuestBookInfo)(DataProvider.Instance().YourCompany_GuestBook_GetAll(ModuleId))
        End Function
    
        <DataObjectMethod(DataObjectMethodType.Update)> _
        Public Shared Sub GuestBook_Update(ByVal objTest As GuestBookInfo)
          DataProvider.Instance.YourCompany_GuestBook_Update(objTest.ID, objTest.Name, 
                                                      objTest.Email, objTest.Message, objTest.DateEntered)
        End Sub
    
      End Class
    
    
    End Namespace

    Этот код создает класс с четырьмя методами (рис. 15.26):

  • GuestBook_Insert - Добавляет записи в БД. Используется объект GuestBookInfo. Параметры ModuleId, Name, Email, Message передаются методу YourCompany_GuestBook_Insert в файле DataProvider.vb
  • GuestBook_Delete - Удаляет записи из БД. Используется объект GuestBookInfo. Параметр ID передается методу YourCompany_GuestBook_Delete в файле DataProvider.vb.
  • . Используется параметр .
  • . Используется объект GuestBookInfo. Метод открывает объект и передает отдельные параметры ( ID, ModuleId, Name, Email, Message, DateEntered ) методу YourCompany_GuestBook_Update в файле DataProvider.vb ".
  • (рис 15.26) Класс GuestBookController

    Этапы реализации уровня представления

    Для создания уровня представления следует:

  • модифицировать файлы локализации ( *.resx );
  • модифицировать элементы управления и связанные с ними файлы кода ( EditGuestBook.ascx, Settings.ascx, ViewGuestBook.ascx ).
  • Все перечисленные файлы находятся в каталоге /DesktopModules/GuestBook.

    Модификация файлов локализации

    Технология локализации, используемая в DNN, позволяет создавать текстовые метки с возможностью изменения текста при переключении языка. Это достигается путем изменения файла ресурсов, который имеет расширение .resx.

    Откройте файл /DesktopModules/GuestBook/App_LocalResources/EditGuestBook.ascx.resx (рис. 15.27).

    (рис 15.27) Исходное содержимое файла EditGuestBook.ascx.resx.

    Измените содержимое файла таким образом, чтобы оно соответствовало рис. 15.28.

    (рис 15.28) Измененное содержимое файла EditGuestBook.ascx.resx.

    Откройте файл Settings.ascx.resx (рис. 15.29).

    (рис 15.29) Исходное содержимое файла Settings.ascx.resx

    Следует изменить его содержимое таким образом, чтобы оно соответствовало приведенному на рис. 15.30.

    (рис 15.30) Измененное содержимое файла Settings.ascx.resx

    Аналогично, следует заменить содержимое файла ресурсов ViewGuestBook.ascx.resx на следующее (рис. 15.31).

    (рис 15.31) Измененное содержимое файла ViewGuestBook.ascx.resx

    Модификация элементов управления

    Модуль состоит из трех элементов управления:

  • EditGuestBook.ascx и EditGuestBook.ascx.vb
  • Settings.ascx и Settings.ascx.vb
  • ViewGuestBook.ascx и ViewGuestBook.ascx.vb
  • В контекстном меню файла EditGuestBook.ascx выберите пункт View Markup (рис. 15.32).

    (рис 15.32) Контекстное меню файла EditGuestBook.ascx

    Замените код элемента управления на следующий:

    <%@ Control language="VB" Inherits="YourCompany.Modules.GuestBook.EditGuestBook" 
    CodeFile="EditGuestBook.ascx.vb" AutoEventWireup="true"%>
    <%@ Register TagPrefix="dnn" TagName="Label" Src="~/controls/LabelControl.ascx" %>
    <dnn:label id="lblContent" runat="server" controlname="lblContent" 
    suffix=":"></dnn:label>
    nbsp;
    <asp:ObjectDataSource ID="ObjectDataSource_Tasks" runat="server" 
      DataObjectTypeName="YourCompany.Modules.GuestBook.GuestBookInfo"
      DeleteMethod="GuestBook_Delete" InsertMethod="GuestBook_Insert" 
      OldValuesParameterFormatString="original_{0}"
      OnInit="Page_Load" SelectMethod="GuestBook_GetAll" 
      TypeName="YourCompany.Modules.GuestBook.GuestBookController"
      UpdateMethod="GuestBook_Update">
        <SelectParameters>
          <asp:Parameter DefaultValue="00" Name="ModuleId" Type="Int32" />
        </SelectParameters>
    </asp:ObjectDataSource>
    nbsp;
    <asp:GridView ID="GridView1" runat="server" AllowPaging="True" 
      AutoGenerateColumns="False" DataSourceID="ObjectDataSource_Tasks" 
      DataKeyNames="ID">
      <Columns>
        <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
        <asp:BoundField DataField="ID" HeaderText="ID" Visible="False" />
        <asp:BoundField DataField="ModuleID" HeaderText="ModuleID" Visible="False" />
        <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
        <asp:BoundField DataField="Message" HeaderText="Message" SortExpression="Message" />
        <asp:BoundField DataField="Email" HeaderText="Email" />
        <asp:BoundField ApplyFormatInEditMode="True" DataField="DateEntered" 
         DataFormatString="{0:d}"
        HeaderText="Date" HtmlEncode="False" SortExpression="DateEntered" />
      </Columns>
    </asp:GridView> <asp:BoundField ApplyFormatInEditMode="True" DataField="DateEntered" 
     DataFormatString="{0:d}"
     HeaderText="Date" HtmlEncode="False" SortExpression="DateEntered" />
    </Columns>
    </asp:GridView>

    Проделайте аналогичную процедуру с файлом Settings.ascx, заменив его разметку на следующую:

    <%@ Control Language="VB" AutoEventWireup="false" 
       CodeFile="Settings.ascx.vb" Inherits="YourCompany.Modules.GuestBook.Settings" %>
    <%@ Register TagPrefix="dnn" TagName="Label" Src="~/controls/LabelControl.ascx" %>
    
    <dnn:label id="lblshowform" runat="server" controlname="lblshowform" 
      suffix=":"></dnn:label>
    <br />
    <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True" 
      OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
      <asp:ListItem Selected="True">Yes</asp:ListItem>
      <asp:ListItem>No</asp:ListItem>
    </asp:DropDownList>

    То же самое следует проделать с разметкой файла ViewGuestBook.ascx, заменив ее на следующую:

    <%@ Control Language="VB" Inherits="YourCompany.Modules.GuestBook.ViewGuestBook" 
     CodeFile="ViewGuestBook.ascx.vb"
    AutoEventWireup="true" %>
    <%@ Register TagPrefix="dnn" TagName="Label" Src="~/controls/LabelControl.ascx" %>
    <asp:ObjectDataSource ID="ObjectDataSource_Tasks" runat="server" 
      DataObjectTypeName="YourCompany.Modules.GuestBook.GuestBookInfo"
      DeleteMethod="GuestBook_Delete" InsertMethod="GuestBook_Insert" 
      OldValuesParameterFormatString="original_{0}"
      SelectMethod="GuestBook_GetAll" TypeName="YourCompany.Modules.GuestBook.GuestBookController"
      UpdateMethod="GuestBook_Update" OnInit="Page_Load">
      <SelectParameters>
        <asp:Parameter DefaultValue="00" Name="ModuleId" Type="Int32" />
      </SelectParameters>
    </asp:ObjectDataSource>
    nbsp;
    <asp:GridView ID="GridView1" runat="server" DataSourceID="ObjectDataSource_Tasks"
      AutoGenerateColumns="False" AllowPaging="True" HorizontalAlign="Center">
      <Columns>
        <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
        <asp:BoundField DataField="Message" HeaderText="Message" 
          SortExpression="Message" />
        <asp:BoundField ApplyFormatInEditMode="True" DataField="DateEntered" 
          DataFormatString="{0:d}"
      HeaderText="Date" SortExpression="DateEntered" HtmlEncode="False" />
      </Columns>
      <EmptyDataTemplate>
        There are no entries.
      </EmptyDataTemplate>
    </asp:GridView>
    <br />
    <center>
      <dnn:Label ID="lblAddMessage" runat="server" ControlName="lblAddMessage" 
        Suffix=":">
      </dnn:Label>
    </center>
    <br />
    <asp:FormView ID="FormView1" runat="server" DataSourceID="ObjectDataSource_Tasks" 
      DefaultMode="Insert" HorizontalAlign="Center">
      <InsertItemTemplate>
        <table cellpadding="2" cellspacing="5" style="width: 50%" align="center">
          <tr>
            <td align="right" style="width: 4px">
            <asp:Label ID="Label1" runat="server" Text="Name"></asp:Label></td>
            <td style="width: 100px">
            <asp:TextBox ID="NameTextBox" runat="server" 
             Text='<%# Bind("Name") %>' Width="264px"></asp:TextBox></td>
          </tr>
          <tr>
            <td align="right" style="width: 4px; height: 23px">
            <asp:Label ID="Label3" runat="server" Text="Email"></asp:Label></td>
            <td style="width: 100px; height: 23px">
            <asp:TextBox ID="EmailTextBox" runat="server" 
              Text='<%# Bind("Email") %>' Width="264px"></asp:TextBox></td>
          </tr>
          <tr>
            <td align="right" style="width: 4px; height: 21px">
            <asp:Label ID="Label2" runat="server" 
              Text="Message"></asp:Label></td>
            <td style="width: 100px; height: 21px">
            <asp:TextBox ID="MessageTextBox" runat="server" EnableViewState="False" 
            MaxLength="250"         Rows="2" Text='<%# Bind("Message") %>' 
            TextMode="MultiLine" Width="264px"></asp:TextBox></td>
          </tr>
          <tr>
            <td align="right" colspan="2" style="height: 21px">
            <asp:Button ID="InsertButton" runat="server" Text="Submit" 
             CommandName="Insert" /></td>
          </tr>
        </table>
        <br />
        nbsp;
      </InsertItemTemplate>
    </asp:FormView>

    Далее следует в контекстном меню файла EditGuestBook.ascx выбрать пункт View Code (рис. 15.33).

    (рис 15.33) Контекстное меню файла EditGuestBook.ascx

    Открывшийся код следует заменить на следующий:

    Imports DotNetNuke
    Imports System.Web.UI
    Imports System.Collections.Generic
    Imports System.Reflection
    Imports DotNetNuke.Entities.Modules
    
    Namespace YourCompany.Modules.GuestBook
      Partial Class EditGuestBook
        Inherits PortalModuleBase
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
          Try
          Catch exc As Exception
            Exceptions.ProcessModuleLoadException(Me, exc)
          End Try
        End Sub
    
        Protected Sub SetModuleId(ByVal sender As Object, 
        ByVal e As System.Web.UI.WebControls.ObjectDataSourceSelectingEventArgs) _
                Handles ObjectDataSource_Tasks.Selecting
          e.InputParameters("ModuleId") = ModuleId.ToString
        End Sub
      End Class
    End Namespace

    Код файла Settings.ascx необходимо заменить на следующий:

    Imports System
    Imports System.Web.UI
    Imports DotNetNuke
    Imports DotNetNuke.Entities.Modules
    Imports DotNetNuke.Services.Exceptions
    Namespace YourCompany.Modules.GuestBook
      Partial Class Settings
        Inherits ModuleSettingsBase
        Public Overrides Sub LoadSettings()
          Try
            If (Page.IsPostBack = False) Then
              If (Not (CType(TabModuleSettings("showform"), String)) Is Nothing) Then
                Me.DropDownList1.SelectedValue = CType(TabModuleSettings("showform"), String)
              End If
            End If
          Catch exc As Exception
            Exceptions.ProcessModuleLoadException(Me, exc)
          End Try
        End Sub
    
        Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
          Dim objModules As ModuleController = New ModuleController
          If (Me.DropDownList1.SelectedValue = "Yes") Then
            objModules.UpdateTabModuleSetting(TabModuleId, "showform", "Yes")
          Else
            objModules.UpdateTabModuleSetting(TabModuleId, "showform", "No")
          End If
        End Sub
      End Class
    End Namespace

    Аналогично ниже приведен код для файла ViewGuestBook.ascx:

    Imports DotNetNuke
    Imports System.Web.UI
    Imports System.Collections.Generic
    Imports System.Reflection
    Imports DotNetNuke.Entities.Modules
    Namespace YourCompany.Modules.GuestBook
      Partial Class ViewGuestBook
        Inherits Entities.Modules.PortalModuleBase
        Implements Entities.Modules.IActionable
        Public ReadOnly Property ModuleActions() As Entities.Modules.Actions.ModuleActionCollection _
                                              Implements Entities.Modules.IActionable.ModuleActions
          Get
            Dim Actions As New Entities.Modules.Actions.ModuleActionCollection
            Actions.Add(GetNextActionID, _
                Localization.GetString(Entities.Modules.Actions.ModuleActionType.EditContent, 
                LocalResourceFile), 
                Entities.Modules.Actions.ModuleActionType.EditContent, 
                "", "", EditUrl(), False, Security.SecurityAccessLevel.Edit, True, False)
            Return Actions
          End Get
        End Property
    
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
          Try
            Dim objModules As ModuleController = New ModuleController
            If Not Page.IsPostBack Then
              If (Not (CType(Settings("showform"), String)) Is Nothing) Then
                If (CType(Settings("showform"), String) = "No") Then
                  ' Do not allow messages to be added
                  FormView1.Visible = False
                  lblAddMessage.Visible = False
                End If
              End If
            Else
              Me.GridView1.DataBind()
            End If
          Catch ex As Exception
            Exceptions.ProcessModuleLoadException(Me, ex)
          End Try
        End Sub
    
        Protected Sub NewItem(ByVal sender As Object, _
                  ByVal e As System.Web.UI.WebControls.FormViewInsertEventArgs) _
                  Handles FormView1.ItemInserting
          e.Values.Item("ID") = 0
          e.Values.Item("ModuleId") = ModuleId.ToString()
          e.Values.Item("DateEntered") = DateTime.Now.ToShortDateString
        End Sub
    
        Protected Sub SetModuleID(ByVal sender As Object, _
                  ByVal e As System.Web.UI.WebControls.ObjectDataSourceSelectingEventArgs) _
                  Handles ObjectDataSource_Tasks.Selecting
          e.InputParameters("ModuleId") = ModuleId.ToString
        End Sub
      End Class
    End Namespace

    Тестирование созданного модуля

    После того, как все три уровня модуля разработаны, следует выбрать пункт главного меню Visual Studio Build | Build Web Site. Компиляция должна пройти без ошибок.

    После компиляции следует запустить проект, и в меню DNN выбрать страницу Guest Book. Появится созданный модуль (рис. 15.34).

    (рис 15.34) Созданный модуль GuestBook

    Использование объектных источников данных в DNN

    Рассмотрим в качестве примера метод GuestBook_Update. Он вызывается элементом управления EditGuestBook.ascx. В этом элементе управления присутствует следующий код для связи с объектным источником данных:

    <asp:ObjectDataSource ID="ObjectDataSource_Tasks" runat="server" 
      DataObjectTypeName="YourCompany.Modules.GuestBook.GuestBookInfo"
      DeleteMethod="GuestBook_Delete" InsertMethod="GuestBook_Insert" 
      OldValuesParameterFormatString="original_{0}"
      OnInit="Page_Load" SelectMethod="GuestBook_GetAll" 
      TypeName="YourCompany.Modules.GuestBook.GuestBookController"
      UpdateMethod="GuestBook_Update">
        <SelectParameters>
          <asp:Parameter DefaultValue="00" Name="ModuleId" Type="Int32" />
        </SelectParameters>
    </asp:ObjectDataSource>

    GridView, который пользователь использует для ввода и получения данных, связан с этим элементом управления.

    Обратите внимание на фрагмент

    DataObjectTypeName="YourCompany.Modules.GuestBook.GuestBookInfo.

    В нем указывается объектный источник данных - объект GuestBookInfo, который будет использоваться для передачи параметров (рис. 15.35).

    (рис 15.35) Объект GuestBookInfo

    Этот объект представляет собой обычный класс. Если необходимо иметь полный контроль над параметрами, необходимо добавить бизнес-логику. Эта функция является преимуществом объектных источников данным перед элементами управления, связанными с SQL-данными. Кроме того, это позволяет строить решения, полностью соответствующий n-уровневой архитектуре, полностью контролирующие данные на каждом из уровней.

    Теперь обратите внимание на фрагмент

    TypeName="YourCompany.Modules.GuestBook.GuestBookController

    Он указывает на класс GuestBookController (рис. 15.36), реализующий методы выборки ( Select ), обновления ( Update ), вставки ( Insert ) и удаления ( Delete ).

    (рис 15.36) Класс GuestBookController

    Далее, обратите внимание на фрагмент UpdateMethod="GuestBook_Update

    Он указывает, что метод GuestBook_Update класса GuestBookController является обработчиком события Update. В GridView, когда пользователь нажимает ссылку Update, происходят следующие действия. Поскольку GridView связан с объектным источником данных, объектный источник данных передает параметры из GridView в объект GuestBookInfo и вызывает метод GuestBook_Update класса GuestBookController:

    <DataObjectMethod(DataObjectMethodType.Update)> _
        Public Shared Sub GuestBook_Update(ByVal objTest As GuestBookInfo)
          DataProvider.Instance.YourCompany_GuestBook_Update(objTest.ID, objTest.Name, _
                                  objTest.Email, objTest.Message, objTest.DateEntered)
        End Sub

    Этот метод получает класс GuestBookInfo и передает каждый параметр уроню доступа к данным. Объект GuestBookInfo используется для каждого метода в классе GuestBookController, за исключением метода Select:

    <DataObjectMethod(DataObjectMethodType.Select)> _
        Public Shared Function GuestBook_GetAll(ByVal ModuleId As Integer) As List(Of GuestBookInfo)
          Return CBO.FillCollection(Of GuestBookInfo)(DataProvider.Instance().YourCompany_GuestBook_GetAll(ModuleId))
        End Function

    Этот метод получает параметр ModuleId и возвращает объект GuestBookInfo.

    Контрольные вопросы

  • Опишите архитектуру модулей DNN. Из каких уровней она состоит?
  • Какие функции выполняет каждый их уровней модели модулей DNN?
  • В каких каталогах размещаются компоненты модуля?
  • Какой инструмент оптимально использовать для создания модулей DNN?
  • Страницы:

    Теоретическое введение

    Архитектура модулей DNN

    Архитектура модулей DNN традиционно представляется в виде рис. 15.1.

    (рис 15.1) Архитектура модулей DNN

    Компоненты этой архитектуры соответствуют стандартной трехуровневой архитектурной модели приложений:

  • Presentation Layer (UI - User Interface) - уровень представления, пользовательский интерфейс. Предназначен для взаимодействия с пользователем - отображения информации и элементов управления.
  • Business Logic Layer (BLL) - уровень бизнес-логики, на котором размещается код, реализующий функциональность модуля.
  • Data Access Layer (DAL) - уровень доступа к данным, реализующий взаимодействие с источниками данных, используемыми уровнем бизнес-логики. Он состоит из Abstract Data Provider - Абстрактного провайдера данных, или нескольких Concrete Providers - Конкретных провайдеров, а также опциональных Data Access Application Blocks - Блоков доступа к данным приложения.
  • Структура модуля DNN

    Рассмотрим структуру типового модуля DNN на примере модуля Survey. Код модуля, соответствующий уровню представления (UI) и отвечающий за взаимодействие с пользователем, находится в каталоге DesktopModules\Survey (рис. 15.2).

    (рис 15.2) Код, соответствующий уровню представления

    Код, относящийся к уровням бизнес-логики (BLL) и доступа к данным (DAL) размещаются в каталоге App_Code.

    Создание модулей DNN в Visual Studio 2005

    Для создания новых модулей DNN оптимальным инструментом является Microsoft Visual Studio 2005. Модули, реализованные с помощью Visual Studio 2005, используют .NET Framework 2.0, и предназначены для DNN версии 4.0 и старше.

    В состав Visual Studio 2005 входит web-сервер Cassini, с помощью которого можно тестировать созданные страницы сайта, без необходимости настройки IIS.

    Для Visual Studio разработаны специальные программные дополнения - Starter Kits. Starter Kit встраивается в VS 2005. Starter Kits выполняет несколько специализированных функций, связанных с разработкой модуля, используя SDK и VS-шаблоны.

    Существует версия дистрибутива DotNetNuke, созданная в виде Starter Kit, чтобы программистам было легче ознакомится со структурой DNN. DNN Starter Kit можно загрузить с www.dotnetnuke.com/tabid/125/default.aspx.

    Практические задания

    Установка DotNetNuke Starter Kit

    В Visual Studio 2005 выберите пункт главного меню File | Open | File и выберите файл DotNetNuke_4.x_StarterKit.vsi. Откроется окно выбора устанавливаемых компонентов DNN Starter Kit (рис. 15.3).

    (рис 15.3) Окно выбора устанавливаемых компонентов DNN Starter Kit

    Следует оставить выделенными все компоненты. Далее появляется предупреждение о том, что у устанавливаемого Starter Kit отсутствует цифровая подпись (рис. 15.4).

    (рис 15.4) Предупреждение об отсутствии цифровой подписи

    Следует нажать кнопку Yes, и в окне с перечнем компонентов, подлежащих установке (рис. 15.5) нажать Finish.

    (рис 15.5) Перечень устанавливаемых компонентов

    В результате Starter Kit будет установлен.

    Установка DNN с использованием Starter Kit

    Для установки DNN с использованием Starter Kit следует запустить Visual Studio и выбрать пункт главного меню New | Web Site. Откроется диалоговое окно New web Site Templates (рис. 15.6).

    (рис 15.6) Выбор типа создаваемого сайта

    Выберите тип проекта DNN Web Application Framework. Будет создано web-приложение, содержащее все файлы, необходимые для установки DNN с использованием БД под управлением СУБД MS SQL Server Express.

    Далее следует нажать комбинацию клавиш Ctrl+F5, чтобы запустить процесс установки без включения режима отладки. Далее процедура установки аналогична описанной выше.

    Функции создаваемого модуля

    В данной лабораторной работе будет создан модуль GuestBook - "Гостевая книга", поскольку это позволит осветить большинство функций - выбор, обновление, удаление и вставку. Будет показано, как связать элемент управления GridView с источником данных, используя уровень доступа к данным (DAL).

    Создание нового модуля

    В окне Solution Explorer щелкните в корневом каталоге - это будет местом, в котором будет создаваться новый модуль. В главном меню выберите пункт File | New File.

    (рис 15.7) Выбор типа создаваемого модуля

    Следует выбрать шаблон DotNetNuke Module, переименовать модуль в GuestBook и нажать кнопку Add. Будет создана структура модуля (рис. 15.8).

    (рис 15.8) Структура файлов модуля

    Переименование каталогов модуля

    Кроме того, в главное окно Visual Studio будет загружен документ, указывающий, какие шаги необходимо сделать далее (рис. 15.9).

    (рис 15.9) Инструкция о выполнении дальнейших шагов при создании модуля

    Необходимо переименовать каталог /App_Code/ModuleName в /App_Code/GuestBook и каталог /DesktopModules/ModuleName в /DesktopModules/GuestBook.

    Далее в главном меню Visual Studio следует выбрать пункт Build | Build Web Site. Процедура должна пройти без ошибок.

    Указание страницы "по умолчанию"

    На следующем этапе необходимо указать, какая из страниц сайта будет использоваться в том случае, если пользователь обратится к сайту без указания имени страницы, то есть выбрать страницу "по умолчанию". Для этого в окне Solution Explorer следует щелкнуть правой кнопкой мыши по странице Default.aspx и в контекстном меню выбрать пункт Set as Start Page (рис. 15.10).

    (рис 15.10) Выбор страницы "по умолчанию"

    Создание поставщика данных

    Далее следует запустить проект в режиме "без отладки", нажав Ctrl+F5. Откроется стартовая страница портала (рис. 15.11).

    (рис 15.11) Стартовая страница портала

    Необходимо пройти аутентификацию под именем пользователя host. Пароль, используемый по умолчанию для этого пользователя - dnnhost.

    Далее следует выбрать пункт меню портала Host | SQL (рис. 15.12).

    (рис 15.12) Меню портала

    Откроется одноименная страница (рис. 15.13).

    (рис 15.13) Страница SQL

    Далее необходимо переключиться в Visual Studio и открыть файл DestopModules/GuestBook/ 01.00.00.SqlDataProvider (рис. 15.14).

    (рис 15.14) SQL-Скрипт для создания поставщика данных

    В данном файле хранится SQL-скрипт, предназначенный для создания поставщика данных для модуля GuestBook. Этот файл был автоматически создан при создании нового пустого модуля. Необходимо скопировать его содержимое в буфер обмена и вставить на страницу SQL в DNN (рис. 15.15).

    (рис 15.15) Страница SQL со вставленным SQL-скриптом

    Следует установить флажок "Run as Script" и выбрать ссылку Execute.

    Создание определения модуля

    Из меню портала следует выбрать пункт Host | Module Definitions. Далее необходимо нажать треугольную стрелку в левой верхней части страницы и их контекстного меню выбрать пункт Add New Module Definition (рис. 15.16).

    (рис 15.16) Меню страницы Module Definitions

    Откроется страница Edit Module Definitions (рис. 15.17). В раскрывающемся списке Module Manifest следует выбрать пункт GuestBook.dnn и нажать ссылку Install.

    (рис 15.17) Страница Edit Module Definitions

    Далее следует нажать кнопку Add в группе Page Functions панели инструментов DNN (рис. 15.18).

    (рис 15.18) Панель инструментов DNN

    На появившейся странице в поля ввода Page Name, Page Title и Description следует ввести "Guest Book", а также установить флажок в столбце View Page и строке All Users (рис. 15.19), после чего нажать ссылку Update.

    (рис 15.19) Страница Page Management

    В результате появится созданный модуль (рис. 15.20).

    (рис 15.20) Модуль GuestBook

    Структура файлов и каталогов созданного шаблона модуля

    За просмотр гостевой книги отвечает элемент управления ViewGuestBook.ascx, относящийся к уровню представления. Этот элемент управления загружается, когда ядро DNN отображает модуль GuestBook. Ассоциированный с ним файл ViewGuestBook.ascx.vb содержит следующий код:

    Dim objGuestBooks As New GuestBookController
    Dim colGuestBooks As List(Of GuestBookInfo)
    ' get the content from the GuestBook table
    colGuestBooks = objGuestBooks.GetGuestBooks(ModuleId)

    Этот код ссылается на файл GuestBookController, определенный в файле GuestBookController.vb, относящемуся к уровню бизнес-логики. Этот файл содержит следующий код:

    Public Function GetGuestBooks(ByVal ModuleId As Integer) As List(Of GuestBookInfo)
    Return CBO.FillCollection(Of GuestBookInfo)(DataProvider.Instance().GetGuestBooks(ModuleId))
    End Function

    В свою очередь, этот код ссылается на класс GuestBookInfo, содержащийся в файле GuestBookInfo.vb, который также относится к уровню бизнес-логики.

    Код

    DataProvider.Instance().GetGuestBooks(ModuleId)

    в классе GuestBookController ссылается на код

    ' return the provider
    Public Shared Shadows Function Instance() As DataProvider
    Return objProvider
    End Function

    в файле DataProvider.vb, который является частью уровня доступа к данным. Файл DataProvider.vb содержит код

    Public MustOverride Function GetGuestBooks(ByVal ModuleId As Integer) As IDataReader

    который ссылается на метод, переопределенный в файле SQLDataProvider.vb этим кодом:

    Public Overrides Function GetGuestBooks(ByVal ModuleId As Integer) As IDataReader
     Return CType(SqlHelper.ExecuteReader(ConnectionString, _ 
                GetFullyQualifiedName("GetGuestBooks"), ModuleId), _ 
                IDataReader)
    End Function

    Этот код использует Data Access Application Blocks и возвращает IDataReader.

    Таким образом, соответствие файлов модуля уровням приведенной модели может быть представлено в виде рис. 15.21.

    (рис 15.21) Соответствие файлов модуля уровням модели

    Этапы реализации уровня доступа к данным

    При создании уровня доступа к данным буду проделаны следующие операции:

  • создана таблица в БД;
  • созданы хранимые процедуры;
  • изменен файл SqlDataProvider.vb, в который будет помещен код, вызывающий хранимые процедуры;
  • изменен файл DataProvider.vb, в который будут добавлены методы (которые переопределяются в файле SqlDataProvider.vb ).
  • Подключение к БД

    Так как в данной лабораторной работе используется СУБД MS SQL Server Express, то подключение уже настроено. Для просмотра текущего подключения следует выбрать пункт главного меню Visual Studio View | Server Explorer. Откроется окно Server Explorer (рис. 15.22).

    (рис 15.22) Компонент Visual Studio Server Explorer

    Удаление демонстрационной таблицы и хранимых процедур

    При создании нового модуля автоматически была создана таблица YourCompany_GuestBook, а также ряд хранимых процедур:

  • YourCompany_AddGuestBook,
  • YourCompany_DeleteGuestBook,
  • YourCompany_GetGuestBook,
  • YourCompany_GetGuestBooks,
  • YourCompany_UpdateGuestBook.
  • Их необходимо удалить.

    Создание таблицы

    Для создания таблицы, в которой будут храниться используемые модулем данные, следует зарегистрироваться на сайте под учетной записью host, и выбрать в меню Host пункт SQL. При помощи открывшейся страницы следует выполнить следующий SQL-скрипт:

    IF EXISTS (SELECT * FROM dbo.sysobjects WHERE 
      id = object_id(N'{databaseOwner}[{objectQualifier}YourCompany_GuestBook]') 
      and OBJECTPROPERTY(id, N'IsTable') = 1)
    
    DROP TABLE {databaseOwner}[{objectQualifier}YourCompany_GuestBook]
    GO
    CREATE TABLE {databaseOwner}[{objectQualifier}YourCompany_GuestBook] (
    [ID] [int] IDENTITY (1, 1) NOT NULL ,
    [ModuleID] [int] NULL ,
    [Name] [nvarchar] (50) NULL ,
    [Email] [nvarchar] (50) NULL ,
    [Message] [nvarchar] (250) NULL ,
    [DateEntered] [datetime] NULL 
    ) ON [PRIMARY]
    
    ALTER TABLE {databaseOwner}[YourCompany_GuestBook] ADD 
    CONSTRAINT [PK_{objectQualifier}YourCompany_GuestBook] PRIMARY KEY CLUSTERED 
    (
    [ID]
    ) ON [PRIMARY]

    В результате будет создана следующая таблица YourCompany_GuestBook (рис. 15.23).

    (рис 15.23) Созданная таблица

    Создание хранимых процедур

    Аналогичным образом следует выполнить следующий SQL-скрипт, создающий хранимые процедуры:

    CREATE PROCEDURE {databaseOwner}[{objectQualifier}YourCompany_GuestBook_Delete] 
    (
    @ID int
    )
    AS
    DELETE FROM {objectQualifier}YourCompany_GuestBook
    WHERE (ID = @ID)
    RETURN
    GO
    
    CREATE PROCEDURE {databaseOwner}[{objectQualifier}YourCompany_GuestBook_GetAll] 
    (
    @ModuleID int 
    )
    AS
    SELECT ID, ModuleID, Name, Email, Message, DateEntered
    FROM {objectQualifier}YourCompany_GuestBook
    WHERE (ModuleID = @ModuleID)
    order by DateEntered DESC
    RETURN
    GO
    
    CREATE PROCEDURE {databaseOwner}[{objectQualifier}YourCompany_GuestBook_Insert] 
    (
    @ModuleID int,
    @Name nvarchar(50),
    @Email nvarchar(50),
    @Message nvarchar(250)
    )
    AS
    INSERT INTO {objectQualifier}YourCompany_GuestBook
    (ModuleID, Name, Email, Message, DateEntered)
    VALUES (@ModuleID,@Name,@Email,@Message,getdate())
    RETURN
    GO
    
    CREATE PROCEDURE {databaseOwner}[{objectQualifier}YourCompany_GuestBook_Update] 
    (
    @ID int,
    @Name nvarchar(50),
    @Email nvarchar(50), 
    @Message nvarchar(250),
    @DateEntered datetime
    )
    AS
    UPDATE {objectQualifier}YourCompany_GuestBook
    SET Name = @Name, Email = @Email, Message = @Message, DateEntered = @DateEntered
    WHERE (ID = @ID)
    RETURN
    GO

    В результате будут созданы хранимые процедуры, отвечающие за удаление записей, отображение всех записей, вставку новой записи и модификацию существующей записи в гостевой книге (рис. 15.24).

    (рис 15.24) Созданные хранимые процедуры

    Модификация файла SqlDataProvider.vb

    Содержимое файла SqlDataprovider.vb следует заменить следующим кодом:

    Imports System
    Imports System.Data
    Imports System.Data.SqlClient
    Imports Microsoft.ApplicationBlocks.Data
    Imports DotNetNuke.Common.Utilities
    Imports DotNetNuke.Framework.Providers
    
    Namespace YourCompany.Modules.GuestBook
    
      Public Class SqlDataProvider
        Inherits DataProvider
    
        Private Const ProviderType As String = "data"
        Private Const ModuleQualifier As String = ""
        Private _providerConfiguration As ProviderConfiguration = _
               ProviderConfiguration.GetProviderConfiguration(ProviderType)
        Private _connectionString As String
        Private _providerPath As String
        Private _objectQualifier As String
        Private _databaseOwner As String
    
        ' <summary>
        ' Constructs new SqlDataProvider instance
        ' </summary>
        Public Sub New()
          MyBase.New()
          'Read the configuration specific information for this provider
          Dim objProvider As Provider = _ 
              CType(_providerConfiguration.Providers(_providerConfiguration.DefaultProvider), Provider)
    
          ' This code handles getting the connection string from either the connectionString / 
          ' appsetting section and uses the connectionstring section by default if it exists. 
          ' Get Connection string from web.config
          _connectionString = Config.GetConnectionString()
    
          ' If above funtion does not return anything then 
          ' connectionString must be set in the dataprovider section.
          If _connectionString = "" Then
            ' Use connection string specified in provider
            _connectionString = objProvider.Attributes("connectionString")
          End If
    
          _objectQualifier = objProvider.Attributes("objectQualifier")
          If ((_objectQualifier <> "") _
          AndAlso (_objectQualifier.EndsWith("_") = False)) Then
            _objectQualifier = (_objectQualifier + "_")
          End If
          _databaseOwner = objProvider.Attributes("databaseOwner")
          If ((_databaseOwner <> "") _
          AndAlso (_databaseOwner.EndsWith(".") = False)) Then
            _databaseOwner = (_databaseOwner + ".")
          End If
        End Sub
    
        ' <summary>
        ' Gets and sets the connection string
        ' </summary>
        Public ReadOnly Property ConnectionString() As String
          Get
            Return _connectionString
          End Get
        End Property
    
        ' <summary>
        ' Gets and sets the Provider path
        ' </summary>
        Public ReadOnly Property ProviderPath() As String
          Get
            Return _providerPath
          End Get
        End Property
    
        ' <summary>
        ' Gets and sets the Object qualifier
        ' </summary>
        Public ReadOnly Property ObjectQualifier() As String
          Get
            Return _objectQualifier
          End Get
        End Property
    
        ' <summary>
        ' Gets and sets the database ownere
        ' </summary>
        Public ReadOnly Property DatabaseOwner() As String
          Get
            Return _databaseOwner
          End Get
        End Property
    
        ' -----------------------------------------------------------------------------
        ' <summary>
        ' Gets the fully qualified name of the stored procedure
        ' </summary>
        ' <param name="name">The name of the stored procedure</param>
        ' <returns>The fully qualified name</returns>
        ' -----------------------------------------------------------------------------
        Private Function GetFullyQualifiedName(ByVal name As String) As String
          Return (DatabaseOwner _
          + (ObjectQualifier _
          + (ModuleQualifier + name)))
        End Function
    
        ' -----------------------------------------------------------------------------
        ' <summary>
        ' Gets the value for the field or DbNull if field has "null" value
        ' </summary>
        ' <param name="Field">The field to evaluate</param>
        ' <returns></returns>
        ' -----------------------------------------------------------------------------
        Private Function GetNull(ByVal Field As Object) As Object
          Return Null.GetNull(Field, DBNull.Value)
        End Function
    
        Public Overrides Sub YourCompany_GuestBook_Insert(ByVal ModuleId As Integer, _
         ByVal Name As String, ByVal Email As String, ByVal Message As String)
          SqlHelper.ExecuteNonQuery(ConnectionString, _
         GetFullyQualifiedName("YourCompany_GuestBook_Insert"), _
         ModuleId, Name, Email, Message)
        End Sub
    
        Public Overrides Sub YourCompany_GuestBook_Delete(ByVal ID As Integer)
          SqlHelper.ExecuteNonQuery(ConnectionString, _
             GetFullyQualifiedName("YourCompany_GuestBook_Delete"), ID)
        End Sub
    
        Public Overrides Function YourCompany_GuestBook_GetAll(ByVal ModuleId As Integer) As IDataReader
          Return CType(SqlHelper.ExecuteReader(ConnectionString, _
            GetFullyQualifiedName("YourCompany_GuestBook_GetAll"), ModuleId), IDataReader)
        End Function
    
        Public Overrides Sub YourCompany_GuestBook_Update(ByVal ID As Integer, ByVal Name As String, _
           ByVal Email As String, ByVal Message As String, ByVal DateEntered As DateTime)
          SqlHelper.ExecuteNonQuery(ConnectionString, _
            GetFullyQualifiedName("YourCompany_GuestBook_Update"), ID, Name, Email, Message, DateEntered)
        End Sub
      End Class
    End Namespace

    Модификация файла DataProvider.vb

    Содержимое файла DataProvider.vb следует заменить следующим кодом:

    Imports System
    Imports DotNetNuke
    Imports System.Data
    Imports DotNetNuke.Framework
    
    Namespace YourCompany.Modules.GuestBook
    
      Public MustInherit Class DataProvider
        ' singleton reference to the instantiated object
        Private Shared objProvider As DataProvider = Nothing
    
        ' constructor
        Shared Sub New()
          CreateProvider()
    
        End Sub
    
        ' dynamically create provider
        Private Shared Sub CreateProvider()
          objProvider = CType(Reflection.CreateObject("data", "YourCompany.Modules.GuestBook", ""), DataProvider)
        End Sub
    
        ' return the provider
        Public Shared Function Instance() As DataProvider
          Return objProvider
        End Function
    
        Public MustOverride Sub YourCompany_GuestBook_Insert(ByVal ModuleId As Integer, _ 
                ByVal Name As String, ByVal Email As String, ByVal Message As String)
        Public MustOverride Function YourCompany_GuestBook_GetAll(ByVal ModuleId As Integer) As IDataReader
        Public MustOverride Sub YourCompany_GuestBook_Update(ByVal ID As Integer, ByVal Name As String, _ 
                ByVal Email As String, ByVal Message As String, ByVal DateEntered As DateTime)
        Public MustOverride Sub YourCompany_GuestBook_Delete(ByVal ID As Integer)
    
      End Class
    
    End Namespace

    Таким образом, создание уровня доступа к данным завершено. Переходим к уровню бизнес-логики.

    Этапы реализации уровня бизнес-логики

    Для построения уровня бизнес-логики буду произведены следующие действия:

  • модифицирован файл GuestBookInfo.vb ;
  • модифицирован файл GuestBookController.vb.
  • Модификация файла GuestBookInfo.vb

    В данном файле будет создан класс, предназначенный для хранения данных, диаграмма которого приведена на рис. 15.25.

    (рис 15.25) Диаграмма класса GuestBookInfo

    Для его реализации замените содержимое файла на следующее:

    Imports System
    Imports System.Configuration
    Imports System.Data
    
    Namespace YourCompany.Modules.GuestBook
    
      Public Class GuestBookInfo
    
        Private _ModuleId As Integer
        Private _ID As Integer
        Private _Name As String
        Private _Email As String
        Private _Message As String
        Private _DateEntered As DateTime
    
        ' 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 Name
        ' </summary>
        Public Property Name() As String
          Get
            Return _Name
          End Get
          Set(ByVal value As String)
            _Name = value
          End Set
        End Property
    
    
        ' <summary>
        ' Gets and sets the Email
        ' </summary>
        Public Property Email() As String
          Get
            Return _Email
          End Get
          Set(ByVal value As String)
            _Email = value
          End Set
        End Property
    
    
        ' <summary>
        ' Gets and sets the Message
        ' </summary>
        Public Property Message() As String
          Get
            Return _Message
          End Get
          Set(ByVal value As String)
            _Message = value
          End Set
        End Property
    
    
        ' <summary>
        ' Gets and sets the DateEntered
        ' </summary>
        Public Property DateEntered() As DateTime
          Get
            Return _DateEntered
          End Get
          Set(ByVal value As DateTime)
            _DateEntered = value
          End Set
        End Property
    
    
      End Class
    End Namespace

    Модификация файла GuestBookController.vb

    Содержимое файла следует заменить следующим кодом:

    Imports System
    Imports System.Collections.Generic
    Imports System.Configuration
    Imports System.ComponentModel
    Imports System.Data
    Imports System.Xml
    Imports System.Web
    Imports DotNetNuke
    Imports DotNetNuke.Common
    Imports DotNetNuke.Common.Utilities
    Imports DotNetNuke.Entities.Modules
    Imports DotNetNuke.Services.Search
    
    
    Namespace YourCompany.Modules.GuestBook
    
      Public Class GuestBookController
    
        <DataObjectMethod(DataObjectMethodType.Insert)> _
        Public Shared Sub GuestBook_Insert(ByVal objTest As GuestBookInfo)
          DataProvider.Instance.YourCompany_GuestBook_Insert(objTest.ModuleId, objTest.Name, 
                    objTest.Email, objTest.Message)
        End Sub
    
        <DataObjectMethod(DataObjectMethodType.Delete)> _
        Public Shared Sub GuestBook_Delete(ByVal objTest As GuestBookInfo)
          DataProvider.Instance.YourCompany_GuestBook_Delete(objTest.ID)
        End Sub
    
        <DataObjectMethod(DataObjectMethodType.Select)> _
        Public Shared Function GuestBook_GetAll(ByVal ModuleId As Integer) As List(Of GuestBookInfo)
          Return CBO.FillCollection(Of GuestBookInfo)(DataProvider.Instance().YourCompany_GuestBook_GetAll(ModuleId))
        End Function
    
        <DataObjectMethod(DataObjectMethodType.Update)> _
        Public Shared Sub GuestBook_Update(ByVal objTest As GuestBookInfo)
          DataProvider.Instance.YourCompany_GuestBook_Update(objTest.ID, objTest.Name, 
                                                      objTest.Email, objTest.Message, objTest.DateEntered)
        End Sub
    
      End Class
    
    
    End Namespace

    Этот код создает класс с четырьмя методами (рис. 15.26):

  • GuestBook_Insert - Добавляет записи в БД. Используется объект GuestBookInfo. Параметры ModuleId, Name, Email, Message передаются методу YourCompany_GuestBook_Insert в файле DataProvider.vb
  • GuestBook_Delete - Удаляет записи из БД. Используется объект GuestBookInfo. Параметр ID передается методу YourCompany_GuestBook_Delete в файле DataProvider.vb.
  • . Используется параметр .
  • . Используется объект GuestBookInfo. Метод открывает объект и передает отдельные параметры ( ID, ModuleId, Name, Email, Message, DateEntered ) методу YourCompany_GuestBook_Update в файле DataProvider.vb ".
  • (рис 15.26) Класс GuestBookController

    Этапы реализации уровня представления

    Для создания уровня представления следует:

  • модифицировать файлы локализации ( *.resx );
  • модифицировать элементы управления и связанные с ними файлы кода ( EditGuestBook.ascx, Settings.ascx, ViewGuestBook.ascx ).
  • Все перечисленные файлы находятся в каталоге /DesktopModules/GuestBook.

    Модификация файлов локализации

    Технология локализации, используемая в DNN, позволяет создавать текстовые метки с возможностью изменения текста при переключении языка. Это достигается путем изменения файла ресурсов, который имеет расширение .resx.

    Откройте файл /DesktopModules/GuestBook/App_LocalResources/EditGuestBook.ascx.resx (рис. 15.27).

    (рис 15.27) Исходное содержимое файла EditGuestBook.ascx.resx.

    Измените содержимое файла таким образом, чтобы оно соответствовало рис. 15.28.

    (рис 15.28) Измененное содержимое файла EditGuestBook.ascx.resx.

    Откройте файл Settings.ascx.resx (рис. 15.29).

    (рис 15.29) Исходное содержимое файла Settings.ascx.resx

    Следует изменить его содержимое таким образом, чтобы оно соответствовало приведенному на рис. 15.30.

    (рис 15.30) Измененное содержимое файла Settings.ascx.resx

    Аналогично, следует заменить содержимое файла ресурсов ViewGuestBook.ascx.resx на следующее (рис. 15.31).

    (рис 15.31) Измененное содержимое файла ViewGuestBook.ascx.resx

    Модификация элементов управления

    Модуль состоит из трех элементов управления:

  • EditGuestBook.ascx и EditGuestBook.ascx.vb
  • Settings.ascx и Settings.ascx.vb
  • ViewGuestBook.ascx и ViewGuestBook.ascx.vb
  • В контекстном меню файла EditGuestBook.ascx выберите пункт View Markup (рис. 15.32).

    (рис 15.32) Контекстное меню файла EditGuestBook.ascx

    Замените код элемента управления на следующий:

    <%@ Control language="VB" Inherits="YourCompany.Modules.GuestBook.EditGuestBook" 
    CodeFile="EditGuestBook.ascx.vb" AutoEventWireup="true"%>
    <%@ Register TagPrefix="dnn" TagName="Label" Src="~/controls/LabelControl.ascx" %>
    <dnn:label id="lblContent" runat="server" controlname="lblContent" 
    suffix=":"></dnn:label>
    nbsp;
    <asp:ObjectDataSource ID="ObjectDataSource_Tasks" runat="server" 
      DataObjectTypeName="YourCompany.Modules.GuestBook.GuestBookInfo"
      DeleteMethod="GuestBook_Delete" InsertMethod="GuestBook_Insert" 
      OldValuesParameterFormatString="original_{0}"
      OnInit="Page_Load" SelectMethod="GuestBook_GetAll" 
      TypeName="YourCompany.Modules.GuestBook.GuestBookController"
      UpdateMethod="GuestBook_Update">
        <SelectParameters>
          <asp:Parameter DefaultValue="00" Name="ModuleId" Type="Int32" />
        </SelectParameters>
    </asp:ObjectDataSource>
    nbsp;
    <asp:GridView ID="GridView1" runat="server" AllowPaging="True" 
      AutoGenerateColumns="False" DataSourceID="ObjectDataSource_Tasks" 
      DataKeyNames="ID">
      <Columns>
        <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
        <asp:BoundField DataField="ID" HeaderText="ID" Visible="False" />
        <asp:BoundField DataField="ModuleID" HeaderText="ModuleID" Visible="False" />
        <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
        <asp:BoundField DataField="Message" HeaderText="Message" SortExpression="Message" />
        <asp:BoundField DataField="Email" HeaderText="Email" />
        <asp:BoundField ApplyFormatInEditMode="True" DataField="DateEntered" 
         DataFormatString="{0:d}"
        HeaderText="Date" HtmlEncode="False" SortExpression="DateEntered" />
      </Columns>
    </asp:GridView> <asp:BoundField ApplyFormatInEditMode="True" DataField="DateEntered" 
     DataFormatString="{0:d}"
     HeaderText="Date" HtmlEncode="False" SortExpression="DateEntered" />
    </Columns>
    </asp:GridView>

    Проделайте аналогичную процедуру с файлом Settings.ascx, заменив его разметку на следующую:

    <%@ Control Language="VB" AutoEventWireup="false" 
       CodeFile="Settings.ascx.vb" Inherits="YourCompany.Modules.GuestBook.Settings" %>
    <%@ Register TagPrefix="dnn" TagName="Label" Src="~/controls/LabelControl.ascx" %>
    
    <dnn:label id="lblshowform" runat="server" controlname="lblshowform" 
      suffix=":"></dnn:label>
    <br />
    <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True" 
      OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
      <asp:ListItem Selected="True">Yes</asp:ListItem>
      <asp:ListItem>No</asp:ListItem>
    </asp:DropDownList>

    То же самое следует проделать с разметкой файла ViewGuestBook.ascx, заменив ее на следующую:

    <%@ Control Language="VB" Inherits="YourCompany.Modules.GuestBook.ViewGuestBook" 
     CodeFile="ViewGuestBook.ascx.vb"
    AutoEventWireup="true" %>
    <%@ Register TagPrefix="dnn" TagName="Label" Src="~/controls/LabelControl.ascx" %>
    <asp:ObjectDataSource ID="ObjectDataSource_Tasks" runat="server" 
      DataObjectTypeName="YourCompany.Modules.GuestBook.GuestBookInfo"
      DeleteMethod="GuestBook_Delete" InsertMethod="GuestBook_Insert" 
      OldValuesParameterFormatString="original_{0}"
      SelectMethod="GuestBook_GetAll" TypeName="YourCompany.Modules.GuestBook.GuestBookController"
      UpdateMethod="GuestBook_Update" OnInit="Page_Load">
      <SelectParameters>
        <asp:Parameter DefaultValue="00" Name="ModuleId" Type="Int32" />
      </SelectParameters>
    </asp:ObjectDataSource>
    nbsp;
    <asp:GridView ID="GridView1" runat="server" DataSourceID="ObjectDataSource_Tasks"
      AutoGenerateColumns="False" AllowPaging="True" HorizontalAlign="Center">
      <Columns>
        <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
        <asp:BoundField DataField="Message" HeaderText="Message" 
          SortExpression="Message" />
        <asp:BoundField ApplyFormatInEditMode="True" DataField="DateEntered" 
          DataFormatString="{0:d}"
      HeaderText="Date" SortExpression="DateEntered" HtmlEncode="False" />
      </Columns>
      <EmptyDataTemplate>
        There are no entries.
      </EmptyDataTemplate>
    </asp:GridView>
    <br />
    <center>
      <dnn:Label ID="lblAddMessage" runat="server" ControlName="lblAddMessage" 
        Suffix=":">
      </dnn:Label>
    </center>
    <br />
    <asp:FormView ID="FormView1" runat="server" DataSourceID="ObjectDataSource_Tasks" 
      DefaultMode="Insert" HorizontalAlign="Center">
      <InsertItemTemplate>
        <table cellpadding="2" cellspacing="5" style="width: 50%" align="center">
          <tr>
            <td align="right" style="width: 4px">
            <asp:Label ID="Label1" runat="server" Text="Name"></asp:Label></td>
            <td style="width: 100px">
            <asp:TextBox ID="NameTextBox" runat="server" 
             Text='<%# Bind("Name") %>' Width="264px"></asp:TextBox></td>
          </tr>
          <tr>
            <td align="right" style="width: 4px; height: 23px">
            <asp:Label ID="Label3" runat="server" Text="Email"></asp:Label></td>
            <td style="width: 100px; height: 23px">
            <asp:TextBox ID="EmailTextBox" runat="server" 
              Text='<%# Bind("Email") %>' Width="264px"></asp:TextBox></td>
          </tr>
          <tr>
            <td align="right" style="width: 4px; height: 21px">
            <asp:Label ID="Label2" runat="server" 
              Text="Message"></asp:Label></td>
            <td style="width: 100px; height: 21px">
            <asp:TextBox ID="MessageTextBox" runat="server" EnableViewState="False" 
            MaxLength="250"         Rows="2" Text='<%# Bind("Message") %>' 
            TextMode="MultiLine" Width="264px"></asp:TextBox></td>
          </tr>
          <tr>
            <td align="right" colspan="2" style="height: 21px">
            <asp:Button ID="InsertButton" runat="server" Text="Submit" 
             CommandName="Insert" /></td>
          </tr>
        </table>
        <br />
        nbsp;
      </InsertItemTemplate>
    </asp:FormView>

    Далее следует в контекстном меню файла EditGuestBook.ascx выбрать пункт View Code (рис. 15.33).

    (рис 15.33) Контекстное меню файла EditGuestBook.ascx

    Открывшийся код следует заменить на следующий:

    Imports DotNetNuke
    Imports System.Web.UI
    Imports System.Collections.Generic
    Imports System.Reflection
    Imports DotNetNuke.Entities.Modules
    
    Namespace YourCompany.Modules.GuestBook
      Partial Class EditGuestBook
        Inherits PortalModuleBase
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
          Try
          Catch exc As Exception
            Exceptions.ProcessModuleLoadException(Me, exc)
          End Try
        End Sub
    
        Protected Sub SetModuleId(ByVal sender As Object, 
        ByVal e As System.Web.UI.WebControls.ObjectDataSourceSelectingEventArgs) _
                Handles ObjectDataSource_Tasks.Selecting
          e.InputParameters("ModuleId") = ModuleId.ToString
        End Sub
      End Class
    End Namespace

    Код файла Settings.ascx необходимо заменить на следующий:

    Imports System
    Imports System.Web.UI
    Imports DotNetNuke
    Imports DotNetNuke.Entities.Modules
    Imports DotNetNuke.Services.Exceptions
    Namespace YourCompany.Modules.GuestBook
      Partial Class Settings
        Inherits ModuleSettingsBase
        Public Overrides Sub LoadSettings()
          Try
            If (Page.IsPostBack = False) Then
              If (Not (CType(TabModuleSettings("showform"), String)) Is Nothing) Then
                Me.DropDownList1.SelectedValue = CType(TabModuleSettings("showform"), String)
              End If
            End If
          Catch exc As Exception
            Exceptions.ProcessModuleLoadException(Me, exc)
          End Try
        End Sub
    
        Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
          Dim objModules As ModuleController = New ModuleController
          If (Me.DropDownList1.SelectedValue = "Yes") Then
            objModules.UpdateTabModuleSetting(TabModuleId, "showform", "Yes")
          Else
            objModules.UpdateTabModuleSetting(TabModuleId, "showform", "No")
          End If
        End Sub
      End Class
    End Namespace

    Аналогично ниже приведен код для файла ViewGuestBook.ascx:

    Imports DotNetNuke
    Imports System.Web.UI
    Imports System.Collections.Generic
    Imports System.Reflection
    Imports DotNetNuke.Entities.Modules
    Namespace YourCompany.Modules.GuestBook
      Partial Class ViewGuestBook
        Inherits Entities.Modules.PortalModuleBase
        Implements Entities.Modules.IActionable
        Public ReadOnly Property ModuleActions() As Entities.Modules.Actions.ModuleActionCollection _
                                              Implements Entities.Modules.IActionable.ModuleActions
          Get
            Dim Actions As New Entities.Modules.Actions.ModuleActionCollection
            Actions.Add(GetNextActionID, _
                Localization.GetString(Entities.Modules.Actions.ModuleActionType.EditContent, 
                LocalResourceFile), 
                Entities.Modules.Actions.ModuleActionType.EditContent, 
                "", "", EditUrl(), False, Security.SecurityAccessLevel.Edit, True, False)
            Return Actions
          End Get
        End Property
    
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
          Try
            Dim objModules As ModuleController = New ModuleController
            If Not Page.IsPostBack Then
              If (Not (CType(Settings("showform"), String)) Is Nothing) Then
                If (CType(Settings("showform"), String) = "No") Then
                  ' Do not allow messages to be added
                  FormView1.Visible = False
                  lblAddMessage.Visible = False
                End If
              End If
            Else
              Me.GridView1.DataBind()
            End If
          Catch ex As Exception
            Exceptions.ProcessModuleLoadException(Me, ex)
          End Try
        End Sub
    
        Protected Sub NewItem(ByVal sender As Object, _
                  ByVal e As System.Web.UI.WebControls.FormViewInsertEventArgs) _
                  Handles FormView1.ItemInserting
          e.Values.Item("ID") = 0
          e.Values.Item("ModuleId") = ModuleId.ToString()
          e.Values.Item("DateEntered") = DateTime.Now.ToShortDateString
        End Sub
    
        Protected Sub SetModuleID(ByVal sender As Object, _
                  ByVal e As System.Web.UI.WebControls.ObjectDataSourceSelectingEventArgs) _
                  Handles ObjectDataSource_Tasks.Selecting
          e.InputParameters("ModuleId") = ModuleId.ToString
        End Sub
      End Class
    End Namespace

    Тестирование созданного модуля

    После того, как все три уровня модуля разработаны, следует выбрать пункт главного меню Visual Studio Build | Build Web Site. Компиляция должна пройти без ошибок.

    После компиляции следует запустить проект, и в меню DNN выбрать страницу Guest Book. Появится созданный модуль (рис. 15.34).

    (рис 15.34) Созданный модуль GuestBook

    Использование объектных источников данных в DNN

    Рассмотрим в качестве примера метод GuestBook_Update. Он вызывается элементом управления EditGuestBook.ascx. В этом элементе управления присутствует следующий код для связи с объектным источником данных:

    <asp:ObjectDataSource ID="ObjectDataSource_Tasks" runat="server" 
      DataObjectTypeName="YourCompany.Modules.GuestBook.GuestBookInfo"
      DeleteMethod="GuestBook_Delete" InsertMethod="GuestBook_Insert" 
      OldValuesParameterFormatString="original_{0}"
      OnInit="Page_Load" SelectMethod="GuestBook_GetAll" 
      TypeName="YourCompany.Modules.GuestBook.GuestBookController"
      UpdateMethod="GuestBook_Update">
        <SelectParameters>
          <asp:Parameter DefaultValue="00" Name="ModuleId" Type="Int32" />
        </SelectParameters>
    </asp:ObjectDataSource>

    GridView, который пользователь использует для ввода и получения данных, связан с этим элементом управления.

    Обратите внимание на фрагмент

    DataObjectTypeName="YourCompany.Modules.GuestBook.GuestBookInfo.

    В нем указывается объектный источник данных - объект GuestBookInfo, который будет использоваться для передачи параметров (рис. 15.35).

    (рис 15.35) Объект GuestBookInfo

    Этот объект представляет собой обычный класс. Если необходимо иметь полный контроль над параметрами, необходимо добавить бизнес-логику. Эта функция является преимуществом объектных источников данным перед элементами управления, связанными с SQL-данными. Кроме того, это позволяет строить решения, полностью соответствующий n-уровневой архитектуре, полностью контролирующие данные на каждом из уровней.

    Теперь обратите внимание на фрагмент

    TypeName="YourCompany.Modules.GuestBook.GuestBookController

    Он указывает на класс GuestBookController (рис. 15.36), реализующий методы выборки ( Select ), обновления ( Update ), вставки ( Insert ) и удаления ( Delete ).

    (рис 15.36) Класс GuestBookController

    Далее, обратите внимание на фрагмент UpdateMethod="GuestBook_Update

    Он указывает, что метод GuestBook_Update класса GuestBookController является обработчиком события Update. В GridView, когда пользователь нажимает ссылку Update, происходят следующие действия. Поскольку GridView связан с объектным источником данных, объектный источник данных передает параметры из GridView в объект GuestBookInfo и вызывает метод GuestBook_Update класса GuestBookController:

    <DataObjectMethod(DataObjectMethodType.Update)> _
        Public Shared Sub GuestBook_Update(ByVal objTest As GuestBookInfo)
          DataProvider.Instance.YourCompany_GuestBook_Update(objTest.ID, objTest.Name, _
                                  objTest.Email, objTest.Message, objTest.DateEntered)
        End Sub

    Этот метод получает класс GuestBookInfo и передает каждый параметр уроню доступа к данным. Объект GuestBookInfo используется для каждого метода в классе GuestBookController, за исключением метода Select:

    <DataObjectMethod(DataObjectMethodType.Select)> _
        Public Shared Function GuestBook_GetAll(ByVal ModuleId As Integer) As List(Of GuestBookInfo)
          Return CBO.FillCollection(Of GuestBookInfo)(DataProvider.Instance().YourCompany_GuestBook_GetAll(ModuleId))
        End Function

    Этот метод получает параметр ModuleId и возвращает объект GuestBookInfo.

    Контрольные вопросы

  • Опишите архитектуру модулей DNN. Из каких уровней она состоит?
  • Какие функции выполняет каждый их уровней модели модулей DNN?
  • В каких каталогах размещаются компоненты модуля?
  • Какой инструмент оптимально использовать для создания модулей DNN?
  • Вернуться к учебному плану