Архитектура модулей DNN традиционно представляется в виде рис. 15.1.
(рис 15.1) Архитектура модулей DNNКомпоненты этой архитектуры соответствуют стандартной трехуровневой архитектурной модели приложений:
Рассмотрим структуру типового модуля DNN на примере модуля Survey. Код модуля, соответствующий уровню представления (UI) и отвечающий за взаимодействие с пользователем, находится в каталоге DesktopModules\Survey (рис. 15.2).
(рис 15.2) Код, соответствующий уровню представленияКод, относящийся к уровням бизнес-логики (BLL) и доступа к данным (DAL) размещаются в каталоге App_Code.
Для создания новых модулей DNN оптимальным инструментом является
В состав Visual Studio 2005 входит web-сервер Cassini, с помощью которого можно тестировать созданные страницы сайта, без необходимости настройки IIS.
Для Visual Studio разработаны специальные программные дополнения - Starter
Существует версия дистрибутива DotNetNuke, созданная в виде Starter
В Visual Studio 2005 выберите пункт главного меню File | Open | File и выберите файл DotNetNuke_4.x_StarterKit.vsi. Откроется окно выбора устанавливаемых компонентов DNN Starter
(рис 15.3) Окно выбора устанавливаемых компонентов DNN Starter KitСледует оставить выделенными все компоненты. Далее появляется предупреждение о том, что у устанавливаемого Starter
(рис 15.4) Предупреждение об отсутствии цифровой подписиСледует нажать кнопку Yes, и в окне с перечнем компонентов, подлежащих установке (рис. 15.5) нажать Finish.
(рис 15.5) Перечень устанавливаемых компонентовВ результате Starter
Для установки DNN с использованием Starter
(рис 15.6) Выбор типа создаваемого сайтаВыберите тип проекта DNN Web
Далее следует нажать комбинацию клавиш Ctrl+F5, чтобы запустить процесс установки без включения режима отладки. Далее процедура установки аналогична описанной выше.
В данной лабораторной работе будет создан модуль GuestBook - "Гостевая книга", поскольку это позволит осветить большинство функций - выбор, обновление, удаление и вставку. Будет показано, как связать
В окне Solution Explorer щелкните в
(рис 15.7) Выбор типа создаваемого модуляСледует выбрать шаблон DotNetNuke
(рис 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-скрипт, предназначенный для создания
(рис 15.15) Страница SQL со вставленным SQL-скриптомСледует установить флажок "Run as Script" и выбрать ссылку Execute.
Из меню портала следует выбрать пункт Host |
(рис 15.16) Меню страницы Module DefinitionsОткроется страница Edit
(рис 15.17) Страница Edit Module DefinitionsДалее следует нажать кнопку Add в группе Page Functions панели инструментов DNN (рис. 15.18).
(рис 15.18) Панель инструментов DNNНа появившейся странице в поля ввода Page Name, Page Title и Description следует ввести "
(рис 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
Этот код использует IDataReader.
Таким образом, соответствие файлов модуля уровням приведенной модели может быть представлено в виде рис. 15.21.
(рис 15.21) Соответствие файлов модуля уровням модели
При создании уровня доступа к данным буду проделаны следующие операции:
SqlDataProvider.vb, в который будет помещен код, вызывающий хранимые процедуры;DataProvider.vb, в который будут добавлены методы (которые переопределяются в файле SqlDataProvider.vb ).Так как в данной лабораторной работе используется СУБД MS SQL Server Express, то подключение уже настроено. Для просмотра текущего подключения следует выбрать пункт главного меню Visual Studio View |
(рис 15.22) Компонент Visual Studio Server Explorer
При создании нового модуля автоматически была создана таблица YourCompany_GuestBook, а также ряд хранимых процедур:
YourCompany_AddGuestBook,YourCompany_DeleteGuestBook,YourCompany_GetGuestBook,YourCompany_GetGuestBooks,YourCompany_UpdateGuestBook.Их необходимо удалить.
Для
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) Созданные хранимые процедуры
Содержимое файла 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 следует заменить следующим кодом:
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.В данном файле будет создан класс, предназначенный для хранения данных, диаграмма которого приведена на рис. 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
Содержимое файла следует заменить следующим кодом:
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.vbGuestBook_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.
Технология .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.vbSettings.ascx и Settings.ascx.vbViewGuestBook.ascx и ViewGuestBook.ascx.vbВ контекстном меню файла EditGuestBook.ascx выберите пункт View
(рис 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 выбрать страницу
(рис 15.34) Созданный модуль GuestBook
Рассмотрим в качестве примера метод 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>
Обратите внимание на фрагмент
DataObjectTypeName="YourCompany.Modules.GuestBook.GuestBookInfo.
В нем указывается объектный источник данных - объект GuestBookInfo, который будет использоваться для
(рис 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. В , когда пользователь нажимает ссылку Update, происходят следующие действия. Поскольку связан с объектным источником данных, объектный источник данных передает параметры из в объект 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 традиционно представляется в виде рис. 15.1.
(рис 15.1) Архитектура модулей DNNКомпоненты этой архитектуры соответствуют стандартной трехуровневой архитектурной модели приложений:
Рассмотрим структуру типового модуля DNN на примере модуля Survey. Код модуля, соответствующий уровню представления (UI) и отвечающий за взаимодействие с пользователем, находится в каталоге DesktopModules\Survey (рис. 15.2).
(рис 15.2) Код, соответствующий уровню представленияКод, относящийся к уровням бизнес-логики (BLL) и доступа к данным (DAL) размещаются в каталоге App_Code.
Для создания новых модулей DNN оптимальным инструментом является
В состав Visual Studio 2005 входит web-сервер Cassini, с помощью которого можно тестировать созданные страницы сайта, без необходимости настройки IIS.
Для Visual Studio разработаны специальные программные дополнения - Starter
Существует версия дистрибутива DotNetNuke, созданная в виде Starter
В Visual Studio 2005 выберите пункт главного меню File | Open | File и выберите файл DotNetNuke_4.x_StarterKit.vsi. Откроется окно выбора устанавливаемых компонентов DNN Starter
(рис 15.3) Окно выбора устанавливаемых компонентов DNN Starter KitСледует оставить выделенными все компоненты. Далее появляется предупреждение о том, что у устанавливаемого Starter
(рис 15.4) Предупреждение об отсутствии цифровой подписиСледует нажать кнопку Yes, и в окне с перечнем компонентов, подлежащих установке (рис. 15.5) нажать Finish.
(рис 15.5) Перечень устанавливаемых компонентовВ результате Starter
Для установки DNN с использованием Starter
(рис 15.6) Выбор типа создаваемого сайтаВыберите тип проекта DNN Web
Далее следует нажать комбинацию клавиш Ctrl+F5, чтобы запустить процесс установки без включения режима отладки. Далее процедура установки аналогична описанной выше.
В данной лабораторной работе будет создан модуль GuestBook - "Гостевая книга", поскольку это позволит осветить большинство функций - выбор, обновление, удаление и вставку. Будет показано, как связать
В окне Solution Explorer щелкните в
(рис 15.7) Выбор типа создаваемого модуляСледует выбрать шаблон DotNetNuke
(рис 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-скрипт, предназначенный для создания
(рис 15.15) Страница SQL со вставленным SQL-скриптомСледует установить флажок "Run as Script" и выбрать ссылку Execute.
Из меню портала следует выбрать пункт Host |
(рис 15.16) Меню страницы Module DefinitionsОткроется страница Edit
(рис 15.17) Страница Edit Module DefinitionsДалее следует нажать кнопку Add в группе Page Functions панели инструментов DNN (рис. 15.18).
(рис 15.18) Панель инструментов DNNНа появившейся странице в поля ввода Page Name, Page Title и Description следует ввести "
(рис 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
Этот код использует IDataReader.
Таким образом, соответствие файлов модуля уровням приведенной модели может быть представлено в виде рис. 15.21.
(рис 15.21) Соответствие файлов модуля уровням модели
При создании уровня доступа к данным буду проделаны следующие операции:
SqlDataProvider.vb, в который будет помещен код, вызывающий хранимые процедуры;DataProvider.vb, в который будут добавлены методы (которые переопределяются в файле SqlDataProvider.vb ).Так как в данной лабораторной работе используется СУБД MS SQL Server Express, то подключение уже настроено. Для просмотра текущего подключения следует выбрать пункт главного меню Visual Studio View |
(рис 15.22) Компонент Visual Studio Server Explorer
При создании нового модуля автоматически была создана таблица YourCompany_GuestBook, а также ряд хранимых процедур:
YourCompany_AddGuestBook,YourCompany_DeleteGuestBook,YourCompany_GetGuestBook,YourCompany_GetGuestBooks,YourCompany_UpdateGuestBook.Их необходимо удалить.
Для
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) Созданные хранимые процедуры
Содержимое файла 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 следует заменить следующим кодом:
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.В данном файле будет создан класс, предназначенный для хранения данных, диаграмма которого приведена на рис. 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
Содержимое файла следует заменить следующим кодом:
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.vbGuestBook_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.
Технология .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.vbSettings.ascx и Settings.ascx.vbViewGuestBook.ascx и ViewGuestBook.ascx.vbВ контекстном меню файла EditGuestBook.ascx выберите пункт View
(рис 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 выбрать страницу
(рис 15.34) Созданный модуль GuestBook
Рассмотрим в качестве примера метод 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>
Обратите внимание на фрагмент
DataObjectTypeName="YourCompany.Modules.GuestBook.GuestBookInfo.
В нем указывается объектный источник данных - объект GuestBookInfo, который будет использоваться для
(рис 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. В , когда пользователь нажимает ссылку Update, происходят следующие действия. Поскольку связан с объектным источником данных, объектный источник данных передает параметры из в объект 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.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.