Введение в ASP

Григорий Грин

Этот текст предназначен для тех, кто никогда не имел дела с ASP и вообще смутно себе представляет возможности программирования на стороне сервера. Я ставил себе задачу создать у читателя общее представление о предмете. Отдельные неточности при этом менее важны - пожалуйста, громко не ругайтесь.

Общие сведения

ASP (Active Server Pages) – это мощная технология от Microsoft, позволяющая легко разрабатывать приложения для WWW. ASP работает на платформе Windows NT и IIS (Internet Information Server), начиная с версии 3, хотя вроде есть реализации на других платформах. ASP – это не язык программирования, это внутренняя технология, позволяющая подключать программы к Web-страницам. Основа успеха ASP – простой скриптовый язык (Visual Basic Script или Java Script) и возможность использования внешних COM-компонент.

Как это все происходит?

Вы пишете программу и складываете в файл на сервере. Браузер клиента запрашивает файл. Файл сначала интерпретируется сервером, на выходе производится HTML-код. Этот HTML посылается клиенту. Файлы с программами имеют расширение .asp. Файлы asp – это обычные текстовые файлы, содержащие исходные тексты программ. Файлы делаются с помощью любого текстового редактора. Каталог, в котором размещены файлы asp должен иметь права на выполнение, так как сервер исполняет эти файлы, когда браузер их запрашивает. Собственно программы пишутся на любом скриптовом языке, который установлен в системе. По умолчанию поддерживаются VBScript и JavaScript. Можно доустановить другие (например, Perl). Если ничего специально не указывать используется VBScript. В дальнейшем будем ссылаться только на него. Программные фрагменты заключаются в скобки <% %>. Можно ставить открывающую скобку в начале файла, закрывающую – в конце, все что между ними – программа на Visual Basic'е.

Какие средства есть для программирования?

Web – нормальная среда программирования, если правильно понять, что есть что. В VBScript есть все нормальные конструкции структурного программирования (if, while, case, etc). Есть переменные (описывать не обязательно, тип явно не задается). Поддерживаются объекты. Работа с ними обычная – Object.Property, Object.Method. Есть ряд встроенных объектов (Request, Response, Session, Server, Connection, Recordset). Можно доустанавливать другие компоненты (скачивать, покупать, программировать), например для работы с электронной почтой.

Вывод

Понятия "экран", куда можно выводить данные нет. Все, что надо показать пользователю, выбрасывается в выходной поток на языке HTML. Браузер пользователя интерпретирует этот HTML. Для упрощения вывода существует объект Response. Вывод осуществляется с помощью метода Write.

Response.Write("<h2>Hello, world!</h2>").

Так производится запись во внутренний буфер объекта Response. Когда скрипт заканчивает работу, весь буфер выдается клиенту. Надо заметить, что клиент получает "чистый" HTML, таким образом программы на ASP не зависят от клиентского ПО, что очень важно. Если внутри выводимой строки нужно использовать кавычку, кавычка удваивается. Другие методы и свойства Response позволяют управлять выводом. Так Response.Buffer регулирует, получает ли клиент данные по мере из записи в Response, или все сразу по завершении исполнения страницы. Метод Response.Redirect перенаправляет браузер на другую страницу. Чтобы им пользоваться, нельзя до него на странице использовать Response.Write.

Ввод

Программа на ASP не может явно спросить пользователя о чем-то. Она получает данные из других страниц, либо через URL. Передаваемые параметры помещаются во входной поток и доступны через объект Request. Чтобы передать переменную var в программу test.asp, надо написать:

test.asp?var=abc

Чтобы из программы получить значение этой переменной, надо написать:

var = Request("var")

Несколько переменных разделяется знаком &:

test.asp?var1=abc&var2=def

Кроме того, чтобы задавать параметры в URL, можно воспользоваться формами HTML. В вызывающей странице пишем так:

<form method="get" action="test.asp">
<input type=text name="var1" value="default">
<input type=hidden name="var2" value="var2value">
<input type=submit value="Submit Form">
</form>

Так это выглядит:

При этом пользователь увидит форму из одного поля ввода (var1), в нем будет значение по умолчанию "default". Второе поле (var2) будет невидимо и будет передавать всегда фиксированное значение "var2value". Кнопка "Submit Form" завершает заполнение формы и передает все переменные на test.asp (action). Если method="get", переменные передаются через URL (test.asp?var1=default&var2=var2value). Если method="post", передаются вместе с запросом так, что внешне передача переменных не заметна. В вызываемой программе безразлично, какой метод изпользовался (почти). Если у вас нет специальных аргументов за метод GET, используйте метод POST.

Формы

Формы HTML используются для организации диалога с пользователем. Поддерживаются стандартные элементы управления. Все многообразие задается немногими тэгами:

Описание – в документации по HTML.

Взаимосвязь между отдельными страницами

Обычно сервер WWW не хранит состояние приложения, т.е. все запросы взаимонезависимы, и нет стандартного способа понять, что несколько запросов пришли от одного и того же пользователя. Но это очень нужно для разработки полноценных приложений и является одной из главных проблем разработки Web-приложений.

Один из методов решения этой проблемы - cookies. Пользователю при первом обращении выдается специальный идентификатор, после этого браузер пользователя предъявляет этот идентификатор при каждом обращении, и сервер может распознать, что это тот же самый пользователь. Пользователь может отключить cookies, в этом случае этот метод не работает.

ASP, используя cookies, предоставляет программисту более простое средство - объект Session (сессия). Сессия стартует, когда новый пользователь обращается к любому asp-файлу приложения. Сессия заканчивается при отсутствии активности пользователя в течение 20 минут, либо по явной команде. Специальный объект Session хранит состояние сессии. Туда можно записывать переменные, которые доступны из любой страницы в этой сессии. Записать данные в этот объект можно просто:

Session("var") = var

Считать потом еще проще:

var = Session("var")

Сессия, таким образом, – это еще один метод передачи данных между страницами. Одна страница пишет данные в сессию, другая – берет потом оттуда.

Наряду с объектом Session существует объект Application. Если сессия создается для каждого нового пользователя, до Application существует в единственном экземпляре, и может использоваться всеми страницами приложения.

Application("var") = var
var = Application("var")

Управление приложением

Программисту предоставляется возможность реагировать на 4 события: старт/стоп приложения и старт/стоп каждой сессии. Для реализации этих событий предназначен файл global.asa, который должен располагаться в корневом каталоге приложения. Вот его примерный скелет:

<SCRIPT LANGUAGE=VBScript RUNAT=Server>

SUB Application_OnStart
END SUB

SUB Application_OnEnd

END SUB

SUB Session_OnStart

END SUB

SUB Session_OnEnd

END SUB

</SCRIPT>

Нужно "просто" вписать Ваш код на соответствующее место. Нужно заметить, что отлаживать код для global.asa довольно непросто, так как он выполняется при очень специфических обстоятельствах (к примеру при старте или остановке сервера).

Использование внешних компонент

Если на сервере установлены дополнительные компоненты, их можно использовать из ASP. Стандартные объекты (например из библиотек ADO (Connection и Recordset) и Scripting (Dictionary, FileSystemObject)) доступны всегда. Установка новой компоненты обычно состоит в копировании dll-файла в каталог на сервере и ее регистрации с помощью программы regsvr32.exe. [В COM+ используется своя процедура инсталляции объектов, это однако не влияет на использования объектов.]

Создать экземпляр объекта можно так:

Set var  = Server.CreateObject("Class.Object")

Class.Object указываются в документации на компоненту. В переменной var запоминается ссылка на созданный экземпляр объекта. Когда объект не нужен, ссылку нужно обнулить с помощью команды:

Set var = Nothing

Пожалуйста всегда обнуляйте все ссылки на объекты, когда они больше не нужны. Теоретически это должно происходить автоматически при завершении процедуры/страницы, однако в стандартной сборке мусора есть определенные "проблемы".

В остальном использование компоненты зависит от самой этой компоненты.

Работа с базами данных

Из ASP можно легко и просто работать с любыми базами данных. Это делается через две промежуточные технологии: ODBC и ADO.

ODBC позволяет организовать доступ к любым базам данных через унифицированный интерфейс с помощью языка SQL. Специфика конкретных СУБД учитывается при помощи специальных драйверов БД. Такие драйверы существуют для всевозможных СУБД (в частности SQL Server, Oracle, Access, FoxPro). Поддержка ODBC обеспечивается на уровне операционной системы Windows (NT). Настройка – через Control Panel/ODBC. Базовым понятием является источник данных или data source. Источник данных – это совокупность сведений о базе данных, включая ее драйвер, имя компьютера и файла, параметры. Чтобы пользоваться базой надо создать источник данных для нее. Важно, чтобы источник данных был "системным", в отличии от "пользовательского". После этого надо лишь знать имя источника данных. [В настоящее время ODBC отступает перед натиском технологии OLE DB. На практике это однако практически ничего не изменяет. Вместо имени источника данных нужно использовать Connection String, в которой указывается имя ODBC-драйвера и все его параметры.]

ADO – это совокупность объектов, доступных из ASP, позволяющих обращаться к источнику данных ODBC [или OLE DB]. Фактически нужны лишь 2 объекта – Connection, представляющий соединение с базой данных и Recordset, представляющий набор записей, полученный от источника. Сначала необходимо открыть соединение, потом к нему привязать Recordset, потом, пользуясь методами Recordset'а, обрабатывать данные. Вот пример:

<%
Dim Conn, RS, strSQL, strOut
strOut = ""
Set Conn = Server.CreateObject("ADODB.Connection")
Conn.Open "Data-Source-Name"
Set RS = Server.CreateObject("ADODB.Recordset")
strSQL = "SELECT * FROM AGENTS ORDER BY USER_ID"
RS.Open strSQL, Conn
RS.MoveFirst
strOut = strOut & "<P>Here is the data:"
strOut = strOut & "<TABLE BORDER=""1"">"
strOut = strOut & "<TR><TH>USER_ID</TH><TH>Name</TH></TR>"
Do While Not RS.EOF
	strOut = strOut & "<TR>"
	strOut = strOut & "<TD>" & RS.Fields("USER_ID") & "</TD>"
	strOut = strOut & "<TD>" & RS.Fields("NAME") & "</TD>"
	strOut = strOut & "</TR>"
	RS.MoveNext
Loop
strOut = strOut & "</TABLE>"
strOut = strOut & "<HR>"
strOut = strOut & "That's it!"
RS.Close
Set RS = Nothing
Conn.Close
Set Conn = Nothing
Response.Write strOut
%>

Если команда SQL не возвращает данных, recordset не нужен, надо пользоваться методом Conn.Execute(SQL_COMMAND).

Если Вы хотите вызывать хранимые процедуры сервера БД с параметрами, нужно воспользоваться объектом Command, который в свою очеред содержит объекты Parameter.

Методики программирования, советы

Описание переменных

VBScript - очень нетребовательный к программисту язык. Так он не требует описывать переменные и не содержит явных типов данных. Все переменные принадлежат одному типу Variant. Из-за отсутствия описаний могут произойти очень трудно обнаруживаемые ошибки. Одна опечатка может стоить полдня поисков.

Однако, есть возможность явно потребовать описания переменных. Для этого первой строкой в ASP-файле нужно написать Option Explicit. После этого обращение к переменной, которая не была объявлена с помощью Dim, вызывает ошибку с указанием номера строки.

Кстати, где расположены описания Dim в процедуре - совершенно не важно. Они могут стоять как до использования переменной, так и после, и даже в цикле. Видимо они отрабатываются препроцессором. Явно задать тип переменной с помощью Dim Var as Typ, как в Visual Basic, все равно нельзя.

Чередование ASP/HTML

Если нужно выдать большой кусок HTML, можно не пользоваться Response.Write. Если в asp-файле встречается кусок текста вне скобок <% %>, он трактуется просто как HTML, который надо вывести. Пример:

<% If var="VAL" Then %>
	Дорогой друг!
	…
<% Else %>
	Извините, вам сюда нельзя
	…
<% End If %>

Обработка ошибок

Для отслеживания ошибок используется специальный объект Err. Он устанавливается в ненулевое значение, если предыдущая команда породила ошибку. Ее можно проверять с помощью If, и таким образом реагировать на ошибки. Чтобы из-за ошибки не прерывалось выполнение программы, в начале нужно включить команду

On Error Resume Next

Включение других файлов

Можно выносить повторяющийся код в отдельный файл, и подключать к разным другим по мере необходимости с помощью команды include. Это очень удобно, если вы хотите вынести повторяющийся код в отдельный файл и использовать снова и снова в разных страницах:

<!--#include file="filename.inc" -->

Важно: все includes в тексте отрабатываются до исполнения файла. Т.е. даже если include стоит внутри if, то сначала будут включены все includes во всех ветках, и только потом, во время исполнения, будет принятно решение, какую ветку выполнять. Т.е. следующий код не дает условного включения файлов:

<% If var="VAL" Then %>
	<!--#include file="filename1.inc" -->
<% Else %>
	<!--#include file="filename2.inc" -->
<% End If %>

Обработка форм

Если надо что-то спросить у пользователя и на основании этого что-то сделать, в простейшем случае создается два файла: один с формой, второй – с ее обработчиком. Обработчик выполняет все действия. Пример:

form.htm:
<form method="post" action="run.asp">
<input type=text name="var1" value="default">
<input type=hidden name="var2" value="var2value">
<input type=submit value="Обработать">
</form>

run.asp:
var1 = Request("var1")
var2 = Request("var2")
…
что-то делаем
…
Response.Write("все хорошо!<br>”)

Рекурсивная обработка форм

Удобный метод состоит в том, чтобы сбор данных и обработку осуществлял один и тот же файл. Для этого пишется asp, в котором есть разные разделы. Специальная переменная отвечает за выбор раздела при запуске. Пример:

test.asp:
<%
Action = Request("Action")
If Action = "" Then
	' Action не заполнен – значит надо показать форму
	Action = "FORM"
End If
Select Case Action
Case "FORM"
	' Показываем форму
	' action- сам на себя, Action="PROCESS", т.е.
	' второй раз пойдет по другой ветке
%>
<form method="post" action="test.asp">
<input type=hidden name="Action" value="PROCESS">
<input type=text name="var1" value="default">
<input type=submit value="Обработать">
</form>
<%
Case "PROCESS"
	' Обрабатываем
var1 = Request("var1")
var2 = Request("var2")
…
что-то делаем
…
Response.Write("все хорошо!<br>")
End Select
%>

Переменные HTTP

Запрос от браузера, кроме запрашиваемой страницы несет еще некоторые данные. Эти данные, например, IP-адрес клиента, доступны через специальные переменные объекта Request. IP-адрес – Request("REMOTE_ADDR"). Другие - см.документацию (ASPSamp\Samples\srvvar.asp).

Переадресация

Очень легко написать на ASP скрипт, который будет производить некоторые расчеты, и в зависимости от результатов переадресовывать браузер на разные URL (например, подставлять нужный баннер). Делается это так:

Response.Redirect "somewhere.html"

Только надо следить, чтобы до выполнения команды redirect ничего не было записано в Response (даже коментарии HTML).

Электронная почта

Одна из часто встречающихся задач – отправить электронную почту с Web-страницы. На первый взгляд, можно просто написать

<FORM ACTION="mailto:user@host.com">

Но это приводит к тому, что при отправке формы делается попытка на клиентской машине запустить почтовую программу и создать новое сообщение с данными формы. Если это не получается (почтовая программа не настроена, пользователь не отправил почту, и т.д.) - письмо и не будет отправлено. Гораздо надежнее работает серверное решение.

Для этого существуют внешние компоненты, есть и бесплатные. Например, компонента Jmail от Dimac. Все, что для нее нужно – это адрес SMTP-сервера. Вот пример ее использования:

On Error Resume Next
Set Mailer = Server.CreateObject("JMail.SMTPMail")
If err<>0 Then
	Response.Write("Невозможно создать объект")
Else
	Mailer.ServerAddress = SMTP_SERVER
	Mailer.Sender = EMAIL
	Mailer.Subject = "Service: Delivery order"
	Mailer.AddRecipient ADMIN_EMAIL
	Mailer.Body = "------------------------------------" & chr(10)
	Mailer.AppendText "body text"
	Mailer.Execute
	If err<>0 Then
		Response.Write("Mail error")
	Else
		Response.Write("Mail send Ok")
	End If
End If
Set Mailer = Nothing