Непонятен ход решения задачи |
Создание интерактивных Web-документов
Как придать структуру программному коду
Я говорил о том, что одной из трудностей Web-программирования в нынешних условиях, является слабая структурированность программного кода, отсутствие столь привычного модульного построения программных проектов. Чтобы как-то справиться с этой проблемой, я для себя создал определенные правила. Приведу их, может быть, они будут полезны и другим:
- Декларативная часть кода, исполняемого на сервере, записывается в заголовочной части HTML-текста страницы - в конец тега <head>. Декларативной части предшествует специальный комментарий. Вы могли видеть его в тексте приведенного кода.
- Декларативная часть кода, исполняемого на клиентской стороне, также записывается в заголовочной части сразу после серверного кода, если таковой присутствует. Этому фрагменту кода также предшествует специальный комментарий.
- Исполняемая часть серверного кода, снабженная комментарием, записывается в начале тега <body>.
- Исполняемая часть клиентского кода отсутствует. Инициируют выполнение программного кода на стороне клиента процедуры - обработчики событий.
Эти нехитрые правила хоть как-то облегчают понимание программного текста, столь важное при отладке многомерного кода. А теперь вернемся к рассмотрению того, что собой представляют две другие ASP-страницы нашего узла.
Страница qomToBase - страница, где информация пользователя записывается в базу данных
Напомню, эта страница вызывается после нажатия кнопки с заголовком "Послать вопрос и/или отзыв и/или оценку". Кнопка имеет статус Submit. Одновременно странице передаются данные о заданном пользователем вопросе, сделанном отзыве, проставленной оценке, также как и данные о книге, с которой связаны эти характеристики. Серверный код на этой странице должен обеспечить прием параметров и запись полученной информации в таблицы базы данных. Должен быть сформирован HTML-код, уведомляющий пользователя о результатах выполнения его запроса.
Я решил на этапе проектирования оставить эту страницу пустой - ни интерфейсных объектов, ни даже простого текста на этой странице нет. Все, что на ней появится, когда она откроется на клиентском компьютере, будет определяться результатами выполнения серверного кода. Поэтому, если открыть эту страницу во FrontPage на вкладке Normal, то все будет пусто. Но серверный код в ней, конечно же, присутствует.
Код, исполняемый на сервере
Напомню, следуя собственным правилам структурирования кода, я отделяю декларативную часть кода, содержащую описание переменных и процедур. С ее рассмотрения и начнем:
<SCRIPT LANGUAGE=vbscript RUNAT=Server> '********************************************************** '** Объявления глобальных переменных, процедур и функций ** '************ на серверной стороне ************************ 'Задание объектов ADODB - Connection, Command, Recordset Dim Con1 'Объект ADODB, задающий соединение Dim Cmd1 'Объект ADODB, задающий команду Dim Rst1 'Объект ADODB, задающий набор записей 'Переменные для приема полей формы frmMain страницы Qpage Dim pAuthor 'Автор книги Dim pTitle 'Название книги Dim pQ 'Вопрос Dim pOp 'Отзыв Dim pM 'Отметка Dim pUser 'Автор вопроса, отзыва, отметки Sub InitVars() 'Инициализация глобальных переменных Set Con1=Server.CreateObject("ADODB.Connection") 'Получение информации, переданной при пересылке формы pAuthor =Request.form("Author") pTitle =Request.form("Title") pQ =Request.form("Question") pOp =Request.form("Opinion") pM =Request.form("Mark") 'pM="Excellent" pUser=Session("UserId") End Sub 'InitVars Sub CreateConnection() 'Создание соединения с тестовой базой данных Access Dim strConnStr 'Строка соединения If Con1.State <> 1 Then strConnStr="Provider=Microsoft.jet.oledb.4.0; " & _ "Data Source =c:\Ch20\dbPP2000.mdb" Con1.Open strConnStr End If End Sub 'CreateConnection Sub SelectAndExec() 'Анализ запроса и его выполнение Dim res 'результат выполнения запроса Dim strMark 'Уведомление о сохранении отметки Dim strOpinion 'Уведомление о сохранении отзыва Dim strQuestion 'Уведомление о сохранении вопроса Dim str1 'строковая константа On Error Resume Next str1 = "Сохранение в базе данных прошло успешно" If Len(pQ)> 2 Then 'Вопрос задан res = False res = SaveQuestion If res = True Then strQuestion="Ваш Вопрос - " & str1 Else strQuestion = "Ваш Вопрос - " & Err.Description End If End If If Len(pOp)> 2 Then 'Отзыв задан res = False res = SaveOpinion If res = True Then strOpinion="Ваш отзыв - " & str1 Else strOpinion = "Ваш отзыв - " & Err.Description End If End if If pM > 0 Then 'Оценка задана res = False res = SaveMark If res = True Then strMark="Ваша оценка - " & str1 Else strMark = "Ваша оценка - " & Err.Description End If End If 'Формирование HTML-кода страницы с уведомлением 'о результатах выполнения запроса Response.Write "<p>" & strMark Response.Write "<p>" & strQuestion Response.Write "<p>" & strOpinion Response.Write "<p><A href=""qpage.asp"">" & _ " <font size=7 color = ""#FF6666""> Вернуться </font> </a>" Response.Write "на страницу Читатели" End Sub 'SelectAndExec Function SaveMark 'Сохранение отметки Dim par 'параметр для формирования запроса на вставку Set Cmd1=Server.CreateObject("ADODB.Command") With Cmd1 'Конфигурирование объекта Command .ActiveConnection = Con1 .CommandText = "InsertMark" .CommandType = 4 'adCmdStoredProc For i = 0 to .Parameters.Count -1 .Parameters.Delete(i) 'Чистка коллекции Next 'i Set par= .CreateParameter("repMark",2,1) par.value=pM .Parameters.Append par Set par= .CreateParameter("repUID",3,1) par.value=pUser .Parameters.Append par Set par= .CreateParameter("repAuthor",202,1,255) par.value=pAuthor .Parameters.Append par Set par= .CreateParameter("repTitle",202,1,255) par.value=pTitle .Parameters.Append par .Execute SaveMark=True End With End Function 'SaveMark Function SaveOpinion 'Сохранение отзыва Dim par 'параметр для формирования запроса на вставку Set Cmd1=Server.CreateObject("ADODB.Command") With Cmd1 'Конфигурирование объекта Command .ActiveConnection = Con1 .CommandText = "InsertOpinion" .CommandType = 4 'adCmdStoredProc For i = 0 to .Parameters.Count -1 .Parameters.Delete(i) 'Чистка коллекции Next 'i Set par= .CreateParameter("repOpinion",202,1,255) par.value=pOp .Parameters.Append par Response.Write par Set par= .CreateParameter("repUID",3,1) par.value=pUser .Parameters.Append par Response.Write par Set par= .CreateParameter("repAuthor",202,1,255) par.value=pAuthor .Parameters.Append par Response.Write par Set par= .CreateParameter("repTitle",202,1,255) par.value=pTitle .Parameters.Append par Response.Write par .Execute SaveOpinion=True End With End Function 'SaveOpinion Function SaveQuestion 'Сохранение вопроса Dim par 'параметр для формирования запроса на вставку Set Cmd1=Server.CreateObject("ADODB.Command") With Cmd1 'Конфигурирование объекта Command .ActiveConnection = Con1 .CommandText = "InsertQuestion" .CommandType = 4 'adCmdStoredProc For i = 0 to .Parameters.Count -1 .Parameters.Delete(i) 'Чистка коллекции Next 'i Set par= .CreateParameter("repQuestion",202,1,255) par.value=pQ .Parameters.Append par Set par= .CreateParameter("repQDate",133,1) par.value = Date .Parameters.Append par Set par= .CreateParameter("repUID",3,1) par.value=pUser .Parameters.Append par Set par= .CreateParameter("repAuthor",202,1,255) par.value=pAuthor .Parameters.Append par Set par= .CreateParameter("repTitle",202,1,255) par.value=pTitle .Parameters.Append par .Execute SaveQuestion = True End With End Function 'SaveQuestion </SCRIPT>
Декларативная часть кода достаточно большая - в ней около десятка процедур, которые и решают все задачи, возложенные на эту страницу. Зато исполняемый фрагмент серверного кода невелик - он сводится к вызову тех или иных процедур. Приведу сразу и его, а уже потом приступлю к обсуждению деталей работы по выполнению запросов пользователя.
<body> <SCRIPT LANGUAGE=vbscript RUNAT=Server> '********************************************************** '** Исполняемый код на серверной стороне ** '************ на серверной стороне ************************ 'Инициализация переменных InitVars 'Создать соединение с базой данных CreateConnection 'Анализ запроса и выполнение действия, заданного пользователем SelectAndExec </SCRIPT> </body>
Исполнение серверного кода начинается с инициализации глобальных переменных, которое производится в процедуре InitVars. Помимо привычной инициализации объекта ADODB.Connection именно здесь происходит извлечение информации, переданной в полях формы. Метод (свойство) Form серверного объекта Request позволяет по индексу (имени поля) получить значение соответствующего поля формы, которая была послана на сервер нажатием кнопки Submit. Присвоив в начале работы эти значения специально созданным глобальным переменным, в дальнейшем уже можно не испытывать никаких затруднений - вся нужная информация, переданная серверу, будет под рукой. Обратите внимание на еще один способ получения информации на стороне сервера. Для получения значения переменной pUser, которая хранит идентификатор пользователя, используется другой серверный объект Session. Обычно этот объект создается по данным регистрации пользователя, но я упростил задачу и задал его явно на предыдущей странице. Таким образом, после работы процедуры InitVars вся нужная серверу информация получена и хранится в обычных переменных.
Обратите внимание на закомментированный оператор, присваивающий переменной pMark некорректное значение. Я использовал его, чтобы смоделировать ситуацию, приводящую к ошибке при записи в базу данных. Это позволило мне убедиться в том, что предусмотренная кодом обработка ошибок периода выполнения работает должным образом.
Следующим шагом работы является установление соединения с базой данных. Оно типично, и я на нем останавливаться не буду.
Основная работа на серверной стороне выполняется в процедуре SelectAndExec. Прежде всего следует понять, какую информацию прислал пользователь, - послал ли пользователь вопрос, написал ли отзыв, проставил оценку. С этой целью анализируется содержимое переменных, хранящих значение вопроса, отзыва, оценки. Если соответствующее поле пусто (оценка равна 0 ), то ничего записывать в базу данных не нужно, в противном случае вызывается соответствующая функция - SaveQuestion, SaveOpinion, SaveMark, которая и добавляет новую запись в одну из таблиц базы данных.
Обратите внимание, если запись в базу данных пройдет успешно, то переменная res получит значение True. Если же при выполнении функции возникнет ошибка, то предусмотренный обработчик исключительной ситуации On Error позволит продолжить выполнение программы, но переменная res сохранит значение False. В зависимости от значения res формируется то или иное сообщение для уведомления пользователя о результатах выполненной работы.
Последний фрагмент в процедуре SelectAndExec формирует HTML-код страницы с уведомлениями о результатах работы, а также ссылку для возврата на основную страницу. Для этого используется, как обычно, метод Write объекта Response.
Три процедуры - SaveQuestion, SaveOpinion, SaveMark устроены одинаково - все они добавляют одну запись к той или иной таблице базы данных, используя для этого хранимый запрос на добавление записи. Давайте разберем более подробно первую из них. Начну с вида хранимого запроса. Вот его SQL-запись:
PARAMETERS repQuestion Text ( 255 ), repQDate DateTime, repUID Long, repAuthor Text ( 255 ), repTitle Text ( 255 ); INSERT INTO QA ( Question, QDate, UserId, Author, Title ) VALUES ([repQuestion], [repQDate], [repUID], [repAuthor], [repTitle]);
Как видите, это запрос с пятью параметрами. Через параметры полям записи передаются - сам вопрос, дата задания вопроса, название и автор книги, по которой был задан вопрос и идентификатор пользователя, задавшего вопрос.
Понятно, что в функции SaveQuestion, вызывающей этот запрос, при формировании объекта ADODB.Command главной задачей является корректное формирование коллекции Parameters этого объекта. Дальше остается только вызвать метод Execute, чтобы выполнить запрос. Поскольку в главах, посвященных объектам ADO, я подробно рассматривал все свойства и методы этих объектов, в том числе работу с коллекцией Parameters, то теперь останавливаться на деталях, думаю, нет необходимости.
На этом можно и закончить описание вопросов создания программного кода, да и самой страницы в целом. В заключение взгляните, как выглядит эта страница, после того как пользователь послал свою оценку книги на сервер, и эта операция была успешно выполнена.