» ASP
для новичков
» Главная
страница
»
ASP
для новичков
Формы
Формы являются, пожалуй,
единственным средством получения информации от удаленного пользователя. Однако
при разработке Web-приложений ASP.NET нет нужды всегда пользоваться стандартными
средствами HTML. В конце концов, у нас есть компоненты Web Forms (Web-формы).
Они-то нам и пригодятся. Схема работы достаточно проста.
Пользователь вносит данные в органы
ввода информации, которые разработчик размещает на странице, и нажимает кнопку,
отсылающую данные на сервер. На сервере их принимает программа, обрабатывает, и
в результате обработки генерирует новую Web-страницу, которую и отсылает
пользователю в качестве ответа на его действия. Схема, как видим, очень проста.
Однако встает следующий вопрос. А
как разработчик будет создавать страницу с ответом? Первый пример приложения
ASP.NET всего лишь показывает, как можно изменять внешний вид Web-страницы.
Неужели потребуется на одной странице разместить два набора элементов оформления
— один для формы, второй для ответа на действия пользователя, а затем по очереди
делать их видимыми? Естественно, подобную схему работы нельзя назвать изящной.
На самом деле, все будет намного
проще, если мы воспользуемся объектом ASP.NET с наименованием HttpResponse. Этот
объект является встроенным, т. е. разработчику нет необходимости самостоятельно
создавать экземпляр объекта для работы, он доступен постоянно. Данный объект
предназначен для передачи информации с WWW-сервера в браузер удаленного
пользователя по протоколу HTTP. Каждый раз, когда необходимо передать
пользователю новую Web-страницу, разработчик может воспользоваться данным
объектом, и с его помощью передать динамически сгенерированную страницу.
А как получать данные, введенные
пользователем, от формы? Для этих целей существует встроенный объект
HttpRequest, в котором находятся данные, получаемые сервером.
Попробуем создать проект с
наименованием form. Он будет состоять из двух страниц. На первой мы разместим
только стандартные органы управления HTML. Попробуем запросить у пользователя
его имя и адрес электронной почты. После того, как удаленный пользователь введет
запрошенные данные и нажмет не подтверждающую кнопку, эти данные будут
отправлены на вторую страницу, которая будет заниматься обработкой данных,
полученных из формы, размещенной на первой странице.
Так как первая страница не должна
будет производить каких-либо действий, ее можно создать при помощи компонентов,
размещенных на вкладке HTML. Нам потребуется два компонента Label, два
однострочных поля текстового ввода TextFieid и одна кнопка submit Button.
HTML-код разработанной нами страницы в том виде, как он создан Visual Studio
.NET, приведен в листинге 3.3. Было внесено единственное изменение. По умолчанию
Visual Studio .NET считает, что любая создаваемая страница является исполняемой
частью ASP-приложения, и поэтому в наш листинг была добавлена первая строка
следующего вида:
<%0 Page Language="vb"
AutoEventWireup="false"
Codebehind="WebForml.aspx.vb" Inherits="form.WebForml"%>
Она сигнализирует WWW-серверу о
том, что данная Web-страница должна быть компилирована джиттером, как часть
приложения. В нашей странице нет каких-либо органов управления ASP, поэтому ее
совершенно необязательно пропускать через процедуру компиляции, тем более, что
эта процедура занимает дополнительное время при отправке страницы удаленному
пользователю. Следовательно, эту строку можно безболезненно удалить из HTML-кода
нашей страницы. Получившийся код приведен в листинге 3.3.
Листинг 3.3
<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<titlex/title>
<meta name="GENERATOR"
content="Microsoft Visual Studio.NET 7.0">
<meta
name="CODE_LANGUAGE" content="Visual Basic 7.0">
<meta
name="vs_defaultClientScript" content="JavaScript">
<meta
name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body MS_POS ITIONING="Gr
idLayout " >
<form id="Forml"
raethod="post"
action="http:
/Ylocalhost/form/WebForm2 . aspx">
<INPUT style="Z-INDEX:
101; LEFT: 38px; POSITION: absolute; TOP: 54px"
type="text" name="fl">
<INPUT style="Z-INDEX: 102; LEFT: 45px; POSITION: absolute;
TOP: 183px" type="submit"
value=" подтвердить ">
<INPUT style="Z-INDEX:
103; LEFT: 39px; POSITION: absolute;
TOP: 128px" type="text"
name="f2">
<DIV style="DISPLAY:
inline; Z-INDEX: 104; LEFT: 38px; WIDTH: 320px;
POSITION: absolute; TOP:
21px; HEIGHT: 19px" ms_positioning=" FlowLayout " > Введите Ваше имя
<DIV style="DISPLAY:
inline; Z-INDEX: 105; LEFT: 43px; WIDTH: ЗЗбрх;
POSITION: absolute; TOP:
95px; HEIGHT: 19px" ms_positioning=" FlowLayout "> Введите Ваш адрес
электронной почты
</form>
</body>
</HTML>
Далее в книге мы будем приводить
обычно два варианта HTML-кода для каждои Web-страницы: код, который формируется
Visual Studio .NET, и тот, который будет получен браузером удаленного
пользователя. Естественно, они будут отличаться, но в данном случае мы создали
обычную Web-страницу, поэтому ее HTML-код на сервере и в браузере пользователя
будут идентичны.
Необходимо, естественно, сделать
несколько комментариев к приведенному коду. Основа взаимодействия формы с
обрабатывающей Web-страницей кроется в теге <form>. В нашем случае он
имеет следующий вид:
<form id="Forml"
method="post"
action="http://localhost/forra/WebForm2.aspx">
Особое внимание следует обратить на
атрибуты с наименованиями method и action. Атрибуту method приписано значение
post. Этот атрибут указывает метод, при помощи которого будет передаваться
информация обрабатывающему приложению. Всего может быть использовано два метода
— ? --r- и Get. Соответственно, в нашем случае мы выбрали первый вариант.
Различия между ними будут отчетливо видны в нашем следующем примере, когда мы
рассмотрим механизм передачи данных из формы с методом Get.
Атрибут action в качестве своего
значения содержит URL того приложения, которое будет обрабатывать данные,
введенные пользователем в органы управления формы. В нашем случае мы указываем
на ASP-страницу с наименованием webForma .aspx. Именно она примет данные из
формы, обработает их и сформирует новую Web-страницу, которая будет отправлена
удаленному пользователю.
Для ввода данных удаленным
пользователем мы разместили на Web-странице два однострочных поля ввода. В одно
из них предполагается ввод имени пользователя, во второе — его адреса
электронной почты. Первое поле ввода задано следующей конструкцией:
<INPUT style="Z-INDEX:
101; LEFT: 38px; POSITION: absolute; TOP: 54px"
type="text" narae="fl">
При помощи атрибута type мы задаем
тип создаваемого органа ввода данных. Значение text указывает, что мы создаем
однострочное поле ввода. Помимо этого необходимо обязательно указать
наименование поля. Для данного поля мы устанавливаем имя fi, при помощи атрибута
name. Для второго поля, куда пользователь будет вводить свой адрес электронной
почты, было установлено наименование f2.
После того, как пользователь введет
данные в предназначенные для этого поля, и нажмет на кнопку, отсылающую данные
на сервер, управление переходит ко второй странице, которая носит наименование
webForm2.aspx. Займемся ее созданием.
На второй странице нам достаточно
разместить всего два компонента Label, в которых мы отобразим полученные данные.
Однако перед тем как их отобразить, данные необходимо получить. Для этого мы
воспользуемся встроенным объектом HttpRequest. В его состав входит коллекция
Form, которая содержит все данные, введенные пользователем. Для доступа к ним
осуществляется обращение при помощи наименования органа управления или его
порядкового номера. В листинге 3.4 приведен код класса, реализующего
обрабатывающую Web-страницу.
Листинг 3.4
Public Class WebForm2
Inherits System.Web.UI.Page
Protected WithEvents Labell
As System.Web.Ul.WebControls.Label
Protected WithEvents Label2
As System.Web.UI.WebControls.Label
# Region " Web Form Designer
Generated Code "
'This call is required by
the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
End Sub
Private Sub Page_Init(ByVal
sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call
is required by the Web Form Designer 'Do not modify it using the code editor.
InitializeComponent( )
End Sub
#End Region
Private Sub Page_Load(ByVal
sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Put user code to initialize
the page here
Dim n, email As String n =
Request.Form ("fl")
email = Request.Form("f2")
Labell.Text = "Уважаем ый " + n
Label2.Text = "Мы
обязательно отправим Вам письм о по Вашему адресу — " +
email
End Sub
End Class
Как следует из листинга, получение
и разбор данных будут производиться при загрузке страницы. Единственная функция,
измененная разработчиком, является обработчиком события page_Load. В этом
обработчике мы объявляем две переменные типа string. Переменная n предназначена
для хранения имени пользователя, а переменная email, естественно, будет хранить
его адрес электронной почты. При этом мы используем обращение к элементам
коллекции Form по их наименованию. Так, имя пользователя мы получаем следующим
образом:
n = Request.Form("fl")
Как видим, все крайне просто.
Соответственно, после того, как мы получаем введенные данные, мы соответствующим
образом изменяем свойство Text Элементов Label. После того, как пользователь введет
свои данные и нажмет на кнопку, будет : отображена следующая Web-страница. Ее
внешний вид показан на рис. 3.10.
Код этой Web-страницы в браузере
приведен в листинге 3.5.
Листинг 3.5
<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<title></title>
<meta name="GENERATOR"
content="Microsoft Visual Studio.NET 7.0">
<meta
name="CODE_LANGUAGE" content="Visual Basic 7.0">
<meta
name="vs_defaultClientScript" content="JavaScript">
<meta
name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5"> :'
</HEAD>
<body
MS_POSITIONING="GridLayout">
<form name="Form 1 " method="post" action="WebForm2.aspx" id="Form 1
">
<input type="hidden"
name="__VIEWSTATE"
value="dDwtMTEwMTE10TQwMDtOPDtsPGk8MT47PjtsPHQ80
2w8aTwxPjtpPDM+Oz47bDxOPH
A8cDxsPFRleHQ7PjtsPNCjOLLQsNC20LDQtdC80YvQuSDQmN
CzOL7RgNGMOz4+Oz470z47dDx
wPHA8bDxUZXhOOz47bDzQnNGLINC+OLHRj9C30LDRgtC10L
vRjNC90L4gOL7RgtC/OYDQsNCy
OLjQvCDQktCwOLwgOL/QuNGBOYzQvNC+INC/OL4gOJLQs
NGIOLXQvNGDINCwOLTRgNC10YHRg
yAtIHdlYmlhc3RlckBiaHYuc3BiLnN10z4+Oz470z47Pj47P
j47Pg==" />
<span id="Labell"
style="Z-INDEX: 101; LEFT: 43px; POSITION: absolute;
TOP: З0рх">Уважаемый
Игорь</sраn>
<span id="Label2"
style="Z-INDEX: 102; LEFT: 44px; POSITION: absolute; TOP: 75рх">Мы
обязательно отправим Вам письмо по Вашему
адресу
—Webmaster@bhv.spb.su</span>
</form>
</body>
</HTML>
А теперь рассмотрим специфику
работы с формой в том случае, если мы используем метод передачи данных get.
Изменений придется внести совсем немного. В HTML-коде первой страницы необходимо
всего лишь изменить значение атрибута method тега <form>. Для данного
атрибута требуется установить значение get. А вот обрабатывающую Web-страницу
придется переработать несколько серьезнее. Ее код приведен в листинге 3.6.
Листинг 3.6
Public Class WebForm2
Inherits System. Web. UI.
Page
Protected WithEvents Labell
As System. Web. Ul.WebControls. Label
Protected WithEvents Label2
As System. Web. UI .WebControls. Label
#Region " Web Form Designer
Generated Code "
'This call is required by
the Web Form Designer.
<System. Diagnostics .
DebuggerStepThrough ()> Private Sub Initial! zeConponentO
End Sub
Private Sub Page_Init (ByVal
sender As System. Object, ByVal e As System. EventArgs) Handles MyBase.Init
'CODEGEN: This method call
is required by the Web Form Designer
'Do not modify it using the
code editor. InitializeComponent ( )
End Sub
#End Region
Private Sub Page_Load( ByVal
sender As System. Object, ByVal e As System. EventArgs) Handles MyBase.Load
'Put user code to initialize
the page here
Dim n, email As String
n =
Request.QueryStringC'fl")
email = Request.
QueryString("f2")
Labell. Text = "Уважаемый "
+ n
Label2 . Text = "Мы
обязательно отправим Вам письмо по Вашему адресу — " + email
End Sub
End Class
Как видно, для получения данных,
введенных пользователем, мы все так же используем встроенный объект Request. Но
обращаемся уже не к коллекции Form, а к свойству Querystring. Это свойство также
является коллекцией, и мы можем обращаться к ее элементам просто через указание
их наименований. Мы не будем сейчас приводить иллюстраций, на которых будут
показаны эти страницы при
отображении их браузером, так как они практически идентичны страницам из
прошлого примера. Есть только одно отличие. URL обрабатывающей Web-страницы
будет выглядеть следующим образом:
http://localhost/form/WebForm2.aspx?fl=
%DO%98%DO%B3%DO%BE%Dl%80%Dl%8C&f2=
WebmasterSbhv . spb . su
Таким образом, все данные,
введенные пользователем, были переданы через строку URL, а уже потом были
извлечены из нее обрабатывающим приложением. При этом следует обратить внимание,
что текст, записанный русскими символами, подвергся URL-кодированию, о котором
мы уже говорили выше, а именно, все символы русского языка были переданы при
помощи их шестнадцатеричных кодов.
Теперь встает вопрос, какой же тип
передачи данных из формы предпочтительнее использовать — Get или Post? Здесь
следует опираться как раз на специфику передачи данных. На строку URL изначально
установлено ограничение по длине. Более того, вся эта строка видна пользователю
вместе с именами полей, в том числе и скрытых, и с их значениями, что позволяет
пользователю увидеть некоторую часть логики работы приложения и изменить
вводимые значения и наименования полей ввода. Встает вопрос, предоставление
подобной свободы пользователю — это хорошо? Даже для обычных приложений
предоставление слишком большой свободы пользователю не приветствуется, а уж в
Web-приложениях это совсем недопустимо, так как они в силу своей природы много
больше уязвимы для вторжения. Поэтому всегда стоит использовать метод передачи
данных post, если нет каких-либо особых причин использовать именно Get. Кстати,
я не могу себе представить хотя бы одной причины, которая жестко обязывала бы
разработчика использовать именно метод Get.
Есть и еще один вариант работы с
данными, введенными пользователями. Для этого мы можем вообще не использовать
стандартные формы HTML, а воспользоваться компонентами Web Forms. Разработчику
будет достаточно легко получить введенные пользователем данные, но встанет
другой вопрос — как передать данные другой странице. Мы уже не помещаем их в
выходной поток, который будет принимать и анализировать другая страница.
Разработчик может воспользоваться неким аналогом глобальных переменных. Как мы
уже знаем, встроенный объект Application доступен для всех страниц, входящих в
состав одного приложения. В данном объекте приложение может создавать свои
глобальные переменные. Этой возможностью мы и воспользуемся.
Для начала объявим новый проект
ASP.NET с названием form2. Как и в первом примере с формой, мы создадим две
страницы. На первой странице мы разместим компонент TextBox, реализующий
текстовое поле, метку Label, в которой будет указан некий текст подсказки, и
кнопку Button, которая и
запустит процесс обработки информации. В нашем случае мы запрашиваем имя
пользователя, сохраняем его в аналоге глобальной переменной, а затем вторая
страница отображает введенное имя пользователя. Для этого на второй странице мы
просто разместим один-единственный компонент Label, свойство Text которого мы
будем задавать при загрузке страницы. Но этот механизм лучше уже рассмотреть при
помощи листингов. Начнем мы с первой страницы, на которой размещены основные
органы ввода информации. Внешний вид ее в среде разработки был продемонстрирован
на рис. 3.11. А в листинге 3.7 приведен HTML-код данной страницы.
Листинг 3.7
<%@ Page Language="vb"
AutoEventWireup="false"
Codebehind="WebForml.aspx.vb" Inherits="form2.WebForml "%>
<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<titlex/title>
<meta name="GENERATOR"
content="Microsoft Visual Studio.NET 7.0">
<meta
name="CODE_LANGUAGE" content="Visual Basic 7.0">
<meta
name="vs_defaultClientScript" content="JavaScript">
<meta
name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body
MS_POSITIONING="GridLayout">
<form id="Forml"
method="post" runat="server">
<asp:TextBox
id="TextBoxl" style="Z-INDEX: 101; LEFT: 35px;
POSITION: absolute; TOP:
39px" runat="server"x/asp:TextBox>
<asp:Button id="Buttonl"
style="Z-INDEX: 102; LEFT: 40px;
POSITION: absolute; TOP:
86px" runat="server"
Text="Подтвердить"></asp:Button>
<asp:Label ld="Labell"
style="Z-INDEX: 103; LEFT: 38px;
POSITION: absolute; TOP:
13px" runat="server">
Укажите Ваше
имя</азр:Label>
</form>
</body>
</HTML>
Однако одного HTML-кода будет явно
недостаточно для работы приложения. Необходимо запрограммировать обработчик
нажатия пользователем на кнопку. В листинге 3.8 приведен полный код класса,
соответствующего первой странице. Естественно, в нем приведен и обработчик
нажатия на кнопку.
Листинг 3.8
Public Class WebForml
Inherits System.Web.UI.Page
Protected WithEvents
TextBoxl As System.Web.UI.WebControls.TextBox
Protected WithEvents Labell
As System.Web.UI.WebControls.Label
Protected WithEvents Buttonl
As System.Web.UI.WebControls.Button
#Region " Web Form Designer
Generated Code "
' This call is required by
the Web Form Designer.
<System.Diagnostics.DebuggerstepThrough( )> Private Sub
InitializeConponent0
End Sub
Private Sub Page_Init (ByVal
sender As System. Object, ByVal e
As System. EventArgs)
Handles MyBase.Init
'CODEGEN: This method call
is required by the Web Form Designer
'Do not modify it using the
code editor. InitializeComponent ( )
End Sub
#End Region
Private Sub Page_Load (ByVal
sender As System. Object, ByVal e As System. EventArgs) Handles MyBase.Load
'Put user code to initialize
the page here
End Sub
Private Sub Buttonl_Click
(ByVal sender As System. Object, ByVal e
As System. EventArgs)
Handles Buttonl. Click
Application . Clear ( )
Application. Add ("NAME",
TextBoxl .Text)
Response . Redirect (
"WebForm2 . aspx" )
End Sub
End Class
Нас будет больше всего интересовать
код процедуры Buttoni_ciick. В ней находятся всего три оператора. Первый
оператор очищает ранее установленные глобальные переменные. Второй оператор
является вызовом метода Add объекта Application. Мы просто создаем переменную с
именем name, и приписываем ей значение, указанное пользователем в поле
текстового ввода. Последний оператор заставляет браузер пользователя послать
запрос серверу на отображение страницы webForm2.aspx.
Теперь обратимся ко второй странице
с наименованием webForm2.aspx. На ней мы разместили всего лишь один текстовый
объект Label. HTML-код этой страницы приведен в листинге 3.9.
Листинг 3.9
<%@ Page Language="vb"
AutoEventWireup="false" Codebehind="WebForm2.aspx.vb"
Inherits=" f orm2 . WebForm2
"%>
<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<titlex/title>
<meta name="GENERATOR"
conter.t="Microsoft Visual Studio.NET 7.0">
<meta name="CODE
LANGUAGE" content="Visual Basic 7.0">
<meta
name="vs_defaultClientScript" content="JavaScript">
<meta name="vs
targetSchema"3
content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body
MS_POSITIONING="GridLayout">
<form id="Forml"
method="post" runat="server">
<asp:Label id="Labell"
style="Z-INDEX: 101; LEFT: 42px;
POSITION: absolute; TOP:
34px" runat="server">Label</asp:Label>
</form>
</body>
</HTML>
А код класса, соответствующего
данной странице, показан в листинге 3.10.
Ли стинг 3.10
Public Class WebForm2
Inherits System.Web.UI.Page
Protected WithEvents Labell
As System.Web.Ul.WebControls.Label
fRegion " Web Form Designer
Generated Code "
'This call is required by
the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent( )
End Sub
Private Sub Page_Init(ByVal
sender As System.Object, ByVal e
As System.EventArgs) Handles
MyBase.Init
'CODEGEN: This method call
is required by the Web Form Designer
'Do not modify it using the
code editor.
InitializeComponent ()
End Sub
#End Region
Private Sub Page_Load(ByVal
sender As System.Object, ByVal e
As System.EventArgs) Handles
MyBase.Load
'Put user code to initialize
the page here
Labell.Text = "Здравствуйте,
" + Application.Item(O)
End Sub
End Class
Перед тем, как страница будет
отображена в браузере, следует прочитать текст, записанный в элемент объекта
Application, и с помощью полученного текста сформировать внешний вид текстовой
метки, размещенной на странице. Для этого следует воспользоваться обработчиком
события page_Load, который автоматически генерируется средой разработки для
каждой страницы, входящей в состав какого-либо приложения ASP.NET. Данный
обработчик будет выполняться каждый раз при загрузке данной страницы в браузер
удаленного пользователя. Поэтому мы и вставили в его тело оператор, который
формирует свойство Text объекта Labeli при помощи первого элемента объекта
Application. Необходимо помнить, что нумерация элементов коллекций начинается с
нуля, поэтому первый элемент коллекции будет иметь нулевой индекс. Чем хорош подобный способ получения
информации от пользователя? Разработчик получает возможность использовать всю
мощь функциональных компонентов Web Forms, он не ограничен устаревшими
элементами стандартных HTML-форм. Однако проблемы данного способа заключены не в
приеме информации от пользователя, а в способе ее передачи на сервер.
Использование глобальных переменных может быть хорошо в тех случаях, когда
разработчик точно уверен, что в тот промежуток времени, когда один пользователь
введет свои данные и передаст их на сервер, а тот возвратит ответ, никто другой
не введет иные данные. Потому что переменная в нашем случае — одна и та же для
всех пользователей, которые будут запрашивать наши страницы. Следовательно,
вполне возможна ситуация, когда первый пользователь получил страницу с формой,
начал ее заполнять, но пока он это делает, другой пользователь тоже получил
форму и заполнил ее быстрее, чем первый. Тогда второй пользователь первым нажмет
кнопку подтверждения, и именно его данные будут сохранены в глобальной
переменной. Следовательно, когда первый пользователь отправит свои данные, ему в
ответ будет послана информация, базирующаяся на данных второго пользователя.
Избавиться от этой ситуации помогает принудительная очистка глобальной
переменной перед отправкой данных из формы, как это сделано в нашем примере. Но
это все равно не панацея, так как требуемое логикой приложения время жизни
данных, хранимых в подобных глобальных переменных, может быть достаточно
большим, а большой поток посетителей будет достаточно часто обновлять данные
глобальных переменных.
Еще одно решение этой проблемы
может заключаться в блокировке объекта Application. В разделе, посвященном
данному встроенному объекту, были описаны методы Lock и unlock. Вызов метода
Lock закрывает объект Application от изменений иными пользователями. После
окончания работы с данным объектом, можно (и следует) открыть объект для всех
остальных пользователей, при помощи метода unlock. В том случае, если сервер, на
котором базируется приложение ASP.NET, достаточно быстро работает, использование
подобной методики работы может быть вполне оправданным. Но в этом случае, одна
переменная может использоваться цепочкой только из двух страниц. Таким образом
нельзя создавать последовательность из трех или более страниц, связанных одним
комплектом глобальных переменных. Дело в том, что при такой схеме переменная
будет жить не только во время ее обработки сервером, но и во время передачи
страниц пользователю и, что самое главное, в то время, пока сервер может ожидать
ответа пользователя. Это неприемлемо. Следует получить данные, заблокировать
объект Application, записать данные в его основную коллекцию, передать их другой
странице для обработки и/или записи в базу данных и разблокировать объект
Application. Эта схема вполне работоспособна и позволяет обойтись без ощутимого
замедления работы.
Теперь рассмотрим ситуацию, когда
данные, вводимые пользователем, должны удовлетворять неким условиям. Например,
приложение может требовать ввода телефона или адреса электронной почты.
Естественно, необходимо проконтролировать, какие именно данные вводит
пользователь. Возраст должен быть целым положительным числом в четко
ограниченном диапазоне, например, от десяти до девяноста. В адресе электронной
почты должен присутствовать знак "@" и, как минимум, одна точка в доменном
имени. Почтовый индекс России должен состоять из шести цифр. И так далее.
Естественно, ошибки, обусловленные
как невнимательностью пользователя, так и преднамеренным вводом неверных данных,
просто неизбежны. И, уж поверьте моему опыту, их будет немало. Следовательно,
необходимо проверять вводимые пользователем данные хотя бы на предмет
соответствия некоему формату. Как это сделать?
Функционально все способы можно
разделить на два типа — выполняемые на сервере и выполняемые на стороне
пользователя. Проверка на стороне сервера может выполняться самим приложением.
По результатам проверки эти данные либо передаются для записи и обработки, либо
формируется страница с сообщением об ошибке, которая отправляется пользователю.
Этот вариант удобен для разработки, так как программист будет пользоваться тем
средством разработки и тем языком, который наиболее привычен для него. Однако подобная схема имеет
очень серьезный недостаток — слишком большое время реагирования на ошибку,
допущенную пользователем. А именно, данные сначала уйдут по линиям связи (как
всегда, слишком медленным, это, похоже, неотъемлемое свойство всех линий связи),
затем будут обрабатываться сервером, а потом снова передаваться по искомым
линиям связи обратно пользователю. Другими словами, узким местом будут именно
линии передачи информации, которые в данной схеме используются два раза.
Неразумно.
Однозначное предпочтение
разработчик должен отдавать механизмам проверки, выполняющимся на стороне
пользователя. В этом случае ему необходимо воспользоваться соответствующим
языком сценариев. Несмотря на то, что ASP-разработчик пользуется языком из
семейства Visual Basic, для создания сценариев, функционирующих на стороне
пользователя, настоятельно рекомендуется использовать JavaScript. Причины этого
мы уже обсуждали.
Visual Studio .NET конечно же
позволяет интегрировать в разрабатываемые Web-страницы блоки кода, исполняемого
на стороне клиента. Но писать программы проверки значений на языках сценариев,
особенно для проверки текстовых шаблонов, является одним из самых нудных занятий
в программировании, по моему мнению. И вот здесь нас ожидает один очень приятный
сюрприз. Visual Studio .NET предлагает разработчику несколько механизмов
проверки достоверности, которые сами автоматически осуществляют контроль
введенных пользователем данных. Причем, что самое важное, они делают это без
отправки данных на сервер. Вся проверка происходит на сто-роне пользователя.
Рассмотрим тривиальный пример.
Создадим форму для получения
возраста пользователя. Ограничим вводимое значение интервалом от десяти до
девяноста. В том случае, если пользова-тель введет неверные данные, необходимо
будет его предупредить об ошиб-ке. Нам потребуется практически такая же форма,
как и в предыдущем примере с использованием объекта Application. Естественно,
придется не-сколько изменить текст подсказки, и добавить компонент с
наименованием RangeValidator. Основное программирование будет производиться
простым заданием свойств данного компонента.
В свойстве ErrorMessage
следует установить текст предупреждения, которое будет отображаться на странице
в случае внесения неверных данных пользова-телем. Также следует обратить особое
внимание на группу свойств Behavior. Прежде всего, надо установить какое именно
устройство ввода данных будет обрабатываться данным компонентом проверки
соответствия шаблону. При разработке действует основное правило — один компонент
проверки обрабатывает одно устройство. Разработчик может, конечно, оставить
какое-либо устройство ввода данных не подстрахованным компонентом проверки, если
данная информация не является критичной, или присоединить к нему два различных
компонента проверки соответствия шаблону, но заставить один компонент
контролировать несколько органов ввода не получится.
Итак, в свойстве controiToVaiidate
следует установить имя того устройства ввода данных, которое будет
контролироваться компонентом проверки соответствия шаблону. Затем в свойстве
туре надо указать, какой тип данных должен быть введен в контролируемое поле.
Компонент проверки позволяет обрабатывать типы string, integer, Double, Date и
currency, т. е. практически весь спектр типов данных. Также следует свойству
Enabledientscript придать значение True, чтобы Visual Studio .NET мог
сгенерировать код проверки данных на выбранном языке сценариев.
Остается лишь указать минимальное и
максимальное возможные значения. Они устанавливаются при помощи свойств
Minimumvaiue и MaximumValue, соответственно. HTML-код получившейся Web-страницы
приведен в листинге 3.11.
Листинг 3.11
<%@ Page Language="vb"
AutoEventWireup="false"
Codebehind="WebForml.aspx.vb"
Inherits="form2.WebForml"%>
<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<titlex/title>
<meta name="GENERATOR"
content="Microsoft Visual Studio.NET 7.0">
<meta name="CODE_LANGUAGE"
content="Visual Basic 7.0">
<meta
name="vs_defaultClientScript" content="JavaScript"> <meta
name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body
MS_POSITIONING="GridLayout"> <form id="Forml" method="post"
runat="server">
<asp:TextBox id="TextBoxl"
style="Z-INDEX: 101; LEFT: 35px;
POSITION: absolute; TOP: 39px"
runat="server"x/asp:TextBox>
<asp:Button id="Buttonl"
style="Z-INDEX: 102; LEFT: 40px;
POSITION: absolute; TOP: 86px"
runat="server" Text="rioflTBepWTb "></asp: Button>
<asp:Label id="Labell"
style="Z-INDEX: 103; LEFT: 38px; POSITION: absolute; TOP: 13px"
runat="server">
Укажите Ваш воз
pac т </asp:Label>
<asp:RangeValidator
id="RangeValidatorl" style="Z-INDEX: 104;
LEFT: 229px; POSITION: absolute;
TOP: 26px" runat="server" ЕггогМеззаде="Возраст должен находиться в промежутке
от 10 до 90" ControlToValidate="TextBoxl" MaximumValue="90" MinimumValue="10"
Туре="Integer">
</asp:RangeValidator>
</form> » </body> (
</HTML>
Код класса, соответствующего
разработанной Web-странице, приведен в листинге 3.12. Следует обратить внимание,
что обработчик нажатия кнопки несколько отличается от обработчика из предыдущего
примера. Теперь добавлен вызов метода lock для объекта Application, который
блокирует его . Разблокировка объекта должна быть произведена при
загрузке второй страницы, которая ответит пользователю, что его данные успешно
приняты и обработаны.
Л истинг 3.12
Public Class WebForml
Inherits System.Web.UI.Page
Protected WithEvents TextBoxl As
System.Web.UI.WebControls.TextBox
Protected WithEvents Labell As
System.Web.UI.WebControls.Label
Protected WithEvents
RangeValidatorl As System.Web.UI .WebControls .RangeValidator
Protected WithEvents Buttonl As
System.Web.UI.WebControls.Button #Region " Web Form Designer Generated Code "
'This call is required by the Web
Form Designer.
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
End Sub
Private Sub Page_Init(ByVal sender
As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is
required by the Web Form Designer 'Do not modify it using the code editor.
InitializeComponent( )
End Sub
#End Region
Private Sub Page_Load(ByVal sender
As System.Object, ByVal e
As System.EventArgs) Handles
MyBase.Load
'Put user code to initialize the
page here
End Sub
Private Sub Buttonl_Click(ByVal
sender As System.Object, ByVal e
As System.EventArgsT Handles
Buttonl.Click
Application.Clear( )
Application.Lock( )
Application.Add("AGE",
TextBoxl.Text)
Response.Redirect("WebForm2.aspx"
)
End Sub
End Class
Однако во всех этих листингах не
показано, как именно будет контролироваться ввод пользователем данных.
Действительно, не следует забывать, что тот HTML-код, который разработчик видит
при создании страницы, содержит специфические теги ASP. Поэтому, когда
пользователь запросит данную страницу, ее сначала пропустит через себя джиттер,
создав приложение, а затем с правильным HTML-кодом отправит удаленному
пользователю. Ли
стинг 3.13
< ! DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.0 Transitional//EN">
<html> ' <head>
<titlex/title>
<meta name="GENERATOR"
content="Microsoft Visual Studio. NET 7.0">
<meta name="CODE LANGUAGE"
content="Visual Basic 7.0">
<meta name="vs
defaultClientScript" content=" JavaSpript">
<meta name="vs_targetSchema"
content="http: //schemas.microsoft.com/ intellisense/ie5">
</HEAD>
<body
MS_POSITIONING="GridLayout">
<form name="Forml" method="post"
action="WebForml . aspx"
language=" javascript"
onsubmit="ValidatorOnSubmit () ; " id="Forml">
- <input type="hidden"
name=" VIEWSTATE" value="dDwxMTkzNzklODM70z4=" />
<script language="javascript"
src="/aspnet_client/system_Web/l_0_2914_16/ WebUIValidation. js"x/script>
<input name="TextBoxl"
type="text" id="TextBoxl" style="Z-INDEX: 101; LEFT: 35px; POSITION: absolute;
TOP: 39px" />
<input type="submit"
name="Buttonl" value="noflTBepwiTb" onclick="if
(typeof (Page_ClientValidate) ==
'function') Page_ClientValidate ( ) ;
" language=" javascript"
id="Buttonl" style="Z-INDEX: 102; LEFT: 40px; POSITION: absolute; TOP: 86px"
/>
<span id="Labell"
style="Z-INDEX: 103; LEFT: 38px; POSITION: absolute; TOP: 13рх">Укажите Ваш
возраст</зрап>
<span id="RangeValidatorl"
controltovalidate="TextBoxl" errormessage="Bo3pacT должен находиться в
промежутке от 10 до 90"
type=" Integer"
evaluationfunction="RangeValidatorEvaluate!sValid" maximumvalue="90"
minimumvalue="10" style="color :Red; Z-INDEX: 104;
LEFT :229px; POSITION: absolute;
TOP: 2 6px; visibility: hidden; ">Возраст должен находиться в промежутке от
10 до 90</span>
<script
language="javascript">
<! —
var Page_Validators = new Array
(document .all ["RangeValidatorl"] };
// —>
</script>
<script language="
javascript">
<! —
var Bage_ValidationActive = false;
if (typeof (clientlnformation) !=
"undefined" &&
clientlnformation.appName.indexOf
("Explorer") != - 1 ) {
if (typeof
(Page__ValidationVer) == "undefined")
alert ("Unable to find script
library
'/aspnet_client/system_Web/l_0_2914_16/
WebUIValidation.js
' .
Try placing this file manually, or
reinstall by running 'aspnet_regiis -c'."); I
else if (Page ValidationVer !=
"121") [
}
alert ("This page uses an incorrect
version of WebUIValidation. js. § The page expects version 121. The script
library is " + t
Page_ValidationVer + ".");
else
ValidatorOnLoad ( ) ;
function ValidatorOnSubmit () { if
(Page_ValidationActive) { ValidatorCommonOnSubmit ( ) ;
</script>
</form>
</body>
</HTML>
Как видно, сервер добавил
достаточно объемный код JavaScript, который позволяет не только анализировать
введенное пользователем значение, но и различные ошибки, которые могут быть
вызваны настройками браузера пользователя. То есть, в код также встраивается
система самодиагностики.
Для ASP-разработчика подобные
компоненты системы проверки являются одним из самых полезных при разработке
форм. Естественно, ему предоставлено несколько вариантов подобных компонентов.
Мы рассмотрим механизм их применения, несколько расширив предыдущий пример.
Добавим еще одно поле для
ввода адреса электронной почты. С ним мы свяжем два компонента системы проверки.
Адрес электронной почты будет являться обязательной для ввода информацией.
Соответственно, мы свяжем с ним компонент RequiredFieidVaiidator. В нем следует
установить значение всего двух уже знакомых нам свойств — ErrorMessage и
controiToVaiidate. Этого будет достаточно для работы данного компонента.
Именно собственный адрес электронной
почты является одним из самых "трудных" вопросов к пользователю. Слишком уж
часто пользователи допускают ошибки в его написании. Поэтому стоит
проконтролировать правильность его введения. Обычно достаточно проверить, есть
ли в нем символ @ и хотя бы одна точка. Но и эти ограничения не могут
гарантировать точного соответствия введенных данных формальным правилам
написания адресов e-mail. Поэтому разработчику был предоставлен КОМПОНеНТ
RegularExpressionValidator. Он ПО-
зволяет проверить соответствие
введенных пользователем данных некоему шаблону. Достаточно большой список
заранее подготовленных шаблонов предоставляется разработчику, когда тот пытается
установить свойство ValidationExpression. В списке готовых шаблонов есть и так
необходимый нам шаблон адреса e-mail под названием Internet E-mail Address.
Именно им мы и воспользуемся.
Компоненты системы проверки
допустимости не только блокируют отправку неверных данных на сервер при нажатии
подтверждающей кнопки, они отображают предупреждения сразу после того, как
контролируемый орган ввода теряет фокус. Если форма достаточно велика, то может
сработать несколько систем проверки допустимости. Соответственно, пользователю
лучше показать сразу все извещения. Для этого есть компонент ValidationSummary,
который автоматически собирает вместе все извещения об ошибках и отображает их в
виде списка или отдельных абзацев. Достаточно просто разместить этот компонент
на странице, и он автоматически подключится ко всем остальным системам проверки
допустимости.
HTML-код получившейся страницы до
обработки ее сервером приведен в листинге 3.14.
Листинг 3.14 ;
<%@ Page Language="vb"
AutoEventWireup="false"
Codebehind= "WebForml.aspx.vb"
Inherits="form2.WebForml"%>
<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<titlex/title>
<meta name="GENERATOR"
content="Microsoft Visual Studio.NET 7.0">
<meta name="CODE_LANGUAGE"
content="Visual Basic 7.0">
<meta
name="vs_defaultClientScript" content="JavaScript"> <meta
name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body
MS_POSITIONING="GridLayout"> <form id="Forml" method="post"
runat="server">
«asp:TextBox id="TextBoxl"
style="Z-INDEX: 101; LEFT: 35pX; POSITION:
absolute; TOP: 39px"
runat="server"x/asp:TextBox>
<asp:Button id="Buttonl"
style="Z-INDEX: 102; LEFT: 37px; POSITION:
absolute; TOP: 284px"
runat="server" Text="rfoflTBepflHTb"x/asp:Button>
<asp:Label id="Labell"
style="Z-INDEX: 103; LEFT: 38px; POSITION:
absolute; TOP: 13px"
runat="server">Укaжитe Ваш возраст</азр:Label>
<asp:RangeValidator
id="RangeValidatorl" style="Z-INDEX: 104; LEFT: 229px; POSITION:
absolute; TOP: 26px" runat="server"
ErrorMessage= "Возраст должен находиться в промежутке от 10 до 90"
ControlToValidate= "TextBoxl"
MaximumValue="90" MinimumValue="10" Type="Integer">
</asp:RangeValidator>
<asp:TextBox id="TextBox2"
style="Z-INDEX: 105; LEFT: 39px; POSITION:
absolute; TOP: 116px"
runat="server"x/asp:TextBox>
<asp:RequiredFieldValidator
id="RequiredFieldValidatorl" style="Z-INDEX: 106; LEFT: 223px; POSITION:
absolute; TOP: 114px"
runat="server" ControlToValidate="TextBox2" ЕггогМеззаде=
"Обязательно укажите
Ваш E-Mail">
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator
id="RegularExpressionValidatorl" style="Z-INDEX: 107; LEFT: 227px; POSITION:
absolute; TOP: 139px"
runat="server" ControlToValidate="TextBox2" ЕггогМеззаде="Введен неверный адрес
E-Mail"
ValidationExpression="\w+([-+.]\w+)*@\w+([-.]\w+)*\
.\w+([-.]\w+)*">
</asp:RegularExpressionValidator>
<asp:ValidationSummary
id="ValidationSummaryl" style="Z-INDEX: 108; LEFT: 41px; POSITION:
absolute; TOP: 212px"
runat="server" Width="308px" Height="2 9px"x/asp: ValidationSummary>
<asp:Label id="Labe!2"
style="Z-INDEX: 109; LEFT: 42px; POSITION: absolute; TOP: 78px"
runat="server">B ведите адрес E-Mail</asp:Label>
</form>
</body>
</HTML>
Сам код класса здесь не имеет
смысла приводить, так как он не изменился кардинальным образом по сравнению с
предыдущим примером. Достаточно лишь включить оператор добавления новой
глобальной переменной. А вот внешний вид Web-страницы после того, как
пользователь ввел неверные данные и, невзирая на показанные предупреждения,
которые, напомню, отображаются сразу после того, как орган ввода данных теряет
фокус, попробовал отправить на сервер, показан на рис. 3.15.
Естественно, было бы очень
интересно увидеть, каким именно HTML-кодом достигается подобная
функциональность. Код откомпилированной страницы приведен в листинге 3.15.
Листинг 3.15
<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<titlex/title>
<meta name="GENERATOR"
content="Microsoft Visual Studio.NET 7.0">
<meta name="CODE_LANGUAGE"
content="Visual Basic 7.0">
Oneta name="vs_defaultClientScript"
content="JavaScript">
<meta name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body
MS_POSITIONING="GridLayout">
<form name="Forml" method="post"
action="WebForml.aspx" language= "javascript" onsubmit="ValidatorOnSubmit();"
id="Forml">
<input type="hidden"
name="__VIEWSTATE" value="dDwtOTEwMjY3NzgOOzs+" />
<script language="javascript"
src="/aspnet_client/system_Web/l_0_2914 _ 16/
WebUIValidation. js"x/script>
<input name="TextBoxl"
type="text" id="TextBoxl" style="Z-INDEX: 101; LEFT: 35px; POSITION: absolute;
TOP: 39px" />
<input type="submit"
name="Buttonl" value="IloflTBepflHTb" onclick= "if (typeof(Page_ClientValidate)
== 'function') Page_ClientValidate(}; " language="javascript" id="Buttonl"
style="Z-INDEX: 102; LEFT: 37px;
POSITION: absolute; TOP: 284px"
/>
<span id="Labell"
style="Z-INDEX: 103; LEFT: 38px; POSITION: absolute; TOP: 13рх">Укажите Ваш
возраст</зрап>
<span id="RangeValidatorl"
controltovalidate="TextBoxl" errormessage= "Возраст должен находиться в
промежутке от 10 до 90" type="Integer"
evaluationfunction="RangeValidatorEvaluate!sValid" maximumvalue="90"
minimumvalue="10" style="color:
Red;Z-INDEX:104;
LEFT:229px;POSITION: absolute;
TOP:26px;visibility:hidden;">Возраст
должен находиться в промежутке от 10 до 90</span>
cinput name="TextBox2" type="text"
id="TextBox2" style="Z-INDEX: 105; LEFT: 39px; POSITION: absolute;
TOP: 116px" />
<span
id="RequiredFieldValidatorl" controltovalidate="TextBox2"
еггогтеззаде=
"0бязательно укажите Ваш E-Mail"
evaluationfunction=
"RequiredFieldValidatorEvaluatelsValid"
initialvalue="" style= "color:
Red;Z-INDEX:106;
LEFT:223px;POSITION:absolute;
TOP:114px;visibility:hidden;
'Обязательно
укажите
Ваш E-Mail</span>
<span
id="RegularExpressionValidatorl" controltovalidate="TextBox2"
еггогтеззаде=
"Введен неверный адрес E-Mail" evaluationfunction=
"RegularExpressionValidatorEvaluatelsValid" validationexpression=
"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*M style="color:Red;
Z-INDEX:107;
LEFT:227px;POSITION:absolute;
TOP:139px;visibility:hidden;":
Введен неверный адрес E-Mail</span>
<div id="ValidationSummaryl"
style="color:Red,-height:29px;width: 308px;
Z-INDEX:108;LEFT:4Ipx;POSITION:absolute;TOP:212px;
display:none;">
<s,pan id="Labe!2"
style="Z-INDEX: 109; LEFT: 42px; POSITION: absolute; TOP:
78рх">Введите адрес E-Mail</span>
<script language="
javascript">
var Page_ValidationSuinmaries = new
Array (document . all [ "ValidationSummaryl " ] ) ;
var Page_Validators = new Array
(document .all ["RangeValidatorl"] , document. all ["ReguiredFieldValidatorl"] ,
document .all ["RegularExpressionValidatorl"] ) ;
// --> </script>
<script
language="javascript"> <! — var Page_ValidationActive = false;
if (typeof (clientlnformation) !=
"undefined" && clientlnformation.appName.indexOf ("Explorer") != -1) {
if (typeof (Page_ValidationVer) ==
"undefined")
alert ("Unable to find script
library
Vaspnet_client/system_Web/l_0_2914_16/WebUIValidation.
js' .
Try placing this file manually, or
reinstall by running 'aspnet_regiis -c'.");
else if (Page_ValidationVer !=
"121")
alert ("This page uses an incorrect
version of WebUIValidation. js . The page expects version 121.
The script library is " +
Page_ValidationVer + ".");
else
ValidatorOnLoad ( ) ;
}
function ValidatorOnSubmit () {
if (Page_ValidationActive) {
ValidatorCommonOnSubmit () ;
</script>
</form>
</body>
</HTML>
Действительно, следует
признать, что компоненты системы проверки допустимости могут достаточно серьезно
облегчить жизнь разработчику, избавив его от утомительного написания вручную
различных проверок допустимости введенных данных и освободив, подобным образом,
время для разработки действительно серьезных модулей.
Следующий
урок
|