Вы находитесь на странице: 1из 902

В.М.

Снетков

Программирование
на ASP.NET
В.М. СН"",,,В

Программирование на ASP.NET
2-е и здани е, и с п равле нное

С нетков В.М .

Национальный ОжРЬПЫЙ Университет " ИНТ УИТ"

2016

,
В.М. СН"",,,В Програм",ирование на ASP. NET
Прогр амм ировани е на ASP. NEТ/ В. М. Сне"ПФв - М.: Национ альный (}п.;рьпый
Униве р ситет" ИНТУИТ ", 2016
Кур с посвящен технологии прогр а ммирова ния web-прило жений на AS P. NEТ с
и спо льзованием Visua! Studio 2005.
В ку р с е по рроб но рассказывается об этапах создания web-са йmв, прогр аммировании
форм , сер верных и пользовательских элементах управления. Расска зывается о
средствах форм аmрования стра ниц, технологии ADO.NEТ, работе с файлам и и
каталогам и и упра влении бе зопаС НО СTh Ю са Йта .

(с) 000 " И НТУИТ. РУ", 2010-2016


(с) Сне"ПФв В. М . , 2010-2016
в.м. СН"",,,В П рограм ", ирование на AS P.N ET

ОСНОВЫ Visual Studio 2005


Обзор среды разработки VlSua! Studio 2005. Н астройка среды разработки
Visua! Studio 2005. Пр о ц есс разработки страницы. Типы фай лов
AS P.NET Управление ссылками н а сборку Выбор используемого
стандарта НТМL.

Помимо Windows -приложе ний вся мощь IDE сохраняется и для


про е ктиров а ния
Web -сай тов по те хнологии ASP.N ET. Visua! Studio 2005
п оддерживает б и бл иотеку массов Framework 2.0, которая является
усоверше нствованием библиотеки Framework 1.0 (1.1). Сама среда
про ектирова ния VlSua! Studio 2005 также является новой версией среды
Visua! Studio .NET 2003. Мы будем далее р ассматривать возможности
Visua! Studio 2005 при ме нител ьно к пр оектирован ию Web -сайтов ,
пр едназначе ннны х для работы в движке ASP.NET 2.0.

Среда разработки Visua! Studio 2005 пр едоставляет своему польз ователю


(программисту, не п угайте с конечным пользователем!) две
высокоуровневые области функциональности:

1. IDE (lntegrated Deve!opment Environment) среда, позволяющая

р азработч и ку написа ть и отладить код.


2. Компилятор , инспектирующий код разработчика и
прео бразующий его в пром ежугоч ный ба й т-код IL.

Це н тральное место в любой Web -страни ц е за ни мает НТМL -код .


Конечно, все мож но написать и в обычном текстовом редакторе, если в
точности знать и соблюдать весь синтаксис языка НТМL4. Но сейчас
это никто не делает, а пользуется с п ециальными НТМL -редакторам и. В
пр едыдущих версиях VlSua! Studio НТМL -редактор ы были з начитель н о
слабее специализированных редакторов. И самое главное,
вмешивались в HTML - коД, вводимый разработчиком, автоматически
пр еоб р азуя его в громоздкие конструкции. В VlSua! Studio 2005 этот
н едостаток уст р анен, теперь НТМL -редактор только выделяет блоки с
ошибочным кодом.

ПредыдуЩаЯ версия , VlSua! Studio .NET 2003, изначально компилировала


ис ходный НТМL- код активны х страниц до DLL -сборок Visua! Studio
2005 оставляет страницы в исходном НТМL- ф:Jрмате и в таком виде
,
в.м. СН"",,,В Програм ", ирование на ASP. NET

разработчик может перенести их на прОМЫШllенный сервер.


Компиляция же проис ходи т уже на сервере при первом за п уске

страницы , а также в том случае , если в исходный текст страницы в


по следУЮщем были внесены изм енен ия.

VlSual Studio 2005 по зволяет кодировать страницы на разных языках


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

При отладке Web-страни ц прим еняется такой же арсенал средств , как и


при разработке обычных локальных приложений (точки останова ,
по строковое выполнение , просмотр промежугочных значений
п еременных и т.д.). MSDN (Mk:rosoft Developer Network) - справочная
система разработчика от Мiсrоsоft.

Создание заготовки

Мiсrоsоft постановила, что отныне (начиная с VlSua! Studio 2005 )


разработка страниц ASP.NET не является проектом , а является Web -
саЙтом. Мы же , по -старинке , БУдем прим енять и тот и другой термины.
Начать работу по созданию Web -сай та теперь нужно так:

• г;.:.=Запустите ШЕ Visual Studio 2005

Перед вами появится прим ерно следующий интерфейс среды


разработки
в.м. СН"",,,В Програм",ирование на ASP.NET

''' = ""'" Т""" Wf1OO..,. comтLТrty и,;р

.. ",-.- 1.
~ · IiiI III . 8,") . ('10 . ~l"

0 '" S.v< Selec\ed r",m,


flJи'fО)К:t

~ 0 " S.vOI ClJI+ S

...- ., Visual Studio2005 0 " С Ь1 + э-rt· S

0 ' Ы ~H

0 0> '=
I 1I _
CJТЩJ
'ho",.,...,' "'''.' (horn<ImIфf not ""..-"" V"''''nfOm<t
ТooII. """""' di<k apno"", 11,.,., . """'., Е'''''''",.,,.,,I ..-.:1 <" S
0
0~
", ,-
~
С О1 +(

ClJIH

0 " ew
0 ' smDebuo;lл ;;

0 _C""W--.,
Solb::<l EXPOr<r C ~ I+ дI: + L
0 "
0 '" PГCV'""" \\' гФ"
"
0k Tool:x:>x Cb1 +N:·X

epen: Pfо)ЭС t • $ o.-tРq

С го. "' ; Pfo-",ct [,:j D ~,~

R.""Tocbo-

I"<I l;<i<;rv ru"""" 111<1..,.,.,. "


""<'- 5<rVOf """'У'о ~'" (.
""<'- Sorve, Нe;тдl:k:<1 Sor",
O.:;>L SOfVOfP~s.rv.o ,
Dewt::p&r С",-"

Здесь показаны начальная страница , открытая в рабочей области , и


ц епочка меню для на стр оики панел и инструме н тов. Начальная
страница уб ира ется п е ре уста новкой в р аскрывающемся списке As startup
в свойствах среды Tools/Options!Environment/Startup нового режима

орtюпs

-"
~_. Envirrn rnent Аt s И--Цо :

I€'ИЬЩ.
Add- n;Ма cros Securiti
AutoRocover s и--t Рagoэ r>3WS cha .-.--.з l:
IhtIjJ:// msdl,m o:rosoft,com/sqlfrss"ml
Fm ar.::1 Реросе
Frnts ,.--,j Co crs Р [>]"",Oad сrnten! еуегу :

~ m rutes
I ~t ar.::1 Ехрor! Setth;)s
InternatOтia I Settщ s
Keybo<f-d
S"',<
Тaзk List
Вr o wser

~- Projects ar.::1 So Utior'rs


$-- 50..-се C rnlт ol
i!J-- Те,! Editcr
I!J- Вusiness Intell qэncе Des чвs
~- Оаtabзsе Tools
i!J- Debo..щ ~

ос C,.-, ce l
в.м. СН"",,,В Програм ", ирование на ASP. NET

Рабочие панели среды разработЮ1 почти таЮ1е же , что и в IDE VlSua!


Studio .NET 2003.

• r;:;'выполните коман ду FilelN ewlWeb Site и настройте масте р


создания сайта
N~", VJ~h !;it~
======---------~~

Errpty Web
Si.,

Se:>fchOnlre
Т ОЩJ ", II»

Loca oo :

Поле Location = File System (файловая система) обозначает, что


БУдет созд аваться сайт на локальном компьют е ре. Поле Language =
Visua! С# назначает код овую поддержку страниц (мы буд ем
по л ьзоваться языком С# ). Правое длинное поле с кнопкой Browse
задает пугь и папку с именем сайта , где БУдУГ размещаться
входящие в него страницы и подкаталоги.

Щелчок на кнопке ОК после настройЮ1 маст ера , представленной окном


New Web Site, приведет к созданию нового Web -приложения. В
рабочей области появится вкладка с файлом начальной страницы и
именем по умолчанию Ое f aul t . азр х. Э та страница будет
запрашиваться браузером клиента при первом вхождении на сайт по его
URL без указания конкретной страницы.

З аготовка в режиме представления дескрипторов ( Source ) БУдет иметь


ВИД

,
В.М. СН"",,,В Програм",ирование на ASP. NET

<%@ Page L апguagе="С#" АutоЕvепtWirеuр=' 'truе'' CodeFile="Default.aspx.<

< !DO CТYP E html PUBLIC "- IIWЗС IIDШ ХНТМ L 1.0 Tra nsitio naVIEN" 'hu,

<html xm1пs="httр ://www.wЗ.огgl 1 999/xhtml" >


<head nmat="server">
< title >Uпtitled Page</tide>
<lhead>
<body>
< fо пn id="fo rml " ruпаt="sеrvег''>
<div>

</div>
</foпn>
<!body>
<lhtml>

в режиме п редставления D еsigп это бу,цет п ока п устой интерфейс ,


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

Есл и п осмотреть на созданное мастером ч е рез панел ь Solution Ехр!о гег


(или зайти в пап ку WebSitel через проводник) , то можно увидеть, чт о
созд ан а пап ка App_Data - ДЛЯ размещения фай лов с будущими данными ,
сама страница с дескри п торам и Defauh.aspx и файл скры того кода
п аддержЮ1 страницы с тем же именем , но расширением .cs (от слова С#
).

Soluoon Explorer ..... .Q. х

~ C:\",\WebSitel \

~·"~i;':.
t:I DefaLjtaspx.CS

Файлы >1< .aspx и >1< .aspx.cs - это файлы обычного те кстового формата . Мы
можем и х создавать и редактировать в обычном текстовом редакторе ,
н апример , Notepad (Бло кнот). Но в оболочке Visua! Studio 2005 это
,
в.м. СН"",,,В Програм ", ирование на ASP.NET

делать намного удобнее, тем более , что работает п одсказчик кода


IntelliSense и вы п ол н яется автоматическая проверка кода н а нал ичие
синтаксических ошибок.

в процессе п роектирования оболочка может, по мере надобности ,


создавать е ще ряд конструктивно н еобходимых каталогов и файлов в
н ашем Web - саЙт е . Но папки можно созд ать и самому, если в So lution
Explorer на узле сайта вызвать ко нтекстное меню и выполнить опцию
Add ASP.NET Folder (добавить папку ASP.NET)

,
В.М. СН"",,,В Про грам ",и рование на AS P. NET

Sоlutюп Explorer - С \ .. \WebS,tel\ ... -j:o Х


'{]
с
ct
о
~

App_Data ~ ВUild Web Site


~ D€fault.aspx PubUsh Web Site
~ Web.Conlg
~ WebSitel.sln
tJJ Add New Item".

D Add Exis1Jng Item


New FoIder

ВП Add ASPJEТ FokJer ~I


Арр_Сodе Add Reference ...
Арр _GlobalResources Add Web Reference ...
Арр _LocalResources Щ Vi€w Сlзss Diagram
Арр _WebReferences Щi] Сору web Slte ...
App_Browsers Start Op1Jons".
Тheтe
~ Vi€w in Browser
Sro\ll!se With".

rnJ Rе1Теsh FoIder

~ Cut
Сору

~ Р.зstе

li6J Ргорегч Р ages

в проводнике ком п ь ю тера можно за й ти в каталог

Мои докуме н ты fVi5ua l Studio 2005IP roj ectsIWebSitel

и ув и деть там д ва од н о и ме н н ы х фа й ла проекта


в.м. СН"",,,В

I
~WebSltel

Fle ЕФ v'ew !avcrtes ТOOIS нф


"'Вжk ~ ..... !!J rA Se:.-ch ~ Fdders

Addess f-J l!I!mIIII


---- --,. П рограм ", ирование на

:::J f'G:!
AS P.N ET

_~_""ID I~

,СШJN1 ,,1

в этих файлах среда разработки хранит текущие настройки n роекта


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

файлов.

Другое дело - локальные Windows -приложе н ия. Там ест ь обязательный


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

п ереходы на ст р аницы указываются яв н о . Поэтому никакой линковки не


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

Мы в любое время можем удалит ь рассмотренный каталог

Мои докуме н тыfVi5ua l Studio 2005IProjectsIWebSitel

и открыт ь сайт командой File/OpenfV\Тeb Site, указав в окне


в.м. СН"",,,В Програм ", ирование на ASP.NET

Ореп Web Slte ? х

Flle System
~ Select Ihe fO (jer уоо WCflt to 0 jE1 ,
Ffe System
I!J-O A ~JET - ~ I К ю-и-е C ~T Ст>ЕеН •
~ ~,O Larq.Jage C~
!Е-О Lar-qлge С+-+-
Local IIЗ
i!J-О LосlJJгес-r
~
FТF' Site

Remote Site
~-O u~
!Е-О VB,~T - i1J~1ы к »-К8 БарК9iJ Скоп, Ф
~-O Vrзu<ll С+-+- SlJJdioJ ,NET
В-О lМ:B
E;j·D ASP,I\ET
!ЕС! Cmtвlt
u
вС! EX<lmple~
, Ша .М"
~,O Pi::IJJ8S
I!J D [):Jfcu lt
@О Dв1vff2
~o Flash МХ 2004
@-а Flash_pfiJ
GO HT~
I!JD i::OIlS
~· o JavаSс фt
..:J
FoШ: Iс :\Cha Г\ВООk\I"IEВ\.>.SP ,NЕТ\ЕхаЩJles\We!JSitE 1

Оpen CCtxel

и мя п а пки с содержимым саЙта. Но после выхода из оболочки все р авно


будуг созда н ы файлы проекта в указанном месте

Мои докуме н тыfVi5ua l Studio 2005IProjectsIWebSitel

и сохра н е н ы текущие настройки.

При открытии готового Web -приложения , созда нн ого с п омощью VlSual


Studio .NET 2003, с помощью команды FilelOрепIPгоjесtl Sоlutiоп и ли
FilelOрепIWеЬ Site оболочка Vi<;ual Studio 2005 запускает масте р
п реоб р азова ни я Conversion Wizard. VlSual Studio 2005 не поддерживает
добавление Web -страниц старо го формата с использованием п рямой
коман ды
в.м. СН"",,,В Програм ", ирование на ASP. NET

% WebSitel - Мicrоsоft Visual Studio


File Edit View Website Tools Wildow
13 Md New Item ... C1J"I+Shift+A
Add Item". ::tJift+Alt+A

Их нужно открывать через указанные кома н ды FilelOреn!PгоjесtlSоlutюп


или РПеlOреnlWеЬ Site, чтобы вызва ть ма стер пр еобразова ни я

Vi5ual Studio Conver5ion Wizard .1J~J


Welcome to the Visual Studio
Conversion Wizard

тhe soIutbn ог proyoct you с.-е Oper1h;J was created


Il а
preViOJs verSion ofVisua studo, It mustbe
converted to the format used Ьу thiS versiOn. After а
sou tion or апу of its proJects has been converted, it
сап по щег ье ecited, buit, or run Il ргеv iсш
verslOГlS.

If the SШtio:xJ or p-ojoct is uгder SO L.Гce сmП-о , it 001


Ье checked out cutomaticaly шгh;j the conversbn,

---
Ве SLfe the correct SCUce сопП-оl РЩ Iп is actiVe,
агЮ гю 1iIes are exdJsivery c:hecked out Ьу other
users.

d~k Next to proceed.

< РгеУiOи;> 11 ~xt > Firish Cancel


Id
Установки размещения фай лов проекта по умолча нию мож н о изменить
в ме ню оболочки коман дой Тооls/Ор tюns , вызвав окно настройки
параметров
В.М. СН"",,,В Про грам ", ирование на AS P. NET

ОрtlOПS
"*iIiJ

-"
~ -- Envirrnrnent Visual S!L.dOJ р; ор;:tз b:atm :
I,КОО. З87ХВ87DА244ЕЕ\W'" Щ gMМiW@itii"', "ЩФiD ~
Add- n;Ма cros Securiti
AutoRocover
1 4ЕЕ\М:<1 дС»И3Нты\Visual SW OJ 2005\ТеЩJ~tes\Ргор;:tтеЩJ~tes ~
Fm ar.::1 Реросе
Visual S!L.d OJ LSer item te"l'~tes
Frnts ,.--,j Co crs
I2448Е'МJи Де><уМЕ!Нты\Visual S!L.d OJ 2005\Те ЩJ~tes\ItemТе ЩJ~tes ~
I ~t ar.::1 Export Setth;)s
р А~ЩS smw Errcr List if b.J i(J finisГes with errct's
InternatOтia I Settщ s
Keybo<f-d Р Tra:k Active 118т n So lJtm Exp crer
9"'< Р SOOw ad\Iar.::ed bui(J coofg.rat ions
Тaзk List Г A~ays smw so u tm
Вrowser
Р Save rew p; op;:ts..tJen created
~- Projocts ar.::1 So U1:ions
Р "',..-п user v.t.эn tt-.з prop;:t b:atm is оо! 1rusted
$-- 5с...-се Crn1rol
i!J-- Тех! Editcr Г stюw оuч:out wr-dJw v.t.эn bJ i(J sta.-ts
I!J- Вusiness Intellqэncе Оезg:-вз Г PrO"l't fa- syrrbol O:: г"""m O:--<j Yvt.эn гюаm O:--<j fies
~- Оаtabзsе Tools
i!J- Debo...щ Щ

ос C,.-,cel

• IJ$Откройте диалоговое окно Тооls/Орtюns на вкrщцке Projects and


So lution и выберите размещение файлов реше ния в папке над
катало гом вашего сайта WebSitel, чтобы на этапе разработки все
было под рукой. Измененное окно должно выглядеть примерно
так

I!]- Env r-mrre!lt


13- РГ О )8' tз ,.--,j SO u t O"1S

I"~~\ii ' ~'~W~'~Ш~'i;i"~О~""i'~'~""'i'"~'~';;;;;i;----:::::::d


Bu ikJ ..--.d RlI'l
v6 DEf,"-,~ С :\Сha r~\WEБ\t..SP.~Т 2.0'Exa"flJ les ~
УС ++ Dr-octcries
УС ++ Ргор;:! Se:tO:--<js
I!]- Scи се Crn1rol
,'1[C
":\Cha
"'"'c';wcc' o"'""'c'"Cm
r~\WEB\t..sp.~, ioooc"V""c"' "o;c;o;---------.~
2.0'Ex""l'ies
I!]- Т ех! Ed l1D:'
I!J- в.."; "., ,, Iпt<II g.--к:. o.,,; g--..-, '" А !"щs smw Errct' List f bJ (J fnisOOs wil!l юct's
I!J D,bbOlGQ ,00" '" Tra:k Act",e 118т n So utrn E",trer
1iJ DЮ.m1lJ '" 9-.:rw iid"<,"oo bJ i(J cmfQXat&!s
Tools
I!]- Оеу о: е Г A .... ~ j< <how "",Utm
I!] НТм. Desg-e-
'" S,v~ "'''.. p:o~..t..n cr.~tod
I!]- WrriJws Fct' ms Desg-e-
'" \II.""n l!OOr ~ th<> р:а",,! ba>trn '" not 1rL>3ted
Г Show CVpu\ wndow whe<-1 b." il:J ,\y~
Г PrО ЩJ\ fu- 'Jrтbo I O: г"""т ~ ",г.,., г~ "",, т ~ л."

о< Car>:EI

Теп е рь служебные файлы решений и отладки оболочка БУдет сохранять


В.М. СН"",,,В Програм",ирование на ASP. NET

вместе с рабочими файлами ст р аниц. Но это плохое ре ше ни е, потому


что файлы настройки нужны нам на том компьютере, где мы создаем
проект. Выходным же п родуктом проекта являются файлы в каталоге
сай та, именно их мы должны размещать на сервере. А туг еще будуг
болтаться какие- то вспо могательные файлы ре ше ний и отладки. В
любое время мы можем автоматически создать эти файлы , открыв в
оболочке пр оект как каталог саЙта. Мы не должны о них заботи ться -
какая на м разн ица , где они хр анятся , лишь-бы запоминали текущие
настройки среды проектирования и режима отладки.

:.. С: \Chair\Book\WEB \ASP.NET 2.0\Examples\WebSitel


File Ecit V~w Favorites Tools Н€lp
~
.;? Ваа ... -+т I!J ] ~ S€arch ~ FoIdeгs 0 1~ q,
х "" 1ElT I
AMess IS C\ChalГ$ook\WEB'J\SPNEТ 2.0\Ехаmpes\wеЮtе 1

D lШ
--~
--~
~ [;J ~
App_Data Default. aspx Web.Conlig WebSitel,sln WebSitel,suo

Процесс разработки страницы

Оболочка предоставляет инqюрмацию о странице в трех видах:

1. Графический режим Dеsigп Web-конструкто р а (Web-дизайнера)


2. Режим Sошсе исходного HTML - КОАа (режи м дескрип тор ов)
з. Режим кода подце ржки С# ( Code View )

Процесс проектирования страницы сводится к перета скива нию (и ли


д войным щел чком) нужных элем е нтов управле ния пользовательского
и н терфейса из панели ин струме н тов Toolbox на Web -форму и
настройки их п араметров в пан ели свойств Properties. После (и ли
совместно с ... ) размеще ни я элем ентов управления на Web -форме
выполняется создание обработчиков событий и напи са ни е их кода.

Все три режима до пускают редактирование и являются

взаимосвязанными . Изменения в одном из режимов немедлен но

преоб р азуются оболочкой в изм ен ен ия в д ругом режиме. Так


В.М. СН"",,,В Про грам ", ирование на AS P. NET

помещение элеме н та управления на форму в режиме Design немедленно


при водит к генерации соответствующего НТМL-кода в режиме Sошсе . И
наоборот, ручное написание дескрипторов в режиме Sошсе
равносильно к помещению элемен та управления на форму в режиме
Design. Настройка свойств элемента управления эквивален тн а
доб авлению соответствующих атрибугов к дескриптору НТМL-кода
элемен та, и наоборот...

Редактор НТМL-кода теперь н е изменяет код разработчика , размечает


ЮJючевые фрагменты цветом , генерирует подсказки с пом ощью
механизма IпtеlliSеnsе и автоматически форматирует текст отступами.
Режим авто матич еско го выравнивая НТМL-кода устанав л ив ается в окне
свой ств среды на стр ойками НТМL-редактора с помощью опции Format
НТМL оп paste (Форматировать НТМL во вр ем я вставки)

ОрtlOПS

I
Misc81~OCUS нтм.. ~ t o:m

a:-.:J So u t io:"!s f7 Auto!D 8"""""tз rn p.зste n Scu"C8 view


f7 Fспnаt нтм.. оп p.зste

-"
, Fi~ Е~tens оо
$ AII L"'"'F"ges
i!J Вдs o:

i!J CI
$ c;I:++
i!J css

-"
9 НТм..

, TdIbs
",m'
г "МЩi§.og
V"ldat oo

$ P~ " Text
i!J SQ.. Scr " t

ос C,.,cel

Отформатировать отступы можно и так:

• выделить курсором нужный блок кода


• выполнить командУ Fопrnt Sеleсtioп (форматировать выделенное)
контекстного меню НТМL-редактора
в.м. СН"",,,В Програм ", ирование на ASP.NET

EJ < html xmlng = rrhttp://'W1JJIiJ _wЗ _org/ 19 9 9/xhtml rr >


<head runat =~5erverrr>

<title >Untitled Page<! title >


<! head >

Cut

Сору

Paste
Paste Alteгn.ate

Х D~ete

View code
I!l View il Browseг
Synchronize Document Outjine
Fcxmat StЭect:ioп
Forma1jjng аnd Validation

В отли ч ии от п ред ыдущих верс и й Visua! Studio 2005 н е поддерж и вает


сето ч ный режим р азметки для аб с олю тн ого п ози ци о н и р ования
эл е мен тов управл е ни я с п омо щью вне шн ей CSS (Cascading Sty!e Sheet -
ка с кадн ая табл иц а сти лей) . Вместо этого и с пользуется более
естествен н ый потоковый р ежим разметки , пр и котором содержимое
может выстра и ваться по вер т икали без на п олза ни я. Жесткое
п озиц и о н ирова ни е в ып ол н яется с п омощь ю встроенн ы х сти лей
дескр ип то р ов , но такой пyrь не р е комеН дУется как громоздкий и
н егибкиЙ. П ри мер жесткого п оз ици онирова ни я с п омо щью встрое нн ых
стиле й:

< аsр:Вuttоп I D='Ъ tп"


sty!e="position:absolute; !eft:auto; top:auto"
nmat="server" Text="Button" />
в.м. СН"",,,В Програм",ирование на ASP. NET

Общее управление файлами проекта осуществляется в пан ели So lution


Explorer. В ней распознаются различные типы файлов, входящие в
про ект (изображений, НТМL , CSS, баз данных и д р.) и вы даются
разные контекстные меню дл я их обработки. В этой панели можно
п ереименовывать, удалять, перемещать , добавлять новые или
копировать существующие файлы. С уществуют следующие типы файлов
ASP.NET

Типы файлов ASP.NET


Файл Описание

Содержи т пользовательский интерфейс и (необязательно )


*.aspx базовый код приложения. Пользователи запрашивают одну
из таких страниц напрямую или запускают приложение

Пользовательские элементы управления, похожие на Web-


ст р аницы, только к ним нельзя получить прямой доступ.
*.ascx
Они используются при построении страниц подо бно
библ иотечным элементам.

Web -сл ужбы, работающие не так, как Web-страницы, но


*.asmx совместн о использующие одни и те же ресурсы

приложений , параметры конфигурации и па мять.

Основанный на XML конфигурационный файл для

we Ь .соп fig
конкретного приложения , содержащий настройки
безопасности , управления состоянием , памятью и др .
Создается оболочкой при создании первой страницы.

Глобальный файл при ложения, который можно


использовать дл я определ ения глобальных п ереме нны х и
gIob а Lasax
реакции на глобальны е события. Его н ужн о создавать
самому разработчику при необходимости.

Файлы скрытого кода на С# (застраничны е файлы). Они


*.cs позволяют отделить функциональность приложения от
пользовательского интерфейса страницы.

Управление ссылками на сборку

Для но рмальной работы приложения среда про ектиров ания , как и среда
выполнения , нуждаются в б и бл иотечных файлах и ссылках на ни х. По

"
в.м. СН"",,,В П рограм ", ирование на AS P.N ET

умолчанию ASP.NET создает небольшой набор ссылок на библиотечные


сборки .NET, доступные всем Web -страницам. Э ти ссылки
размещаются в специальном конфигурационном файле, доступ ном в
пределах всей машины. Для использования массов в этих сборках не
тр ебуется никаких cnециальных действий.

Основные сборки для страниц ASP.NET


Сборки Описание

Содержит базовый набор типов данных


библиотеки Framework, р ас пространенных
mscorlib.dll, System.dll
типов ИСЮJюч е ний и большое количество
фундаментальных строительных блоков.

Содержи т массы для чтения и записи


конфигурационной информ ации из файла
Systеm. Со пfigша tiоп.dll
web.config, ВЮJючая пользовательские
настройки.

Содержи т массы контейнеров данных для


System.Data.dll ADO.NET вместе с источником данных SQL
Server.
Содержи т массы для управления в GDI+
System.Drawing.dll цветом, шрифгами, кистями и др . , что может
понадобиться для построения графиков.

System.Web.dll Содержи т н еобходимые массы ASP.NET


Содержит массы для по строения Web-
служб (элементов удаленн ого стороннего
System. Web.Servk:es.dll
кода для частичного решения типовы х

задач).

System.Xmldll Содержи т массы для работы с XML

System.Е пtегрпsе ervк:es.


. S . dllСодержитмассыдлятакихслужБСОМ + ,
как тран закции (объединенные операции).

Содержит массы для мобильных элементов


управления при доступе в Web ч ерез
System. Web.Mobile .dll
небольшие устройства тип а сотовых
телефонов .
в.м. СН"",,,В Про грам ", ирование на AS P. NET

Дополни тельны е ссылки на н ужные сборки до бавляются в файл


web .config командой Website/Add Reference... С ист ема предоставляет
диало гов ое окно

dd Reference

,NET Iсом I Projocts I вroт8 1 R8C8l1t I

,""" 7,0,3300,0 vl,0,3705 c:lprogram Fi es\lv1 t ros"

~"""
7,0,3:DJ,0 vl,O,3705 c:lfrogram Fies\Comm"
sysg ru l 2,0,0.0 ~2,0,50727 С:\WINNТlf.1iсгosoft,r-.E"
Syst8m 2,0,0.0 v2,0,50727 C:\W INNT\jI-1iсгosoftr-.E"
Syst8m,Cm fg..ratrn

Syst8m, сер tr,-m8llt 2,0,0.0 v2,0,50727 ,


Sуst8m,Des ф 2,0,0.0 ~2,0,50727 С: \ W INNTlf.1icrosoft, r-.E, ,
Syst8m, DiroctJJy5ffvic8S 2,0,0.0 v2,O,50727 С :\WINN"ТVv1icrosoft r-.E, ,
Syst8m, DirectJJyService .. 2,0,0.0 ~2,0,50727 С: \WINNTlf.1icrosoft, r-.E, ,
System,CXa+lh;J 2,0,0.0 v2,0,50727 С :\W INN"ТVv1icrosoft, i'I:, ,
Sуst8m,СХаwing.Desф 2,0,0.0 v2,0,50727 С :\WI NNT\jI-1iсгosoft, r-.E, ,
- - -----

еж Cct"lCel

и после выбора нужной сборки (одной или нескольких) в файле


web .config появится ИН Д ИВИ дУальная для нашего сайта информация
(блоки комментариев )'Далены)

<?xml version="l .O"?>


< сопfigшаtioп >
<app Settings/>
<connectionStrings/>
<system.web >
<compilatio n debug= ''true''>
<assemblies>
<add assemb ly="SystemData.OracleClient, Version=2.0 .0.0, Сultше= пеut
</assemblies>
</compilation>
< а итепосаtioп пюdе= ' Windоws "l>
В.М. СН"",,,В П рограм ", ирование на AS P. NET

</system. web>
</сопfigша tloп>

При ПОДЮJючении сторонней сборки, н е входящей в глобальный кэш,


оболочка создаст каталог Вin, куда физически скопирует
соответствующий файл dlL Например, при выборе ссылки
SystemData.SqlClient создается каталог Вin и в н его копируется сборка
SystemData.SqIClient.dll, а при выборе SystemData.OracleClient создается
ссылка в конфигурационном файле.

Не п угайте импортирование прос транства имен оператором using в


файле .cs и добавле ни е ссылки на dlL Прописывание пространства имен
по зволяет использовать в коде С# короткие и мена ЮJассов, а сборки
указывают компилятору и среде выполнения локализац ию

(местонахождение) используемых библиотек.

Возможность добавления сборок в конфигурационный файл и их


удаления имеется еще в одном месте оболочки - в панели So lution
Explorer. Если для узла проекта вызвать контекстное меню и выполнить
команду Start ОрПоns ...
В.М. СН"",,,В Програм",ирование на ASP. NET

Solut:ion Explorer - С \ ... \Web ....... ~ Х

PubI,sh Web ~te

Add New Ite т ...


Add Existing Item ...
New Folder

дdd ДSР,NЕТ Fold€r ~

Add Reference ...


Add Web Reference

.Q. View Class Diag-am

Iii Сору Web ~te,,,

sta"t

~ View in Вrowser

Browse Wi1Л ...

lI] Retresh Folder

~ Cut
Сору

Paste

li:iI Property рзgе,

ТО п ояви тся о кн о уп р а в лен ия сбо р ками


В.М. СН"",,,В Програм",ирование на ASP.NET
С Ch.:!lr\Oook W[O \АЗР.r-a::т 2 О\[хшr"l~s WebSlt~l \ Prop~rtv Paq~s зJ~

R.t.-=.
BLМ
Acc.ssbllty
SШ- t qotкrJ>
r~SВ uld 0;:U:rIS

Add Ref",erJC8" Rerm'e

Выбор используемого стандарта НТМL

Большинство серверных элемен тов ВЮIaД КИ Standard ген ерируют


НТМL-код современного стан да рта ХНТМL и сам НТМL - редактор п о
умолчанию так настр оен. Но имеется возможность на строить оболочку
на соб л юдение д р угого стандарта, например чистого НТМL4.01 . ДЛЯ
это го щелкните на пустом месте пан ели ин стр ументов BBep>g1 окна

интерфейса и включите инструменты НТМL Sошсе Editing


В.М. СН"",,,В Програм",ирование на ASP. NET
" .. WebSltel - Mlcro!>oft Visual Studio
Fle Ed t \f~w Website ВU l d Detug Тodз Wird:)w Сот mm ty нер

ыщ

= '% ------,'1 ~
'!Г

Clст Desgner
Оаш Design
DаtaЬзsе Dlig-am
Derug
ОЮJg Location
Oewe
Olibg Editor
Formal:trg

Image Edtor
Laywt
QU<:!Гy Designer
Report В<xders
Report Formal:trg
S:::oJrce CmlIoI
stcnJ.ard
StyI<:o Sh:et
Table Desi g-er
Text Editor
\fiew Desigler

XГVL Dаш

хм... Ed tor
хм... Schema
Customi:ze"

Затем из выпадающего списка появившегося блока инструментов


на стройте редактор оболочки на проверку достове рности нужного
стан дарта.
В.М. СН"",,,В Програм",ирование на ASP.NET
'у.. WebSitel - Micro"oft vi"ual studio
Fi ~ Ed t View Website Вu ld DetU;J Toof5 Wn::bw Comm Lrity ~

QJ T Id fI J! It\ 1'" т !" т ~ ыщ • ~~~ ItJEJ T_


1] ~~ I ·:; a

~~~
" ~=~6'O~~~ Page
~tsc~ Navф tcr 3,0

в <5cr:ipt r:unat =
I pr:otected vо EJ~~~~Wl~~ct-,~~с,с,"~~Ig'-ет--~

По умолча ни ю все серверные элеме н ты управле н ия ASP.NET


автоматичесЮ1 используют разметку стан дарта ХНТМ L . ДЛЯ то го , чтобы
заставить элеме н ты управле н ия ген ерировать ч и стый НТМL , нужно в
н ачале ст р аницы встав и ть блок (в VS-2008 нет тако го атрибуга)

<system.web>
< xhtmlllСопfоrma псе е паыeьs оl еtеR епdегiпg="truе" />
</system.web >
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Введение в Web-сайты

Установка 115. Типы проектов и места их размещения.


Зарезервированные папки АSР-проекта. Создание Web-саЙта .
Настройка параметров при ложен ия через ко нфи гурац ионны е файлы .
Создание файла web .config. ВЮlючение трассировки и ее настройка.
Совмещенная трассировка страниц. Отделенная трассировка страниц .
Секц ии трассировочных да нных. Отложенная компиляция Web-
страниц.

Для реал изации технолоrnи удаленного доступа к информации


создается сеть компьютеров , на одни х из которых размещается

инфо рмация в виде ор ганизова нн ой системы файлов , а другие


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

Компьютер, который запрашивает нужную июlюрмацию с сервера ,


назы вается Юlиентом. Программа , обесп ечивающая взаимодействие
Юlиентского компьютера с сервером, на зывается броузером (браузером).
Чаще все го име нн о броуэер считают Юlие нто м с точки зрения
пр ограммистов.

Взаимодействие Юlиента и сервера пр оисходит по схеме "за прос-ответ ".


Первый запрос Юlиента считается простым (GET), при этом н а сервер
п ередается только URL зап р ашиваемой страницы. Если пользователь
пр одолжает нач аты й сеанс с сайтом, дви гаясь по нему
пр едусмотр енными на стра ниц е средствами навигации , то каждый
п оследУЮЩИЙ запрос к серверу называется обратной отсылкой
(PostВack) . Обрат н ая отсылка обычно осуществляется методом POST.
Обратную отсылку сервер распознает, обрабатывает присланные с ней
событи я и формирует ОТЮlик .

Мы должны понимать прин ципиальное отличие при ложения


локального стола от Web-приложения. Локальное Wiпdоws-прuложе нu е
реагирует немедленно на действия пользователя , вызывая
соответствующие обработчики. ОНО имеет ви довое представление ,
которое меняется н емедленно. В Web-приложении по суги каждая
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

разрабатываемая ст р аница уже является приложением , п оскол ьку


компилируется в отдельную DLL-б и бл иотеку, хотя взаимосвяза нны е
страницы в ц елом принято считать Web- при ложе ни ем. Се р ве рн ая
страница н е и меет ви да, хотя н а эта п е проектиров анuя дл я Удобств а
разработчика она и меет примерный вид в конструкторе оболочки.
Серверная страница т ольЮJ с посо бна сгенерировать вид и отправить
его удаленному поль зователю.

Web-приложение размещается на удале нн ом сервере и может


реагировать на де йс твия пользователя пр едусмот ренны ми
обработчиками тольЮJ т огда, когда получ и т от броуэера обратную
отсылку В н ей БУдет упакованы не только состояния элемен тов
управления на момент п ослед него откл ика , временно сохраненные на

кли е нте , но и новые изменения, в ключая события , которые пр оизвел


удаленный кли е нт н ад посл едни м откликом. При пол уче нии на се рв е ре
обратной отсылки Web-приложение сначала восстанавливает элеме н ты
управления до состояния , которое они имели на момент посл еднего

отклика. Затем прило же ни е р еа гирует на при слан ны е события и


доводи т состояния серверных эл ементов управления до уровня , которое

они имели у клиен та перед обратной отсылкой.

<html>
<head >
< titlе >Uпtitled Dо с umепt </titlе >
< mеы http -еq illv= "Со пtе пt-Туре" content=''textlhtml; charset=windows- 1251">
</head>

<body>
<h2 аlign="сепtег' '> Страница с об ратн ой отсылкой</h2 >
< fо пn паmе ="fопnl " method="post" action="">
<center>
<input type="submit" name="S ubmit" value="Submit''>
</center>
</foпn>
</body>
</html>

Листинг Пример статической страницы Default.htm с обратной


отсыпкой
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Запрашиваемые страницы , которые не требуют п редварительн ой


обработки на сервере, а сразу отсылаются клие н ту в н еизме нн ом виде ,
н азываются статическими или п ассив н ыми. Они имеют расширение
hunl или htm, что равнозначно. С траницы , которые п редварительно
обрабатываются н а сервере специальными программами и ген ер ируют
н ужн ый код на языке НТМL для отправки клиенту, называются
активными. О ни имеют ра с шир е ние asp, aspx, php , cgi и т. д. В
зависимости от того, какой пр о граммной средой они долж ны
обрабатываться.

Отправляющая и приним аю щая сторо н ы работают согласованно п о


определенным пр ав и лам, определяемым протоколом Н1ТР.
Отправляющая сторона делит пер едаваемую инqюрмацию н а отдель ные
еди ницы , которые называются пакетами (п ачками). Каждый п акет
имеет н екоторую служебную инqюрмацию, п омещаемую в его
за головок. В заголовке может содержаться размер пакета, его номер и
контрольная сумма .

и дет сеа нс
( сессия )
г--
Запрос / GEТ
" Запрос
а..
w ОТклик"
) Паkеты
< ОТклик
(')
m
м Il. /
::J:
1- "tJ
~
-1
1-
::J: Обратная Обратная -1
"'tI m
а..
ОТСЫЛr.:з/ POST ,ОТСЫЛr.:з
m
LO
~ отклик"
) Паkеты
<
/ ОТКЛИК
"tJ

Принимающая сторона получает пакет, распаковывает его и по


за головку п роверяет, не ПрОИЗОlllТIO ли потери дан н ых при п ередаче

п акета . Если потери да нных не обнаружено, то приним ающая сторона


отсылает об этом подтверждение, в противном случае отсылается
команда с требованием повторить пер едач у соответствующего пакета .

"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Пакеты доставляются по разным пугям сети, используя любой


включенный в данный момент в эту сеть компьютер как

вспомогательный п ромежугочный узел.

Устан овка IIS

При разработке Web- п риложения


115 (lntemet Information требуется
Servk:es), который эмулирует работу сервера . Среда разработки VlSua!
Studio 2005 имеет свой встроенный (интегрированый) упрощенный IIS ,
но иногда может потребоваться настоящий IIS о п ерационной системы .
Если 115 на вашем ком п ьютере уже установле н , то на д иске С:\ должен
существовать каталог IпеtрuЬ , в п ротивном случае его придется
установить . Для установЮ1 IIS выполните следующее

• u;.;rвыпол ните командУ компьютера ПускlНастройкаlПанель


управления

C!:I Пан~nь управления

A_
= ral:e< ""~"
Corfipotrn
Irt~R )
Едсе "
Irt"""",
""~ ,--
А "тс..."н " А д "",,-,::т р " Дат" н "Р"Н"

~~
.%"
..,."' Т ЖМ",
~-
~
y cт po:k T ",
~
К-""-"т у ра -, 'о
~-
~
'М-"К1
Q;,
"_.
Г'оо"Ь>О<оОТ "
(о)
~"

c\f [ii@J ~ ~ 1Ь1 ~


C Mik ," ~

~"
Сеть "
YA'neнны1 "
С "" "Т е",,
,-
CK_r-ы " C""ц "~JЪНЫe
00ЗЮ)о(НОСТ Н
Те,,"фоо "
~,~

~
,~ ,
[&]
_О"
11
х"
~
Э"е""pont1 " ,-"
С Тi>t<Д "l' ТЫ

• r;:;'щелкните по п иктограмме Установка и удаление программ


• ~ открывшемся диалоговом окне в левой части щелкните по
кнопке
в.М. С""",,,в

... :"81·
~ .•
добаВЛ~~I1Е! И
удаленне ~I
KO~OHeHTOB ~
Про,раммupoвtJNШ' 110 ASP.NET

Windows ,~,

• ~Откроется окно, в котором по ставьте отметку против


компо нента II S
Мастер компонентов Wшdоw"i

Компоненты Windows
Вы молсете дооаеить ИJlI.i lJ\ал.IIЪ KOМ'lc.1eнты Windovvs 21]00

ЧтOCibI дo6aeиrь или I:JдalМТb комnoнент~ установите или Cl"l-lrФrТе флаЖОК.


З~~~ ФЛ~ЖОК Оо3Н~Ч~ ч~стиLНjIO ~:ICHIHceK~ ко,,;noнент~, ВыосНИ1"Ь его
состае n03IJОЛООТ KНOffia ''Состав''.

Комnoне
СС~С':'~-С________________________________~~~СО

11Mf1 ...:J
Опvcание СJl\jЖбы 115 (пщцеРJJ:ка 006 и FТР]СГlO,IJД8ржкO!iFrOlltРа.;щ
Т~Ю~ЦИЙ~ cтp~"'-IASP, поо.клlOчеr-и:. к Мз.У>1Д~Х И

т ~lПI H~ диc:r::е ОЛ МБ Сосп~ ...


Cм6QaHO ~ диске: 33415З МБ

• r;:;n осле нажати я кнопки Далее > мастер выполнит установку


компо нента . При этом, возможно, потребуется уста ново ч ный диск
с системой .

Далее н уж но за реги стри ровать систему ASP.NET на локаль но м


компьютере. В каталоге С:\W I NN1\Мk: го sо ft .NЕ1\F гаme wогk существуют
подкаталоги с версиями vl .O.3705, vl.l .4322, у2.0.502 1 5 и у2.0 . 50727, в
которых н аходят ся файлы asp necregiis.exe. Один из эти х фай лов (лучше
по след н ей версии, расположенный в подкаталоге у2.0.50727 ) н уж н о
за п усти ть с опц и ей /i .
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• ~ыполните кома н ду компьютера ПускlВы п ол н ить и в поле


появив ше гося окна введите команду спЮ.
• Г;;:;=Используя команду cd (change directory - смена каталога)
перейдите в один из указанных катало гов и выполните в н ем
командУ

aspnet_regiis.exe /i

• ~ pOBepЬTe н аличие каталога I пеtр uЬ и подчиненных ему


подкаталогов

=- Inetpub
---------------------

' File EdiI: lJiew Favorite5

~ ~ck ~ .; • [!J ~ [\ Se~


Addre5s 16 IГtetpub
AdminScrip ts
ftproot
iissamples
mailrool:
5cripts
~Ьрш
VoIWwroot

Здесь каталог wwwroot эмулирует корневой каталог Web-дерева .


Все файлы , которые будyr в нем н аходи ться , будуг недоступны для
удаленных клие н тских ком п ьютеров, п оскольку защищаются

сервером.

Типы проектов и места их размещения

Для создания ново го Web-сайта (по старому - Web- п риложе ни я) с


п омощью инструмента VlSua! Studio 2005 нужно выполнить команду
меню File/N ewlWeb Site. Появи тся ди ало говое окно, в котором
п редусмотрены три типа Web-приложений:
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Ne\·, Web Slte .1J~


Terrp~tes:
111 "
q
~ ~ \!с# ~
A5',f.ET '1'100 ASP JU '1'100 Persmal '1'100 ЕЩJЦ '1'100
5ite 5".,-, ;:" 5ite S З; ter Kit 5ite

Зе",ф 01 1,...,
Terrp~tes",

1. File System - используется для р азмещения всех ком п о н е н тов сай та


в файловой системе ком пью тера разработчика. Для тестирования
такого тип а сай та используется встроенный (инmегрированый) в
оболо ч ку облегченный сервер , а не полноценный IIS локального
компьюте р а

2. Н1ТР - сай т р азмещается в указа нно й п а п ке ПQЦкаталога wwwroot,


находящегося в каталоге lnetpub (при условии, что на компьютере
р азработчика установле н llS ). Используется не встроенный в
оболо ч ку упрощенный сервер, а сервер ком пьютера.
З. FTP - этот вариант чаще испол ь зуется, когда Web-сай т р азмещен
на Удаленном ком пьютере и разработчик обращается к файлам и
папкам этого сай та через FТP, а не ч ерез FrontPage Server
Extensions (Администратор серверных расширений)
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

7т FPMMC - [Console Root\FгontPage Seгveг Ехtепsiопs] =-.JgJ~


JI.~ KoН(:orь Qкгю ~гpaBк.a J D ~ l1li 11[1 =-.J!2l~
ю !lеЙСТ6И€ I).ид Uзбр,,"ное Ы
I
Структура Избражое I КOМlьют е

[] З87ЗС887DА2448Е
CJ COIlsole Root
I±Н:З Fron1:Page Server ExtenslOnS

Далее мы будем использовать п ервые два типа проектов . П ри создании


н оваго проекта Web Site оболочка создает катало ги и файлы в трех
местах:

• Файлы решения на этапе проекmuровйнuя. Два файла с


р асшире ни ем .sln. и .suo, необходимые для работы самой оболочЮ1 ,
БУдУГ размещаться в катало ге Мои документы \Visuаl Studio
2005\Projects. Первый файл является текстовым файлом ре шения ,
в торой соде р жит п ользоватеЛЬСЮ1е настройЮ1 решения . Э ти
файлы нужн ы на эта п е р азработЮ1 с помощью оболочЮ1 и
на п рямую к будущему р азвертываемому сай ту от н ошения не
имеют, п оэтому и хранятся отдельн о от самого сайта
• Содержимое саЙта. Каталоrn и файлы исходных текстов самого
сайта, ВЮlючая файлы страни ц , баз данных, ресурсов, н астроек
конфи гура ци и. Они хранятся для проекта тип а File System в
указанном катало ге , а при установле нн ом IIS для п роекта типа
Н1ТР - в катало ге Iпеtр uЬ\wwwroоt\Имя_сайта
• Рабочие файлы сай та для АSР-машины. Каталоги и файлы ,
создаваемые ASP.NET-средоЙ, ВЮlюч ая скомпилирован н ые сборЮ1
.dll для пр и ложе ни я и отдельн ых стра ни ц . Они хр анятся в
системном каталоге

"С:\W I NNТ\Мiсгоsоft.NЕТ\Fгаmеwо гk\v2.0.50727\Теmрогагу


ASP.NET Filеs\Имя саЙта". Э ти каталоrn и файлы после
завершения раз р аботЮ1 можно уничтожи ть. Он и не нужны для
раэверmывйнuя на рабочем сервере
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Зарезервированны е папки АS Р-проекта

Содержи мое сайта может храниться в любом кол и честве вложенных


каталогов, но и ме н а 8 п а п ок счи таю т ся зарезервированными

Pubish Web Site


Add New Item".
Add Existing Ite т."
New Folder
Bin Add ASP.tEТ Folder ~

App_Code Add Reference."


Арр _GIobalResources Add Wm Reference".
Арр _LocalResouгces .Q View Class Diagram
Арр _WebReferences
~ Сору Web ~te ...

App_Data Start OptiOllS".


App_Browsers
I!l View in Бrowser

_т е
Bгowse Witll.,.
Re1Yesh FoIder

Cut
Сору

Paste

Property Pages

Кроме то го, что АSР-машина и щет в них необходимую и н формацию ,


она же защищает и х от прямо го доступа Удаленно го пользователя. При
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

попытке открыть любую из этих папок (за ИСЮJючением Тheme ),


пользователь получит ошибку " НТГР 403 Forbidden " (- сервер не
поддерживает такие запросы).

Особые папки ASP.NET


И мя п апки О пи са ни е

Содержит ском пи лирован ные сборки .dl/, н а


Вin
которые ссылается приложение

Содержит файлы .cs исходного кода ЮJассов,


компилируемых с приложением

G1о Ь а lR еsошсеs
Содержит файлы ресурсов .resx и .resources,
Арр
- компилирующиеся в глобальные сборки

Содержит файлы ресурсов .resx и .resources


Арр_LосаlRеsошсеs отдельных страниц , пользовательских элементов

управления или мастер-страниц

Содержит файлы Web-ссылок .wsd/, .xsd, .disco,


Арр_ WеЬRеsошсеs
.discomap
Содержит файлы да нн ых пр и ложен ия .mdf и .xml
Содержит файлы о п ределения броузера .browser,
которые ASP.NET использует для определения

верси и броузера и его возможностей

Содержит стилевые файлы для страниц и


Theme
элементов управления

Создани е Web- сайта

в качестве упражнения создадим с помощью VlSual Studio 2005 простой


Web-сай т с именем MyFi r s t Si t e .

• ~ыберите команду File/N ewlWeb 5ite и заполни те ди ало говое


окно мастера так (место размещения сайта выберите по своему
усмотрению)
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Ne\·, Web Slte .1J~


Ierrp~tes:
111 "
q
~ ~ \!с# ~
A5'J-ET '1'100 ASPJU '1'100 Persmal '1'100 ЕЩJЦ '1'100
Site Sеп о: е Site S З; tE!r Kit Site

Зе",ф 01 1,...,
Terrp~tEs",

Мастер создаст все н еобходимые для начальной работы каталоrn и


файлы в местах, упомя н угых ра н ее.

в nан ели Solution Exp lorer мы увидим файл разметки стра ницы
Default.aspx и файл отделенно го кода Defauk. aspx.cs (застраничный файл ,
фоновый файл поддержки), а также созда нную особую папку Арр_Оаы

Sоlutюп Ехрюrеr -С \Ттр .. '" -j:o х

App_Data
В ~ D€faut,aspx
!J D€fault,aspx,cs

• г;.:.=вызовите в So lution Explorer на папке App_Data контекстное


меню и выполните кома н ду Delete (ил и выделите папку App_Data
и нажмите клавишу Delete клавиатуры)

Оболочка Удал и т n аn ку, которая в данный момен т нам не н ужна .


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• ~Запустите Проводник Windows и с п уститесь в динами чески


созданный вр еменны й катало г
С:\W I NNТ\Мiсrosоft.NЕ1\Fгаmewогk\v2.0.50727\Теmрогагу ASP.NET
Files\myfirstsite

~523b9284 111
~Edt V'feW Fav<Xltes TooIs НеР

'"' Bock .... ...... i!J I <a Seif"ch ~ Fd:1ers @ [.~ ~ )< ~ J шm ....
Addess I"E; с :\WI~rosoftJ.ET\Framew<xk\Y2,O, 50 727\Temporif"Y АЧ',~ FIes\mуlТstsitе\Збd2а9ю\52::Ь9284
• defiUt,аspх,сdcю7d2_свt>Pes ut,сcu
• defдJt,аspх,сdcю 7d2_cвt>Pes utcomp!<:d
hash, web

Мы видим, что оболочка создала три временных файла:

• .сси - сериализованный н абор объектов исходн ого кода (Code


CompiJe Unit) , которые можно скомпилировать
• .compiled - представляет собой текстовый .xml-фаЙл , содержащий
инqюрмацию для ком пи лятора . Э тот файл указывает, что на
основе Web-страницы .aspx и файла отделенного кода .aspx.cs
создан файл .сси
• hash.web - содержит ютючевое слово хэша Web-сайта для его
кодирования

Теперь мы должны скомпилировать Web-саЙт.

• r;:;'выполните командУ BuildlВuild Web Site и вновь посмотрите во


временный ка талог

Была создана DLL-библиотека .dll, содержащая соб р а нный воедино код


разметки и отделе нн ый КОД, а также создан текстовы й .xml- фаЙ л
.compiled, который содержит н астройки компилятора, примененные пр и
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

создан ии DLL-библиотеЮ1.

• ~Добавьте к сай ту н овую страни ц у. Для этого выполните


командУ Website/Add New Item и настройте диалоговое окно
мастера так

Add Ne\O' Item - С:\ Tmp\MyFlГstSlte\ .1J~


Terrp~tes: 111 "

-

&J
с <ы
r.w lc atL"
D
Мао"" р"'9"


"оо
Crnfg.xati"
~
Wob uoc>r
Cm1rol

••
х м.. File хи
~
н тм.. р"?,,

1m
.. Schema
~
Woo SerV CG

li1
Тех l File
~
C~C

JjJ
P escиce Fi le
~
sty k> ShGGt

1]
SQ.. Database

1m !i]
- , ~ ~. ~ ~ ~
DataSE't
~~
Si"~ ~ ile w eb
Fct"m
VВScrjJt File
"-' JScr " t File

ri=\;" ~' ,811 1,;; Ф .1 R1


I А fu" m fu" WOO "РР l с~tС<\б

Name : I Page2,aspx

L~: IVisual С, iJ р" Росе [ 000 n sEp<f"ate file


Г Select mast8f page

Теперь мы видим , ЧТО во време нн ом каталоге среды выполнения опять


появилась пара файлов дл я н овой стра ницы

~523b9284 _

V~w Favorites TooIs НеР

Back ... ...

• ~ ще раз соберите сайт, выполнив кома нду BuildlВuikl Web Site


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Новая страница Page2.aspx вместе с файлом отделенного


(застраничного) кода Page2.aspx.cs была скомпилирована в отдельную
DLL -библиотеку и был создан файл . xml-инструкция для компи л ятора

:.о 523Ь9284 _
---------------------------------------------------------------

Компиляция стра ниц в отдельные .dll файлы позволяет исполь зовать


ДЛЯ создания каждой отдельной ст р аницы свой язык

пр о гр аммирова ни я , п одцержив аемый ком п илятором. На уровне DLL-


библиотек это будет совместимый в ц елом код. Компилятор соб ир ает в
отдельную сборку как стра ниц у со встроенным кодом , так и ст р аницу с
отделе нны м кодом.

Настройка параметров приложе ния через

конфигурационные файлы

То, что включено в п роект, п осле компиляци и п ревращается в


при ложение , котор ое БУдет работать п од управле ни ем среды АSР.NЕт.
Режим и с п ол н е ни я п р ил ожен ия о пр еделяется до п олнительными
пар аметр ами среды, которые задаются в конфигурационных файлах .
Конфи гурацuон ные фа йлы представляют собой т екстовые файлы ,
на писанные н а языке XML.

Для на строй Ю1 Web-сай тов используется и ерархия ко нфи гура ци онных


файлов. На вершине это й иерархии стоит файл тас hinе.со пбg, который
находи тся в системном катало ге

С:\WINN1\Мiсгоsоft.NЕТ\Fгаmework\v2. 0.50 727\СОNF I G

Он о пр еделяет параметры среды исполнения .NET Framework в ц елом


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

для всех типов приложений: консольных, оконных для рабоче20 стОЛQ,


Web- п риложений и библиотек классов. Часть из этих параметров
являются глобальными для ком пьютера и не MOryr быть
п ереопределен ы. Но некоторые MOryr переопределят ься в файлах
web .config, расположенных ниже по иерархической лестнице, причем ,
чем ближе к рабочим страницам на ходится файл , тем больший
п риоритет имеют его па раметры .

Файл web.config, стоящий в иерархической лестнице сразу за файлом


maсhiпе.сопfig, находится в одн ом с ним каталоге. Далее следуют
н еобязательные файлы: файл web.config, расположенный в корне web-
дерева (каталог wwwroot в lnetpub ), затем web .config, расположенный в
корне web-приложен ия (Website н а этапе проектuрованuя) . Наивысший
п риоритет имеют конфuгурацuонные файлы, размеще нн ые в
п одчи н ен н ых каталогах прилож е ния (если таковые имеются).

machine.conf1g
е CONF IG

i
web.-col1ffg
• CON FIG
t
wеЬ .сопfig
е wwwroot
f f
vveb.con'fig vveb.conflg
е wwwroot\WebApp1
... е wwwrootl.We bA ppN

t f

в
web.conf1g
VW!bApp1\Dir1
... е
web.config
WebApp1\D irM
...

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


п риложение и создает для н его КЭШ настро е к. Настройки формируются
п о следующей схеме:

1. С начала извлекаются па раметры из файла CONF IG\machine.config


2. Затем доба вляются параметры из файла CONFIG\web.config,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

переопределяя одн оименные параметры тасhiле.соnfig


з. Если есть wwwroot\web.config, то из него извлекаются параметры с
замещением ранее доб авленных одн оиме нны х параметров
4. Если приложение имеет свой файл web.config, то в КЭШ
добавл яются и оттуда пар аметры , замещая одноименные
5. Если страница находи тся в подкаталоге и там же имеется свой
файл настроек web.config, то его параметры добавляю тся в кэш и
п е реопределяю т ранее введенные одноименные на стройки

Создани е файла web.config

Файл настроек web.config является текстовым файлом с XML-разметкоЙ .


Его можно создать н есколькими способами. Рассмотр и м некоторые из
них:

Способ 1

При первом запуске нового сай та на выполнение в оболочке VlSua!


Studio 2005 командой DebuglStart Debugging появится сообщение

DеЬuggiпg Not EnabIed

Тм page carmt ье rm in dei:u;J rmde b8CEtJSe debuggh;j i:3 mt anabled n th8 Web,coofl;J
file. What would you like to do?

r. АОС! а new WеЬ,шnfig file with debuggh;j 8nablOO,

~ DЮJgo;Jir.;J should ье diS;abled n th8 lNeb,coofl;J file Ьэfcr8 ЩJlоуir.;J th8


web sit8 bJ а p'c.dJction вn .. r onrrent.

r Rm wнtrut debuggn g. (EQJivalent bJ C1TI+F5)

ОК CEi1cel

предла гающее добавить новый файл web .co nfig с о пци ей включения
отладки. Ниже БУдет пр ед.УПреждение, что п е ред развертыванием
отлаженного прилож е ния эту о пцию в файле настроек следует Удалить .
Щелчок на кно пке Ok заставит оболочку создать web.config в корне

"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

текущего приложения (но не в корне Web-дерева).

Способ 2

Можно воспользоваться угили той Web 5ке Admirllstration

• Г;:;=Создайте новый сайт или в п режнем сайте удалите файл


web.config
• ~ыполните командУ оболочки Website/A5P.NET Сопfigшаtioп

Появится рендеринг (в и зуальное представление) страницы


appConfigНome . aspx
В.М. СН"",,,В

"" ElIt """ F,,,,,, и Тcx:tз нар


t:t 3
------."
..
,,"~K ~ ... ~ ~ 1) ~ ~S.""h (ij f.vo,,,,,, ~~","'" (J ~~ ;;,1 т
/.(\(fess ~1~h::<;t: 1Ш315'_'-- оЬd'nfi'o:L~On'JI~m<~..!....-
,~

Нome Securit)' Appllcatlon 1l"


""'""'O
""'''c.._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _..

U~e thi~ раае to configure your application with values t hat you do not V'lant
to ha rd -code into your page~, епаЫе your application to ~end e-mail,
configu re debugging, set up а default еггог page, and stop ог start your
applici'Jtion.

ApplicatlOn SMTP Settings Application Status


Settings Confiqure SMTP е mail Application is: Online
Exi~t in g application settinas
settings: О Take applicatjon
offline
Crei'Jte applici'! t ion
settings Debugging and
Мапааеа~ Tracing
settings
Configure debugging
a nd tracing

Define dеf<щlt еггог

""'"
.1

• ~становит е ВЮIaДКУ Application и щелкните н а сс ы лке со пfigше


debugging and tracing

Запустится страница DebugAndTrace.aspx, которая сгенерирует


следУЮЩИЙ ОТЮlик
В.М. СН"",,,В Про'раммupoвtJNuе NQ ASP. NET

f le БJ! Уоео< favcr US Tods


~

Config ure the settings for deb LJgging and tracing your
аррliсаtiо п.

г ЕпаЫе dеЬugg i пg
г Capture tracing information

J:j Display tracing information оп individ ua l pages


Display trace outp ut for:
aLocal requests only
cA11 requests

Select the sort order fo r trace results:


фВу time

с Ву categoгy

NLJmber of trace reqLJests to cache: ГiO":j

Select which t race res ults to c~che:


"Most rece nt trace results
aOldest trace resu lts
Configure custom еггог pages

• u;.;rвыполните какое-нибудь действ и е, например, включите


флажок ЕпаЫе debugging, затем восстановите пр ежнее состояние
настроек и закройте броуэер со страницей угилиты. Обратите
внимание , что при любом действие выполняется обратная
отсылка PostBack
• ~ ажмите кнопку Refresh в верхней части панели So lution
Explorer оболочки, чтобы обновить это окно
• г;;;?Откройте ПОЯВИВlШfйся файл web.config и Вы увидите пустую
заготовку настройки параметров web-сайта
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<?xml versio n="l .O'?>


< со пfigш аоо n xmlns= ''http ://schemas. mkroso ft.co m/. N etC о nfigшаtiо n/у2,
</соnfigшаtiоп>

• ~HOBb зап усти те угили ту Web Site Administration и на стр а нице


DebugAndTrace. aspx включите флажок Enable debugging, чт обы
доб а вить пар а м етр отлад ки

Фай л web.config стан ет таким

<?xml version="l .O'?>


< со пfigша tioп xmlns= ''http://schemas.microso ft. com/.N etC о пfigша tio n/у 2 .0">
<system.web>
< сошрilatiо п debug= ''true'' />
</sys tеш.wеЬ >
</со пfigшаtioп>

Способ 3

• ~ыпо л ните коман ду об олочки Website/Add New Item и


выберите ша б л о н Web С опfigшапоп F ile
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Add Ne\·, Item - С:\ Tmp\MyFlГstStte\ .1J~


Terrp~tes: 111 "
е-~ D ~ 1!1 ~
1'100 Fe<m Мао"" Р"'9" l'Iob Uo..- H T~P"'9" 1'100 _y c ~ СЬоо sty k> ShGot
Cm1rol

~
с<ы
~
X~ Fi"
tm
XI~ Schema
li1
Text Fi"
!IJI
Resc....-ce Fi "
IJ
SQ.- Database
"W1c atL"

tm -~, ~ шf· ~ ~ ~
DataSet
~ff
Si l9~ ~ i "Web
Fe<m
VВScr"t Fi"
"-' JScr " t Fi"

ri=\;" g' ,811 1,;; Ф .1 R1 iJ


IА fi " uэed to СС<"1"gже \\100 Aw l сзtrn oettng,
Name: IWeb,(C<"1f,"
LangJage;
1 u I С, iJ Г РIЮ? rodе
Г
m SEparate filE
58 ее! m.ster рзgе

Оболочка создаст файл ко нфи гурации, который затем можно


на страивать либо напр ямую в текстовом редакторе, либо через
yrилиту Web 5ке Аdmirllstгаtiоп.

Включение трассировки и ее настройка

Трассировка (след) применяется дЛЯ QIЮЛUЗQ работы приложения ,


п оскольку при каждом запросе очередной страницы среда исполнения
A5P.NET ВЮlючает в вывод служебную информацию, полезную пр и
отладке. Э ту информацию можно выводить как на за пр ашиваемых
страницах вместе с ОТЮlиком сервера (совмещенная трассировка), так и
в отдельную служебную страницу Trace.axd, которая является
виртуальной и исчезает при перезагрузке сервера (отделенная
трассировка).

Следует п омнить, что отладочная июlюрмация , если она ВЮlючается в


запрашиваемую страницу, доступна для просмотра в любом броузере .
Она делает потенциально уязвuлюй систему безо па с н ости сайта ,
п оскольку содержит в себе важную информацию , ВЮIючая переменные
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

сервера, кото р ой может воспользоваться злоумьши енн ик для


н есанкционированно го п роникновения. По этому на рабочих Web-
серверах хотя-б ы совмещенную трассировку страниц н епр еменн о
н ужно отключать.

Элеме н ты управления страницы DebugAndTrace.aspx ВЮlючают


трассировку и означают следующее

П араметры т р ассировки ASP.NET


Пар аметр
угилиты Web
П араметр , добавл яемый в
Site
WеЬ . солfig при ВЮlючении Описание
Аdтiлistгаtiол
в уг илите
по

умолча нию

Включает тр асс ировку,


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

виртуальную страничу

trace .axd, размещаемую в


памяти сервера на вр емя
O Capture
работы приложе ния. Ее
tracing enabled=''true''
можно прочитать п о адр есу
infопnatiо п
(для при ложе ния т ипа НТТР)
httр :l!lосаllюstl
Имя_при ложе нияl trace.axd .
Э та страница создается IIS и
хранится в памяти до

перезагрузки: компьютера

Трасс ировочны е данн ы е


O Display размещаются внизу каждой
tracing за п рошен н ой страницы .
infопnatiо п оп pageOutput= ''true'' Параллель но тр асс ировка для
iпdividиаl всех об ра бота нных страниц
pages помещается в виртуальную

стран и чу trace .axd


DispJay trace output for:
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Добавляет трассировку в
ОТЮlик страницы только
@ Local юсаlOnly= ''truе'' - по
тогда, когда она запрошена с
requests only умолчанию
того же сервера, где

развернуга ( по умолчанию)

Добавляет трассировку в
ОТЮlик страницы по запрос)';
O All requests юсаlOnly= "falsе"
поступившему с любого
компьютера

Se)ect the sort arder for trace results:


trасеМоdе ="Sо rtВуТпnе " - Результаты трассировки
@ Bytirne
по умолчанию сортируются по времени

О Ву categary traceMode="SortByCategory"
Результаты трассировки
сортируются по секциям

Количество запросов
страниц приложения ,

сохраняемых средой
исполнения в файле trace.axd.
Number of Э тот же параметр определяет
trace requests количество запросов первых

to requestLimit="lS"
запросов, при которых

cache:~1 сервер при соед иняет к

ИНДИВИдУальной странице
трассировочную

инф:Jрмацию при
pageOutput= ''true''
Se)ect whk:h trace resuks to cache:
Сохраняются результаты
O Most recent
mostRecent= ''true'' трассировки самых
trace results
последних запросов

При достижении
установленного количества

запросов КЭШ трассировки

перестает обновляться до
@ Oldesttrace mostRecent= "false" - по
следующего перезапуска
resuks умолчанию
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

приложения, сохраняя

результаты трассировЮ1

самых п ервых запросов

в п е р вой коло н ке та бл ицы п оказано состояние элеме н тов управления


yrилиты , когда в web .config параметров нет и прим е н я ю тся настройЮ1
по умол чанию. Во второй колонке таблицы показан ы параметры ,
которые добавляются в файл web.config при изменении состояния
соответствующих элеме н тов управлен ия на отличное от состояни я п о

умолчанию.

С овмещенная трассировка страниц

Се й час мы п опробуем ВЮlючить трассировку стран иц при ложен и я так,


чтоб ы тр ассировоч ная инф:Jрмация возвращалась вместе с рендерингом
страницы

• г;;;?Запустите уги литу Web Site Administration и н астрой те ее


элементы управле ния так
В.М. С""",,,В Про,раммupoвtJNШ' 110 ASP.NET

~--- -~

Configure the settings for debugging and tracing your


application.
17 ЕпаЫе debugg ing
17 Capture trac ing information

17 Display tracing information оп individual pages


Display trace output for:
r. Local requests only
r AII requests

Select the sort order for trace results:


r. Ву time
r Ву categoгy

Numbeг of tгace requests to cache: гi5"3

Select which trace results to cache:


r. Most ["ecent trace results
r Oldest t race гesults

Confiqure custom егrоr Qaqes

• ~Откройте файл web .config приложения и у6еди т есь, что о н стал


таки м

<?xml versio n="l .O'?>


< со пfigш аоо n xmlns= ''http ://schemas. microso ft.co m/. N etC о nfigшаtiо n/У2,
<system.web >
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<trace e nabled=''true'' mostRecent=''true''


pageOutp ut=''true'' requestLimit="15" 1>
<с о mр ilatюп debug=''true'' 1>
</system. web>
</configuration>

• r;:Fн аст р ойте страницу Default.aspx та к

<%@ Page Language="C#" AutoEventWireup=''true'' Code FiIe=''Default

<html xmIns=' huр://www.wЗ.or&,1 999/xhtml" >


<head runat= "server''>
<tide>Untitled Page</tide>
<lhead>
<body>
<form ю ="foгml " nmat="server''>
<div>
<h1 align="center" style="co lor: Red''>
П р и вет BceM !! !<lhl >
</div>
</fonn>
<!body>
<lhtml>

• г;.:.=Запустите п р иложе ни е и п олуч ите пр име рн о та кой результат


В.М. С""",,,В Про,раммupoвtJNШ' 110 ASP.NET

~ Untltled Pdge - Microsoft Internet Explorer


-------------------------------
Fie Edt
WY
Actless J

Привет всем!!!
Request Details
Session Request
х 5cbOs22bs5b1445rm3 1d u 55 GET
Id: Туре:
Time of St.atus
07.01.200811:00:40 200
Request: Code:
Request Response Unicooe
Unicooe (UТF-8)
Encoding: Encoding: (UTF-8)

Тгасе Infoгmation
From LlI~
ClItegory MesslIge From First(s)
(.)
aSpX.page Вegin PreInit
aSpX.page End PreInit 0,0182579070803692 0,018258
aSpx.page Вegin Init 0,0209208153550242 0,002663
aSpx.page End Init 0,0389624938 3 6 50 72. 0,018042
aSpx.page Вegin InitComplete 0,0394064050039879 0,00044<CJ
aSpx.page End InitComplete 0,0407646781923401 0,001358
aSpx.page Вegin PreLoad 0,0427593451122978 0,001995
aSpx.page End PreLoad 0,0441952818025755 0,001436
,.,~~,- '~~...I .....
C~<><>" <>,...,....,,~,...

• ~ ощелкайте на кнопке Refresh броузер а , инициир уя все новы е


запросы к стра ниц е. Мы видим, что вместе с ре н дер ингом
страницы броузеру возвращается трассировка только текущего
запроса

Но самый п ростой способ ВЮlючен ия трассировки для конкретной


страницы - доба ви ть в дир ект иву @ Page это й страницы пар аметр
Trace=''true ''.

Отделенная трассировка страниц

Если тр ассир овка страниц В Юlюче на « trace enabled= " true "
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

/ > ), то н езависимо от дрyrnх параметров трассировки , служба IIS


создает виртуальную страницу trace.axd, в ю:порую помещает
трассирово чную инqюрмацию всех запрашиваемых страниц. Э та
страница физически не существует, но доступна из броуэера по адресу

httр :lЛосаlhоst/Имя_прилож енияl trace. axd

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


через настоящий IIS компьютера, а либо ч ерез встроенный IIS
оболочки.

Вначале запустим трасс ир овку ч ерез встроенный IIS оболочки.

• ~3апустите приложение MyFirstSite, щелкнув на кнопке Start


DеЬuggiпg (и ли нажмите клавишу F5, или выполните команду
меню оболочки DebuglStart DеЬuggiпg, или выполните кома н ду
меню оболочки DebuglStart Without DеЬuggiпg, или наж ми те
комбинацию клави ш Ctrl+F5)
• ~ ощелкайте на кнопке Refresh броузера, затем через строку
адреса вызовите ст р аницу Trace.axd

Теперь за п устим трасс ир овку ч ерез IIS компьютера.

Поскольку ранее мы создавали приложение типа


File System в
MyFirstSite
файловой системе , то его нужно ско пир овать в каталог InetpubIwwwroot,
который для IIS считается виртуальным каталогом localhost.

• ~ыполните командУ оболочки Website/Copy Web Site


• ~ появившейся пан ели Сору Web щелкните на пиктограмме
Connect, расположенной в верхней части
• ~ появившемся окне выделите узел wwwroot и с помощью
кнопки C reate New Folder создайте подкаталог MyFirstSite (можно
задать и любое другое имя)
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

реп Web Site

Flle Sys:tem
9:t
Re System
Select lt1e foOO- уоо w,.-,t to Cf'8'l.

] ЕМ'ТЕ МО

~ ,~""'
Adm n 5cr \Jts
Loczl IIS

~
"'00'
iВsa rllJ Рз

FТP Ste rnai r oot

J
Re mote Ste

IfJO
~D kav
iED KPCМS
iEO LJ
iED f..'OO ile PhJnes
iED ~8Cow_2OJ6
юD мs SQL SERYER
iEO rr=bs
tiIo М5SQ.J
IfJO f.i: _1
~ ,,",~,~L-.; n.,cc,~~" ~

FoOO- :
'1 с".~':~:~"'ш:\:~=м:оо:::,--------_"':='---==-

cpen Са гсе l

• ~ осле щелчка на кнопке Ореп в панели откроется ее правая


половина , куда скопируйте все файлы наше го п риложения
~
ooIoctod I'\es ltorn ю.хоо!о Г .."ОС. weD ""'.

l!.L-_ _ _ _-----' -" l!.L_ _ _ _-----'-"


Lзs t r d"r~sh ; 1)5,01, 2OJ8 17 47 Lert r ~f~ ; Об !J j .2ООВ 17:47
Г % ". delete<:1 [""'" .. псе 1he 13'>1 сору c:.pe.-atix1
Stlltus:
CClJY "от Р." rrю~ W"b "" ю = \fl~ >I:t ~ /hst-J"d Co"","ted ,1 Об , Оl , JJo:)З 17 45 .29

• ~Закрой те соединение, щелкнув на кнопке Discormect


• r;:FвH OBb щелкните на кн оп ке Соnпесt и откройте корневой
каталог саита wwwroot, где уже находи тся ТОЛЬКО ЧТ О
ско пир ованное н ами пр илаже ни е MyFirstSite
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

реп Web Site

Flle Sys:tem

Re
9:tSystem
Select lt1e foOO- уоо w,.-,t to Cf'8'l.

юD IDWTEМO •
~ $а Inelp<b
~ ·O Adm n 5cr \Jts
Loczl IIS
IE О flp;oot
~ IE О iВsa rllJ Рз
FТP Ste еО rnai r oot
IEO 5cr \Jts
IEО WЩ:м.Ь
I;JO r:lll!l

J
Remote Ste
юО МyF rstsite
IfJO JВu Нзг7
~D kav
iEO KPCМS
iEO LJ
iED f..'OO ile PhJnes
iED ~8Cow_2OJ 6
юD мs SQL SERYER
iEO rr=bs
tiIo М5SQ..7
IfJO f.i: _1
..L..J,..C'"1 ,,",~,~L-..; г>.,cc,~~" ~

FoOO-:
'1 с".~':~:~"'ш:\:~=м:оо:::,--------_"':='---==-

cpen Са гсе l

• ~ы дел ите на левой панели файл web .config и скопируйте его в


wwwroot
SoLrc~ Web sit~: Rcmot~ Web sit~:

с :ITrrpV>t,-п- , CS t.

fme S t:J1JJS
.. G] Dof.ut .ЩJХ ~.,.. 0!i . D1 . 2OCIЗ 16 :3'5
.. ~ c.,r.ut .~ ~I<" 29.0 3 .= 12:405 07.D1. 20ct3 10 11
"Gj Р"9"2 .Щ'Х ~J<" 0!i . D1 . 20С1З 1 26
"~ P"9"2 .• "P ~I<" 05 . 01 . 20С1З 22 :03
!a.,.",mn"o;J Ltdlq 07. D1 . 2OCIЗ 10 : 11

L':; r.li-dl 07. 0 1 КlJ8 10 :51 ~t r~lr~h: 07 0!.ЭXJi3 10 51 -


р Sho". ~leted files snce ~ I~sc cC\JY =r~":tl

St<ltus :
(ОРУ I'torn Scuce wю ,т со Rerno:e wю ет ~ IhshOO , coгcp~ а! QJ ,QI, zcaз Ш : 51 5J , у""" L"" ,, -

~~=============-~~-~
• ~3апустите броузер ком пьютера, за грузите страницу по
умолчанию (Default.aspx) через URL и п ощелкайте несколько раз на
кнопке Refresh, затем то же самое сделайте дл я страницы
Page2.aspx. По сле этого также через URL вызовите виртуальную
страничу Trace.axd, на которой и будет собрана вся трасс ир овка
последних запросов
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

~ http://localhost/MyFlГstSlte/Trace.axd- Мicrosoft Internet Explorer


FIe Edit Vfew Favcrites TooIs НеР

.... Back ... ..... I.D [fJ ~ ' Q. Seif"ch ~ Faycrites


ActlesSJt::I http://'ocзhJstftv1yFгstsitе/Тгасе, зхd

Application Тгасе
[ clea r cu rren t tra ce ]
Physical Directory:c: \inetpub\w wwroot\

Requests to this Application Remaining~


N Time of
File St8tU$ V Ь
о. Request Code ег
07.01.2008
1 М У Fi rstSite{ Defа u It.aspx 200 GET V jew Detal ls
11:06:37
07.01.2008
2 М У Fi rstSite{ Defа u It.aspx 200 GET Yiew Details
11:06:40
07.01.2008
3 MyFi rstSite{Page2.aspx 200 GET V jew Detaj ls
11:06:52
07.01.2008
4 MyFi rstSite{Page2.aspx 200 GET yjew Details
11:06:57
07.01.2008
5 М У Fi rstSite{ Defа u It.aspx 200 GET yjew Detalls
11:07:16
07.01.2008
б М У Fi rstSite{ Defа u It.aspx 200 GET Vie w Detai ls
11:07:20

Мiсrоsoft .NET Frame work Version :2.0.50727 .42; ASP.N ЕТ


Version 2.0.50727.42

1i1 ГГГI ~ LОС3htriflеt

Щел ч ком на гиперссылке View Details можн о раскры ть трасс и ровку


любо го запроса. Щелчок на ссылке [ clear сшге пt иасе ] очисти т
виртуал ьную страницу Trace.axd точно также, как и п ерезагрузка
компьютера.

Секции трассировоч ных данных

Ин формация , которую выдает сервер п ри ВЮlюч ен ной трасс и ровке ,


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

Се кции трассирово ч ны х данны х


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Секция Описание

Reqllest
Содерж ит общую инф:Jрмацию о запросе ст р аницы
Details
Содержит сведения о пр оизводи тельно сти , связанные с
событиями жизненного цикла страницы. В столбце From
First(s) находится абсолютное время , отсчитываемое с
Тгасе
l' • момента получения запроса страницы (нулевое время) до
lпюпnatюп
начала обработки очередного собы тия. В столбце From
Last(s) nоказана дли тельн ость обработки nредыдщегоo
события.

Co ntro l Содержит инф:Jрмацию обо всех элементах ynравления


Тгее страницы, включая размер занимаемой ими памяти

Session
Содержит все n ереме нны е сеанса и их знач ения
State
Appocatio n
Содержит все n ереме нные nриложения и их состояния
S tate
Reqllest
Отображает cnисок всех файлов cookie (куки), полученных
Cookies
сервером в составе запроса
Collection
Rеsропsе
Отображает список всех файлов cookie, переданных
Cookies
броузеру в составе отклика
Collection
Headers Отображает список НТГР-заголовков, полученных сервером
Collection с запросом

Rеsропsе
Отображает cnисок НТГР-заголовков, переданных броузеру
Headers
в составе ОТЮlИка
Collection
Fопn Содержит пары key=value элементов ф:Jрмы, отправленных
Collection броузером с обратной отсылкой PostВack
Q llerystring
С 11_·
оШ:"сtюп
Содержит пары key=value, ВЮlюченные в строки запроса

Server
Отображает состояние всех серверных nеременных
Variab)es
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Отложенная компиляция Web-страниц

ASP.NET поддерживает отложенную (динамическую) компиляцию для


экономии дисково го пространства сервера. ЭТО значит, что на сервер
мы можем разместить страницы с исходными текстами такими , как они

выглядят при проектировании. Но при первом запросе страницы она


компилируется в DLL · сборку и помещается во временный каталог
среды исполнения. Все последующие обращения к этой странице
теперь уже обрабатываются DLL·сборкоЙ

Выводы

1. Web-сервер отвечает за получение и исполнение запросов к


ресурсу и отправку ОТЮJиков

2. Web-броузер (браузер) за получение да нных от сервера ,


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

з. Н1ТР - протокол передач и текстовых данных для взаимодействия


броузера и сервера
4. Обычный способ отправки да нных на сервер, после первого
запроса страницы, называется обратной отсылкой PostBack
s. ASP.NET подце рживает две модели программирования Web-
страниц: с встроенным (совмещенным) кодом и отделенным
(застраничным) кодом. С траница с совмещенным кодом ВЮlючает
в себя код разметки (НТМL) и код языка программирования ,
который размещается в секциях <script> . Таких секций может
быть сколько угодно и они могуг располагаться в любом месте
страницы. Страница с отделенным кодом размещается в двух
файлах: файл разметки и файл кода
б. Динамической компиляцией называется отложенная компиляция
Web-страниц, выполняемая только при первом запросе страницы
пользователем. Разработчику сайта достато чно разместить
страницу с исходным текстом в нужном месте сервера, а об
остальном позаботится среда исполнения (машина, движок)
ASP.NET
7. ASP.NET подце рживает страницы на разных языках

программирования, при условии , что на одной странице


применен только какой-то один язык
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

8. В ASP.NET для глобальной и индивидуальной настройки ее


раБОТbI применяется иерархия конфигураЦИОННblХ файлов. При
формировании кэша настройки парам еТрbl конфигураЦИОННblХ
файлов, расположеННblХ ближе к исполняемой стра ниц е имеют
больший приоритет
9. Функцию трассировки ASP.NET применяют для наблюдения за
пр оизводи тельно стью и использованием ресурсов сервера

10. В целях безо пасн ости при п еремещении на рабочий сервер


отладку и трассировку страниц нужно отключать

"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Web-формы

Абсолют но е позиционирование элеме н то в управления. Обработчик


п ереключ е ния экзем п ляра элеме нта CheckBox. Модел ь собы тий
AS P.NET Автомат ич еские обратные отсылки . Сохранение состояния
ви да. Этапы выполнения страниц на сервере. Обработка событий .
Ав томат ич еская п ри вязка данн ых. Стра ница как ко н тей н ер элементов
управления. Прогр амм н ое управление заголовком страницы . Создание
элемента управления во время выпол н е ни я. К ласс Page. Объекты
Session, АРРlicаооп, Cache. Объект Request. Объект Response. Объект
Server. Объект User.

Файлы к лекц ии Вы можете скачать здесь скачать:

http://o и. intШ . ruld epartment/intemet/prasp пеt/зюз _ We bS пе 2. zip

Стра ницы ASP.NET, официал ьн о известные как Web-формы , являются


н еотъемлемой частью пр иложения ASP.NET Э ТО конкретные
ин те рфейсны е единицы, которые кrlИенты MOryr запр ашива ть и
отображать в своих броузе р ах. Web -формы в ASP.NET подце р живаю т ту
же техноло rnю ви зуал ьного прorра мм ирования , что и Windоws-формы В
локальных прилож ениях. А это очень удобно дл я бедных и н ес ч аст ных
разработчиков, т.е. нас с вами.

в ос н ове Web-форм НТМL-страниц леж ит дескр иптор <fo r т> . ..


</ f o r т> . В акт ивны х страницах други х систем , например РНР ,
страница до п уска ет наличие на ней нескольких дескрипторов
< fo r m> . .. < / fo r т> (дескрипторов Н ТМL -форм). В таком случае эти

дескр иптор ы долж ны им еть атри буг ы ID с ра з ными значениями , чтобы


п оддерж ивающая актив н ые страницы с и стем а мо гла р азл ичать, какая

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

Стра ницы ASP.NET тр ебуют, чтоб ы на каждой из них было не более


од ной формы (в п ринципе, форм на стра ниц е может б ы ть несколько, но
в каждый момент видимой Visib le=True может б ы ть тол ько од на форма).

Но этого достаточно и для обычной НТМL -стр аницы , да бы сколько бы


элементов у пра вления Н ТМL - фор м а не содержала, с ни х всех
собирается информация п ри подготовке обратной отсылки на сервер .
Когда по льзо ватель щелкает на кнопке Submit, броузер извлекает
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

текущие з начения п оследовательн о с каждого элемен та управления и

формир ует и з ни х длин ную строку п ар I D=з н ачение . З атем эта


строка отпр авл яется на сервер странице , указанн ой в атр ибуге act i on
дескр иптора < f orm> , исп ользуя метод post , или метод get . Если
атрибуг а с ti оп не указан, то данные отправляются той же странице .
С ам НТМL н е устанав л ивает на количество форм никаю1Х ограничений ,
а ASP.NET устанавливает и для одной а ктивной страницы способна
ге н е рир овать тол ько одн у НТМL- форму < form></ f o r m> .

Пусть имеется страница Page.aspx, кото р ая хоть и имеет расширение


.aspx, но содержит код обычной статической ст р а ницы . При
выполнении такой страницы система AS P.NET отпр ави т ее
п ользователю как есть, ни че го не доба вляя . Хотя при этом будет
за трачено вр емя на разбор кода и о пр еделение того, что ничего не
н ужн о доба влять.

<html>
<head >
< title>Посылка сообщений </titlе >
<meta content=''text!html; chaгset=windows-1251" http-еquiv="Сопtепt-Туре
</head >
<body>
< fопn method="get" паmе="fо пnl ''>
<р>

Ваше сообщение:
<input id="rпеssаgе" name="message" type="text" value='Hello, world!'':
<br>
Кто посылает:
<input id="autor" name="autor" type=''text'' vаluе="СНЕТКОВ В.М.">
</p>
<р>

Кто примкнул К сообщению:


</p>
<ul>
<li>
<input id= ''P'' narпe=''Р'' type="checkbox" value="checkbox''>
Петров Петр </li>
<li>
<input id= '1" паmе=' 1 " typ e="checkbox" value="checkbox">
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Иванов Иван <Ili>


</ul>
<р>
<input id ="OK" type="submit" value="Submit''>
</p>
</form>
<!body>
</html>

Листинг Пример страницы Page.aspx

Ваше сообщение: Hello, \Norldl


Кто посылает СНЕТКОВ В.М.

Кто примкнул К сообщению .

• О Петров Петр
• О Иванов Иван

Submit

Представление в броузере (клиен те)

Нажмите на кнопку Submit и посмотрите в пол е адреса броузера. Форма


отослала на сервер строку

WеЬFОПIl5 . htm?
message= НеПо%2С +World%21&autor=C НЕТКО В + В.М.&О К =Submit

Посюльку В форме указан метод get , то к URL -адресу через символ


вопроса ( ?) оказалис ь присоединены пары имя = значе ни е, разделенные
амперсан до м ( & ). Обратите в ни мание, что символы пробела ,
восклицательный знак, запятая (и если вы введете русски й текст)
заменяются двухбай тны ми юдам и с предваряющим с и мволом процента
(% ).

ЭТО на зывается URL-кодир ованием сообщения формы в до п устимые


символы латинских букв и цифр (для пр остоты С Н ЕТКО В В.М. как раз
и введено латинскими буквами), чтобы сообщение не содержало
управляющих символов, способных вызвать н ежелательный эффект.
Посюльку прин имающая стран ица не указа на , то принимающей от

"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

кrlИента данные qюрмы на стороне сервера будет та же самая страница.


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

Мы уже говори ли, что если такую страницу разместить на сервере, то


не смотря на расширение .aspx, ASP.NET -машина ее все р авно

обрабатывать н е будет. Для этого НТМL-дескрипторы нужно сделать


активным и (серверными) добавлением атри бута r una t= " зе rver ". в
связи с этим сделаем два определения: та страница, которая не

содержит серверных дескрипторов, называется статической


(пассивной). Если же на странице есть хоть один дескри п тор с
указанным атрибутом, то такая страница подлежи т дальнейшей
обработке системой ASP.NET (или иной) и называется динамической
(активной).

Отсюда мораль: статическим страницам лучше при сваиват ь расширения


hun или htm1, чтобы серве р при их запросе кrlИентом без промедления
осуществлял отправку. Если же присвоить статической странице
расширение aspx, то все равно она без изменений бу,цет отправлена
клиенту, но пр ежде пройдет через систему обработки, что потр ебует
допол ни тельного времени и напра сной траты машинных ресурсов.

Пример кодирования страницы

Оболочка имеет две основных вкладки с элементами пользовательского


интерфейса для подцержки активных страниц, Standard и НТМL.
Вкладка НТМL содержит элементы, напрямую поддерживающие
стандарт НТМL- дескрипторов, и н ужна для то го , чтобы с
минимальными переделками можно было приспособить старые
страницы к новой технолоrnи АSР.N Ет. Достаточно добав ить к
дескрип тор ам таких элемен тов атрибут r unat= " server ". Вкладка
Standard содержит более развитые элемен ты управления, имеющие
больший набор свойств и событий , пол но стью ориентированные на
объектное программирование.

При помещении элемен тов с вкладки НТМL на страницу атрибут


runa t = " se r ver " автоматически не добавляется и такой элемен т

"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

средой на сервере об р абатываться не БУдет. Следовательно , кодировать


на языке программирования его будет нел ь зя . Прежде элемент н ужно
п омети ть как сер верн ы й , введя напрямую указанный атрибуг в
дескрип торное представле ние элеме н та, или в оболочке в режи ме
Design на выделенном элеме нт е вызвать кон текстное меню и выполнить
опцию Run As SelVer Со пtго l (сделат ь серверным элементом управлен ия)

J.. ..
butlon

t J!; Cut -
'tI Сору

lfI Paste
Paste Altегn.зtе

Х Delete
Style ...
RlIl As Serveг Contrd
I I
I!З. View in Browser
Edrt Imag€
Show Smart Tag

rE Rе1Теsh

~ Propeгbes

Если мы разрабаты ваем актив н ую стра ниц у "с нуля", то лучше сразу
п риме н ять серверные элементы управления, где уже автоматически

встро е н дескр ип тор runa t=" s е rve r " . и более того , если его уб р ать ,
это БУдет счи таться Оl.Ш1бкоЙ. Дескрипторы, представляющие серверные
элемен ты , начинаются с метки asp : Т ип элемента , далее следуют

атрибугы элеме н та.

Для примера создадим пр остую страницу.

• Г;:;=Создайте н овый сайт командой FilelNewlWeb Site ... , настроив


окно мастера примерно так
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Ne\·, Web Slte .1J~

111 "

Зе",ф 01 1,...,
Te"l'~tEs",

IА ыл< A5>JoET WOO si'E

Loca~ m : "lcC
"O oC
,,=.Cm
---i!" Гсlс--;\,,"";;;i\w;;"';ы;о,•;-,----::========---:i!~.. ВrOWS8",
L~: IC\C
ruC,C"C,,------i!;]

После щелчка на кнопке ОК БУдет создана нач альная страница , которая


состоит из двух файлов: Defauk.aspx и Default.aspx.cs.

Существует два вида кодировки страниц ASP.NET:

1. Стран ицы со встроенным кодом (совмещенным), когда весь код С#


и НТМL· дескрипторы хранятся в одном файле .aspx
2. Стран ицы со скрытым кодом (раздельным, застра ни ч ным) , когда
код С # хра ни тся отдельно от кода с дескрипторами в фай ле
.aspx.cs

Второй способ лучше и начальная страница сай та создается именно так.


Большой Билл рекомендует использовать и ме нно второй способ, чтобы
разделить дизай н страницы и ее функциональность. Но для тр е нир овки
оди н разок мы воспользуемся п ервым способом.

• ~ ерез пан ель Solution Explorer Удал и те файл с кодом С#


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

С:\ Tmp\WebSi!e1 \
Ц! App_Data

(>реп Witi1

D V>e., DeskJner
Vi€w Component Designer

ВUikJ page

JIi Cu!
Сору

Wete

• ~ редакторе HTM L· decKpunmopoe скорректируй те деЮlар ацию


Page, чтобы о на стала такой

<%@ Page Language="C#" % >

• ~Сразу под деЮlараци ей создайте ко нтей н ер <sc ri pt


runat= " server " ></ script> для бу,цущего размеще ния в
н ем кода С#. ЭТО можно сделать либо напрямую в режиме Sо шсе ,
либо в режи ме Design двойнь/Л1 щелчкам н а страни ц е создать
об р аботчи к соб ы тия по умолча н ию Page_LoadO, который оболочка
п оместит в блок скриптов (а затем за н е н а.цоб н остью обработчик
мож н о Удалить)
• ~ ол н ость у,цал и те деЮJaрацию ООСТУРЕ (н е обязательно, но
чтобы н е мешала)

< !DQ CТYPE html PUBLIC "- /IWЗС /IDТD ХНТМL 1.0 Tгans [ionaVIEI

Те п е рь мы п олуч или стран иц у, где код С# н уж но БУдет разме щать в


кон тейнер ы <scri pt r unat= " server " ></ scr i pt> . Э ти х
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

кон тейнеров на стран иц е может быть сколько угодно и они MOryr


располагаться в любом месте. ASP.NET перед выполне ни ем все р авно
скомпилирует стра ниц у, пройдя весь ее код. Но все же р екоме ндуется
и меть оди н ко н тей н ер и располагать е го вначале страницы (для
удобства бедного со пр овождающего про гр амм иста) . Начальная
за готовка стра ниц ы будет выглядеть так

<%@ Page L апguagе="С#" %>

<script nmat="server''>
</script>

<html xmlns=''httр ://www.wЗ.огgl1999/xhtml''>


<head nmat="server">
< title >Uпtitled Page</tide>
<lhead>
<body>
< fо пn id="forml" ruпаt="sеrvег''>
<div>
</div>
</foпn>
<!body>
<lhtml>

Листинг Начальная заготовка страницы Default.aspx со


встроенным ходом

Создание обработчиков

Для нашего просто го при мера мы создадим два об р аботчи ка готовых


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

Обработчик загрузки стран ицы


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Напомним , что каждый раз при по стynлении на се р ве р п ервого запроса


или обратной отсылки ( по сти нга ) с да нны м и ини циирует ся создание
объ е кта страницы. И как то лько объект страницы БУдет за гр ужен в
памят ь и будуг созда ны и инициализированы все элементы стр аницы ,
срабатывает соб ыти е Load, с котор ы м мы свяжем функцию-обработчик
с н уж ным нам кодом.

Обы чно , при разработке визуальных элементов ynравле ни я, имеющих


события, н азнач ают событие по умолча нию для того, чтоб ы оболочка
при д войном щелчке на элемен те в режиме Design автоматичеси
созд авала обработчик именно этого события. Н а п р и мер, для элемен та
Вuttоп это событие Cl i ck , дл я флажка CheckBox
CheckedChanged, и т. д. Соб ыти е по умол ч анию назначается с
ПО МОI.l.\bю атр и буга [Ое f а u 1 t Eve n t ( " Имя событ ия") ] .

• ~ ереведи те страницу в режим Design и двойным щелчком на


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

<%@ Page Lапguаgе="С#" %>

<script ruпаt= "server''>


protected vo id Page_Load(object sепdег, ЕvепtAгgs е)
{

}
</script>

<html XmInS= ' huр ://www.wЗ .or!j'1999/xhtml' '>


<head ruпаt= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nmat= "server''>
<div>
</div>
</fоПll>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</body>
<lhtml>

Листинг Страница после создания обработчика события


Load
Заметьте , что в дескрипторе <form> н ет атрибугов act i on и
method, это значи т, что данные от юше н та ф:J р ма БУдет посылать
этой же странице, и посылать и х будет методом pos t (метод get
пр и соединяет данн ые элементов ynравл е ния к URL-адресу). ЭТО
нам и нужно , поэтому ничего н е будем менять.
• r;:;nоместите с ВЮIaДКИ Standard панели Toolbox элементы Labe~
CheckBox, TextВox, Button и через панель Properties оф:Jрмите их по
умол чанию примерно так, как п оказано на рисунке

Default.aspx*

['LаЬе1лl !\'"' Red


Имя: ,rtHeHOB '
Прив~тДОрогоЙ ;оварищ(го С"подии) ['L abe1211

liJ Обновить

И сходный код стра ни цы Defauh.aspx будет та ким

<%@ Page Language="C#" %>

<script runat= "server',>


protected void Page_Load(object sender, EventArgs е)
{

}
</script>

<html XmInS= ' huр i/www.wЗ .or&,1999/xhtml' '>


<head runat= "server''>
<tide >Начальная страница </tidе >
<lhead>
<body>
<form id= "forml " nmat= "server''>

"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<div>
<asp:Label ID='1.abel1 " nmat="server''> </asp:Label>
&nbsp;&nbsp;&nbsp;
<asp:C heckBox ID="C heckBoxl " runat="server"
Text="Red" I>< br 1>
Имя :
< a s p :Te xtВox ID =' TextВo x l " runat="se rve r ''>C HeTКOB </asp:TeX1

Прив ет дор о гой т о варищ (гос п од ин)


<asp:Label ID='1.abel2 " nmat="server''> </asp:Label><br 1>
< Ьг 1>
<asp:Button ID =' 'В uttопl '' nmat="server" Те хt=' 'Обновить '' 1>
</div>
</fonn>
<!body>
<lhtml>

Листинг Исходный код страницы примера Default.aspx

Включени е режима абсолю тн ого позицио нирования


элемен тов уп р авле ния

Порядок размещения элеме н тов управления н а форме п роектирования


страницы определяет и п орядок размеще ни я генерируемо го ими HTML -
кода на компьютере юш ента (кода разметки страницы) . При изменении
размеров, стиля или выводимого текста рендерин г автоматически

смещается в броузере без наруше ни я порядка следования и н формации.

Если какой- то элеме н т уп р авления жестко зафиксир овать на web-


странице, то и ре н дерин г этого элеме н та в окне броузера кл и ента также
будет зафикс и рован. ЭТО может привести к тому, ч то рендеринг одних
элемен тов управления в броузере будет нап олзать на ДР)'П1е элементы
НТМL-вывода стран иц ы. В резул ьтате н а клие н те может п олучиться
п римерно вот такая меша нин а

Привет всем!!!lпривет всем!!!


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Но все равно, в н екоторых случаях может п онадобиться им ен но


абсо лютно е позицио нировани е. Вот как этот р еж им в оболочке можно
включить:

• ~ ереведите страницу .aspx в р ежим Design, чтобы появилось


мен ю Layout оболочки
• Г;:;=Выберите команду меню LayoutlPositionlAuto-роsitiоп Орtiопs и
настр ой те диалоговое окно так
Пl'tюп~
==----.1J~
Ш·· Еп v О- m rrmt

Ш Рго ;з,ts in:J So utms


Ш·· SE>.п е Crnl10l
I!J .. тe.t Edl1D"

IE О ,ЬЬа8С Тоо Ь

IE Dob.щ hJ
1jJ·· Dev O:e Tools
г snap р.хеl-Ьаээd pos ~ms in:J s~es to tffi b l ~"."'" SE(t ..... :
ш нт м. Оез чer
, Ю-izооtal spac ..... :
rs-- pixels

Vetti:a' spac ..... :

Г pixels

о< Car>:EI I
I

Обработчик переключения экземпляра C heckВox l


элемента CheckBox

• ~ызовите панел ь D ос umепt Оutliпе кома н дой ме ню View/Other


WindоwslDосшne пt Оutliпе и в р еж им е Design выдел и те в де р е ве
объект CheckBoxl
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Document Out:n: .....Q. х Default..aspx*


.:J oefiJJ t.aspx
B~ forml ['W>,11] ''f-~____
~. ~] -<DIV> Имя: rt' H8HOB
'.,~ Labell
Привет дорогой товарищ (господин) [Labe12]
'·~ !!!nтз ММ
;.E'! -<6.R>
i.,~ T.extвoxl
r Обновить
Н!:З -<ВR>
:·~ Label2
;.E'! -<6.R>
'. Е3 -<ВR>
Ц~ вuttОnl

• ~ ерейдите в п анел ь Properties, п ереведите ее в режим Events


(значек мол нии ), найди те собы тие СhесkеdСhaпgеd и двойным
щелчком на поле событи я создайте для него обработчик

РгорегtJеs .... .r;t х

CheckBoxl System.Web.UI,WebCOIlU'"

Disposed
Init
Load
PreRender
Unюad

Центрировани е интерф ейса

Отцентрируем наши элемен ты н а странице . Для это го

• ~ ерейдите на ВЮJaДКУ Source стра ницы . Установите курсор


внугри контейне р а <d i v></div> . В ни ж н ей части окна
редактора щелкните н а кнопке <di v> , чтобы выдели ть блок
HTML -Koda

"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

~! lюdу )-

Обрати те внимани е, что в ме н ю оболочки для вюыДки Source нет


пункта Fопnat, который появи тся только на вкладке Dе s igп .

• ~ e снимая выделе ни я т екста п ерейдите на вкладку Dе s igп.

Мы ви д им , что все элементы кон тейнера <d i v>< I d i v >


остал и сь выделенными и появилось меню Format.

• Г;:;=Отцен трируйте выделенные элементы страни цы командой

Detщ

UJ • !ОН, ~ I.!> ~ ").!, 0=""


"".,,-
.. _ __
~ Т1 т б New Ro ~ 12pt ~
~ Fcreg"C...n:J CW ", хктм.. 1,0 TriflSi!) ~ I
.е. Backg-c:<..n:J CW ",
Foot ~

I!, Coovert to НyperIГt ", C!rI+L


Insert Вook m if"k ", C!rI+ Shft+L '11 Rфt

~ •• lisbfy

мake Sз т е Эzе

Н<xizalt3 Spach]

УегЬ:aI Spach]

,,&

Ле гко замети ть , что эти действия п ривели к добавлению в дескрип тор
<d i v> атрибуга в н угреннего стиля

<div sty1e=' 'text-align: сепtег ">


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

</div>

Это наглядный прим е р того, чт о зная где и что подкруги ть, можно
п одкручивать и н а прямую. НТМL-дескрипторы такие "одноклеточные",
что все их пов едение ' 'написано у них на лбу". Но чтобы опуститься до
их уровня , нам нужно попот еть при подъеме в гору Серверные
элементы из вкладки Standard на много сложнее, зато несравненно
функциональней и полностью подцерживают парадигму объект НО­
ориентированного программирования. Их настр ойка большей частью
выполняется через код С# и п анель Properties.

Стоит упомянугь пр о режимы редактирования Design и Sошсе. На


сервере наша активная страница все равно БУдет хра ни ться в виде кода ,
как он пр едставляется на вкладке Sошсе ( ... и терпеливо ждать своего
по сетителя). Режим Design является средством визуального
про ектирования и пр една значен для разработчика (нас с вами), чтобы
существенно упрости ть (ускорить) его работу.

Заполнение обработчиков кодом

Заполним обработчики. При загрузке странице по п ервому запросу и ли


обратной отсылке (постинга) мы хотим , чтобы в объект L abe11
пом ещался снимок таймера сервера. Конечно, это не лучший способ
спрашивать время у сервера (ходить за семь верст киселя хлебат ь) , когда
то же самое можно спрос ить у таймера клие н та. Но пока мы не
использовали JavaScript, на м и это сойдет. Кроме этого, в обработчике
копируется з начени е поля объекта T e x tBo x 1 в метку Labe 1 2 и
добавляется ВОСЮlицание.

Второй обработчик устанавливает цвет переднего плана и qюна метки


L abe 11 . Он срабат ывает только тогда, когда при обратной отсылке
(постинге) обнаружено изменение состояния объекта Chec k Bo x1 .
Если состояние Chec k B o x 1 междУ двумя обратными отсылками не
и зменялось, то события CheckedChanged не возникает и код
обработчика не выполняется.

Полностью код страницы в режиме Source для нашего при мера будет
таким
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<%@ Page L апguagе="С#" %>

<script nmat="server''>
protected void Page_Load(object sender, EventArgs е)
{
Label1.Text = 'Текущее время:"
+ DateTnne.Now.ToLongТuneStringO;
Label2.Text = TextВoxl . Text + "!!!";
}

protected void С hес kВо хl_СhесkеdС hапgеd(оЬjесt serкler, ЕvепtAгgs е)


{
if (CheckBoxl.Checked)
{
Label1 .ForeColo r = System.Drawing.Co!or.White;
Labe!l.BackCo!or = System.Drawing.Co!or.Red;
}
e~e
{
Label1 .ForeColo r = System.Drawing.Co!or.Black;
Labe!l.BackCo!or = System.Drawing.Co!or. White;
}
}
</script>

<html xmlпs=''httр ://www.wЗ.огgl1999/xhtml''>


<head nmat="server">
< title > Начальная страница </titlе>
<lhead>
<body>
< fо пn id="fопnl" ruпаt="sеrvег''>
<div stуle=''tехt-аligп: center">
<asp:Labe! ID=''Labe!l '' runat="server''></asp:Labe!>
& пЬ sр;&пЬs р ;&пЬ sр;
<asp:CheckBox ID="CheckBoxl" runat="server"
Text=''Red'' ОпСhесkеdСhaпgеd="СhесkВохl_СhесkеdСhaпgеd" 1:
Имя:
<asp :TextBox ID='TextBoxl" runat="server' '> C H eTКOB </as p :TextВox><
Привет дорогой тов ари щ (господин)

"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<asp:Labe! ID=''Labe12 '' runat="server''></asp:Labe!><br />


< Ьг />
<aspButton ID='Button1" runat="server" Теxt="Обнови ть" />
</div>
</form>
</body>
</html>

Листинг Код страницы примера Default.aspx

• ~3апустите пример , должен получиться внешне

при бл и зительно такой результат

06f108ИТЬ

НТМL · страница на стороне клиен та

Модель событий ASP.NET

в пред ыдущем пример е мы продемо нстрировали использование


н екоторых событий для управления интерфей с ными элемен тами. Такой
п одход упрощает программирование. Разработчик добавляет элементы
управления на WеЬ·форму и затем решает, на какие события н ужно
реагировать. В ASP.NET события работают следующим образом:

1. Клиент первый раз запраl.Ш1вает ст р ани ц у. Среда исполнения


ASP.NET создает объекты страницы и элементов управления ,
выполняется код инициализа ции , страница преобразуется в НТМL
и возвращается клиенту. Объекты страницы сразу же у,цаляются из
па мяти сервера , освобождая место для других запросов.
2. Получив НТМL · страницу ютиент что-то с ней дела ет и
инициирует об р атную отсылку - по стинг (например , щелкает на
кнопке Submit ). Броузер собирает данные со всех элементов
формы и события , которые прои зоштlИ на ют и е н те, упаковывает
все это в пакеты (''пакует ч емоданы ") и отправляет целевой
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

странице сервера на обработку. Целевая страница указана в


атрибуге action НТМL-дескрuптара qюрмы. Каждый пакет
посылается отдельно и с уведомлением ус п ешной доставки.
З. На сервере ASP.NET получ ает ПО СТУПИВlШIе пакеты ,
р аспаковывает и соединяет их. Затем запускает целевую страницу
и предает ей полученные данны е.
4. Целевая страница загружается в память, повторно создаются
объекты с начальной инициализацией как при первой загрузке.
s. Затем серверная стран ица переводится в состояние, какое она
имела перед последней отправкой юшенту. Инqюрмацию о
п оследнем состоянии серверной страницы ей передал клиен т. Э ту
инqюрмацию он получил от страницы в скрытых полях вместе с
последним ответом и теперь вернул в н еизме нном виде в своем

новом запросе (обратной отсылке). Инqюрмация о последнем


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

б. После этого ASP.NET приступает к анализу поступивших собы тий


и определяет, что клиент хотел сделать с данны м и перед обратной
отсылкой.
7. И наконец, Удовлетворяя требования клиента выполняет
действия , предписанные событиями в соответствии с
имеющимися обработчиками. Тем самым qюрмируется новое
состояние серверной страницы и новый НТМL-ответ, который
отправляется клие н ту вместе с новым состояни ем вида в

скрытых полях.

8. После сгенерированного НТМL-ответа страница немедленно


выгружается из памяти сервера.

Автоматические обратные отсылки

в нашем примере только кнопка Submit генерирует обратную отсылку на


стороне клиента. А любые изменения в элемен те Te xt Bo x l и ли
CheckBox l не БУдУГ обработаны до нажатия этой кнопки
(фактической отправки qюрмы на серверную обработку). С одной
стороны это хорошо, меньше ресурсов тратится на пересылку, но с

другой - пользователь не получает немедленный ОТЮlик на свои


действия.
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

в серверных элементах управления таЮ)й случай предусмотр е н. Если


включить свойство AutoPostBack элемента в состояние True. то
после заве ршенных изменений в состоянии элемента автоматически
броуэером будет иницииров а на обратная отсылка. Это происходит за
счет того, что элемент ynравления с таким установленным свойством
при ответе нар яду с НТМL генерирует до п олнительный скрытый
Java Script -Ю)Д, заставляющий броузер выполнять обратную отсылку
всякий раз, Ю)гда происходит и зме нение состояния этого элемента

пользователем.

Проверим это на нашем предыдщемM прим е ре .

• r;:;'выделите на странице Defauh. aspx объекты Te xt Bo xl и


Chec kBox 1 и в панели Properties установите для ни х свойство
AutoPostBack в значение True . Вы видите , что в
дескр ипторах эт и х элементов сразу появился до п олнительный
атрибуг AutoPostBack= " T r ue ". Теперь при генерировании
ответа клиенту эти элементы бу,цуг генерировать и Ja vaSc ript-Ю)Д
обратной отсылки .
• г;.:;=Запустите страницу на вы п олнение и в появившемся окне
броузера через Ю)нтекстное меню выполните опцию VIt'W Sошсе .
Среди прочего HTML-Koda можно увидеть и Ja vaSc ript-Ю)Д
обратной отсылки

<script type= ''textJjavascript''>


<!--
var theForm = dосшnепt.fоrms[ ' forml ' ] ;
if (!theForm) (
theForm = dосшneпt.fоrml;
)
fuпсtiоп _doPo stВack(eve ntTarge t, еveпtArgшneпt) {
if (!theFormonsubmit 11 (theForm.onsubmit() != false)) {
theForm._EVENтrARGET. value = eventTarget;
theForm._EVENТARGUMENT.value = еvепtA rgшneпt;
theForm.submit();
)
)
// -->
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

</script>

<input id="CheckBoxl" type="checkbox" name="C hec kBoxl "


о ос lick =' 'javascript:setTnneout('_do PostBa ck(\'C heckBo х l \', \'\')', О)"

<input ю='ТехtВохl" type= ''text'' пате='ТехtВохl" vа luе=''С идоров ''


о ochange= 'Javascript:setTnnео ut('_do Po stВack (\'ТеxtВо х l \', \'\')', О)"
onkeypress="if (WebForm_ TextВoxКeyHandler(event) == false) геtшг

Ах!, какие умные эти серверные элементы: сами сеют - сами жнyr
- сами песенки поют!!!

• ~ оизменяйте состояние элементов в броузере. Теперь на


каждые изм е нения серверу генерируется обратная отсылка
(постинг) для обработки. Зачем ждать, как в армии , общей
команды Submit...

Обратите внимание, что НТМL-элементы во ВЮJaдке НТМL панели


Toolbox - слабосильные и автоматическую обратную отсылку не
выполняют.

Но все хорошо в меру! Частые запросы к серверу перегружают сеть и


замедляют работу. Да и встраива ем ый в ге н е рируем ый сервером ответ
Jаva Sсгip t-КОА также увеличивает объем передаваемой броузеру
информации. Поэтому слишком увлекаться механизмом автоматических
обратных отсылок не стоит.

Сохранение со стояния вида

Давайте опять вернемся к нашем у простому пример у и выполним


следующее:

• ~ерните свойство AutoPos tBack элементов Chec kBo x 1 и


Te xt Bo x 1 False
опять в состояние

• ~ыделите элемент
Labe 1 1 и установите его свойство
EnableViewSta t e в состояние False (по умолчанию оно
установлено в значение T r ue ). Немедленно в дескрипторе
элемента появится атрибyr EnableV i ewSta te= " Fal зе "

"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• ~Запустите приложение и отметьте, что цвет элемента Labe11


(Текущее время: ... ) меняется ТОЛЬЮ) при первой отсылке после
изменения элемента Chec k Bo x l. Последующие отсылки
восстанавливают начальный цвет.

Что здесь проис ходи т, почему цв ет метки выполняет ТОЛЬЮ) п е рвое


новое указание элемента Chec kB o x 1 ... Все дело в протоколе НТГР и
во времени жизни страницы. НТГР - пр отоЮ)л не хо чет сохранять

последнее состояние страницы, считая о ч е редн ой запрос к странице


п ерв ым , а сама страница существует ТОЛЬЮ) на время обработки запроса
и затем нем едлен но выгружается, чтобы освободить ресурсы сервера
для работы д ругих страниц.

Наша метка Labe 1 1 обновляет цвет только то гда , Ю)гда срабатывает


обработчик и зменен ия состояния элемента CheckBo x l . А это
происходи т ТОЛЬЮ) тогда, когда броузер пришлет информацию , чт о
прои зо шло событие и зме нения состояния элемента Chec k Bo x 1 .

До п устим, что пользовател ь поставил галочку в Chec k Bo x 1. Броузер


прислал это событие на стран ицу. ASP.NET это событие распознала ,
за п устила наш обработчик и зме нения цвета и в соответствии с новым
состоянием Chec kB o x 1 (checked ) выполнила Ю)Д

LabeI1 .ForeColor := S ystе m.Dгаw iпg. С оlог.Whitе;


LabeI1 .BackColor := Systе m.Dгаwiпg. С оloг.Rеd ;

Этим Ю)дом объект Labe 1 1 будет настроен и сгенерирует броузеру


соответствующий HTML -кod цветной метки. Но при следующей
обратной отсылке, если оставить объект Check Bo x 1 в том же
н еизменном состоянии checked, сведений о событии изменения его
состояния сервер н е получ ит. Поэтому и делать с элементом Labe11
при его создании сервер ничего н е будет, а сгенерирует его нач аль н ое
состояние , уста новленно е в пан ели Propertles. Что пользовател ь в
результате пол учи т от сервера - начальные установки цвета Label1. У
н его стоит гало чка цветности метки, а она присылается совсем с

другим, начальным , цветом.

Чтобы налади ть такую ситуацию, существует механизм сохранения


состояния вида. Э то т механизм встроен в каждый серверный элемент

"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

управления и по умолчанию ВЮlючен. Это значит, что элеме н т на и сходе


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

Некоторые элеме н ты , если ОТЮlючить у них ме ханизм состояния вида ,


все равно MOryr готовить перед своей ко н чиной некоторую ми н имально
н еобходимую информацию (сопиоl state), чтобы BocKpecHyrb
п одобающим образом. Этот механизм мы можем увидеть в НТМL-коде
на броузере , зап ечатлен н ый в скрытых полях, наподобие такой
автоматически закодированной абры - кадабры

<input type= "hidden"


naПlе= "_V IEWSТАТЕ" id="_VI EWSТAТE"
value="!wE PDwU L LТE20DAxOD I 50ТY P ZBYCAgМ P ZBYEAgМ
8WAMHQ2hIY2tlZGdkZGRkAgcPDxYCHgRUZXhOBRHQod l
OL 7QsiEhIW RkGAEF H 19fQ29 udНJ vb H NSZXFlaXJlUG9zdEJl
IfXхУВВQlDаGVjаOJvе D Е КD 82+ рlOhоЗОWiA2УZаdб l З t4 Z !

Атрибyr val ие скрытого поля hidden имеет значение упакованного


состояния элеме н тов управления , которое вместе с ответом п ередается

на временное хранение броузеру

• ~осстановите механ и зм сохран ени я состояния в и да эл е менту


Labe l l нашей страницы , вернув свойство
EnableViewState
в значение True . Проверьте работу элемента Label l, запустив
страницу Теперь все работает как надо - цветность метки
сохран яется п ри каждом ответе сервера!

Отметьте для себя , что сервер н ые элеме н ты сохр аняют интерфейсные


значен ия даже при ВЫЮlюченном меха ни зме сохранения состояния

вида. Про несе рверные (нет атрибyrа runa t == " se r ver " ) HTML-
эл е менты такого не скажешь . Web - элементы с ВЮliЩки Standard - все
серверные .
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Для прим ера добавьте на страницу (в любое место) из вкладки НТМL


элемен т Iпрut (C heckbox). Выполните страницу, измените состояние
элемента и отправьте страницу на сервер. Сервер вернет отклик с
первоначальным состоянием элемента. Если же пр евратить элемен т
Iпр ut (Checkbox) в серверный командой Run As Server ControL то элемен т
при постинге бу,цет сохранять свое состояние.

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

СО стороны сервера обработка Web-формы (страницы) средой ASP.NET


происходит поэтапно. На каждом этапе генерируются соответствующие
события, которые наш код может перехватывать и выдавать нужный
ответ. Поток обработки страницы проходит следующие этапы:

• Иници ал и зация структуры страницы


• Иници ал изация кода пользователя
• Про верка достоверност и дан ных
• Обработка событий
• Автоматическая привязка данных
• Очистка

Графически это можно изобра зит ь так


В.М С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

2 И rt " ~ WlИ'J ilJ.IИ Я


cт py t..Т~ pы с;рани цы
( Eiроу.зер ВЫАает .эа про.: 1

!
Ин и цм али.э аЦИ>l
3 IWДOl 1lOJl;.;wвоп еля

!
Про ве pt:a
4 ДОСТQl3 еpt1 ост и

!
ОбрабОТl:а
5 соБЫ ТИЙ

6 I 7
... , \. Броуз е р П ОЛУ"'OIет OТ~

8 Очоост <о

Жизнен н ый цикл стран ицы ASP.NET

Иници ализация структуры страницы

На этом этап е страни ц а за гружается в п амять, р асшифровывается


и н форма ц ия о состоянии ви да (если это обрат н ая отсылка) , за п ускается
событи е Page . In i t . Но это собы тие р ед ко обрабат ы вается
разработчиком , поскольку объект ы элементов управле ни я е ще не
создан ы , а информа ц ия о со ст оянии ви да еще п ол н остью не
рас ши фрова н а.

Иници ализация кода п ользователя

На этом этапе все элемен ты управления уже созда н ы и

"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

инициализированы начальными свойствами. Запускается событие


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

Для определения состояния страницы можно исполь зовать свойство


Page . IsPost Back , которое будет иметь значение f alse при
первом запросе страницы. 1 sPos tBac k является статическим

своЙство.м кnacca Page . ОНО всегда возвращает информ а цию ,


основанную на текущей странице. Можно также испол ьзовать свойство
эюемпляра как t his . IsPostBac k, что р авносиль н о

Page . IsPost Back .

Следует помнить , ЧТО в состоянии вида автоматически сохраняются все


программно и зме н е нные свойства. Инициализация элемента
управления в об р аботч ике события Page.Load считается программным
изменением , поэтому любое затрагива емое нами з начени е элемента
управления БУдет сохранено в состоянии вида. Это без нужды
увеличивает размер страницы и замедляет время передачи данных.

С цел ью ускорения подготовки состояния вида и минимизации размеров


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

в тех случаях, когда действительно легче инициализировать элемент


управления в коде, лучше отключить состоян ие вида для этого элемента

знач ени ем EnableV i ewState= " false " и инициализировать


элемент каждый р аз при запуске события Page . Load н езависимо от
то го , является ли текущий запрос обратной отсылкой и ли поступил
впервые. В качестве упражнения выполним пр о граммн ое
восстановление состояния метки в зависимости от состояния элемента

управления Chec kB o x 1 нашего примера


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• ~ыделите элемен т упр авле ния Labe 11 и ч е рез пан ель


Properties устан ов ите для него E nableV i ewS t a te= " f a1se "
• ~Юlючите флажок Chec kBo x 1 и мно гократно вып олни те
обратную отсылку, чтоб ы убеди ться , что состояние ви да L abe11
н е сохра ня ется

• ~До п олните блок скр ип тов страни цы Defauh.aspx кодом явного


вы зова обработчика Check B o x 1 Chec k edChanged ()

<%@ Page Lапguagе="С#" %>

<script nmat="server''>
protected void Page_Load(object sender, ЕveпtAгgs е)
(
Label1.Text = 'Текущее время:"
+ DаtеТnne.Nоw.ТоLопgТnneStгiпgО;
Label2.Text = TextВoxl . Text + "!!!";

11 Восстанавливаем Labell программно место состояния вида


С heck Вохl_ С heck ed С hanged( null, Е vепtAгgs. Empty);
}

protected void C heckBoxl_CheckedChanged(object serкler, EventArgs е)


{
if (CheckBoxl.Checked)
{
Label1.ForeColor = Systеm.Dгаwiпg.Соlог.Whitе;
Labell.BackColor = SystemDrawing.Color.Red;
}
e~e
{
Labell.ForeColor = System.Drawing.Color.Black;
Labell.BackColor = SystemDrawing.Color. White;
}
}
</script>

<html xmlns=''httр ://www.wЗ.огgl 19 99/xhtml''>


<head nmat="server">

"
В . М. СН"""'Б Про'ра....МuроваНuе 110 ASP.NET

< title> Н ачальная стран и ца< /titlе>


<lhead>
<body>
< fопn ю::::''fо ml1 '' runat=="server''>
<div styk>::::''text-align: сепtег">
<asp:Labe! ID::::''Label1 '' runat::::"server" Е паыeiеwst atе="fu.lsе" />
& пЬ sр;&пЬs р ;&пЬsр;
<asp :Chec kBox ID="Check Boxl" ruпаt="sеrvе г"
Text::::''Red'' ОпСhес k еdСhапgеd::::"Сhес kВ охl _С hес k еdС ha пgеd" /:
И мя :
<asp :ТextВox I D::::'TextВoxl" ruпа t::::"sеrvег' '> С н eT КOB </as p :TextВox> <

П р и вет дорогой то вари щ (го сп один)


<asp:Labe! ID::::''Labe12'' runat::::"server''> </asp Labe!><br 1>
< Ь г />
< аsр :Вuttоп I D=''Вuttопl'' ruпаt= "sеrvе г " Теxt="Об н о в и ть" 1>
</div>
</foпn>
<!body>
<lhnnl>

Ли с тинг Код с траницы примера Default.aspx

Теп е рь мы ви д им , что элемент La b e 11 р а ботает правильно ,


восстанавливая свое состояние программно в зависимости от

состояни я флажка.

Проверка до стоверно сти

При ф:эрмировании о братной отсылки броузер собирает с эл е ментов


дескриптора < f o rm > зн ачения полей и со стояния. Он не проверяет
соотв етствие типов собира е мых данных ожидаеМblМ значениям.
Например , если текстовое поле ожи дает цифры, а поль зователь ввел
туда буквы , з начени е поля нормал ьно будет передано на с ервер. Но
серверныи код ожида ет цифры и готов применить к ним
мате матич еские операции.

Если вовремя не обнаружить , что поступи л и отличные от ожидаемых


данные , то при их обработке во з никнет и сключит ел ьная ситуация и
В . М. СН"""'Б Про'ра....МuроваНuе 110 ASP.NET

выполнение прервется . Но самое опасное, что анализ ошибки БУдет


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

• ~3апустите стран ицу Defauh.aspx и введите в поле TextВox1


какой-ниБУдЬ текст в угловых скобках

Сервер немедленно п рервет выполнение страни ц ы и выдаст


сообщение Server Еггог in 'lWebSite1' Application с п одроб н ым анализом
ошибки.

Предварительная оценка допустимости дан н ых и называется проверкой


достовер н ости . Проверка достоверности может выполняться н а стороне
клиента, где при об н аружении н есо гласования можн о своевреме н но
п редупредить п ользователя и прервать обратную отсылку Э та операция
чаще всего п ро граммируется на языке сценариев JavaScript.

Но и серверная сторона также проверяет достоверность поступ и вших


данных, п режде чем начать их об р аботку. В ASP.NET предУсмотрены
специал ь ные класс ы ( валидатары ), которые вы п ол н яют п роверку
достовер н ости для закрепленных за ними элементов управле ни я. Но
существует общий способ проверить достоверность всей страницы
сразу. Достаточно в каком- н ибудь обработч и ке п роверить значение
свойства страницы Page.lsValid.

Обработка событий

На этом этапе страница уже полностью загружена и проверена на


достовер н ость . Те п ерь среда ASP.NET запустит все собы тия , которые
П РОИЗОШllи на ЮlИенте со времени последней обратной отсылки .
Различают два вида событий на клиенте :

1. С обытия , требующие немедле нн ого ответа сервера (щелчок на


кнопке Submit, и зме н е ни е состояния элеме н та управле ни я с
уста н овленным свойством Au t oPostBac k, и др.). Эти события
инициируют н емедленную об р атную отсылку.
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

2. Отложенные события изменения состояния - ВЮJючают смену


выбора в элемен те управления или изменение текста в текстово м
поле, но обнаруживаемые ASP.NET только по прибытию
очередной обратной отсылки.

Такая модель событий ASP.NET отлич ается от традиционных локальных


Wiпdоws-прuложенuи. В Wiпdоws-прuложенuи состояни е формы (окна)
ц еликом находится в памяти и способно немедленно отр еа ги ровать на
происшедшее событие . В Web-приложении обработка событии формы
(страницы) прои сходи т только при поступлении обратной отсылки на
сервер. В связи с этим на серве р по ступает сразу несколько
н еобработанны х событий и важно знать, в какой последовательности
они обрабатываются.

Например , п усть у нас есть текстовое поле без автоматической обратной


отсылки и кнопка Submit. Мы изменяем текстовое пол е и щелкаем на
кнопке Submit, тр ебуя от броуэера обратную отсылку. Запрос поступает
на сервер , анализируется средой исполнения ASP.NET, которая
запускает следУЮщие события в таком порядке:

1. Page . Ini t
2. Page . Load
з. Te xt Bo x . Te x tChanged

4. Button . Cl i c k
S. Page . PreRende r
б. Page . Unload

Запоминание этой информации может быть решающим в облегчении


нашей жизни как пр о граммистов ASP.NET. Нельзя подсовывать сырые
за го товки на выходе конвейе р а го товой продукции. ЭТО также важно ,
как помнить о то м, что страниц а существует только на время

формирования очередного ответа ЮJиенту и никаки е переменные


при ложения не сохраняют своих значен и и до следУЮще го поступления
обратной отсылки. В этом состоит отличительная особенность Web-
при ложений.

Автоматическая привязка данных


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Важной особенностью современных при ложений любого т ипа является


использование структурирова нны х дан ны х, которые ор га низованы в

базы да нны х. Web-приложения не являются ИСЮJючением. ASP.NET


имеет элеме нты управления и ЮJассы, ав томатизирую щи е процесс

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


источниками данных ASP.NET автоматич ес ки выполняет соеди н е ни е ,
обновление и запрос ы к источнику д ан ных как часть жизненного цикла
страницы.

Существуют два тип а опера ций с источникал1U данных. Любые


изменения (вставка, у,цале ни е, uзменение записей ЕД) выполняются
после обработки всех событий элементов управления, но
непосредственно п еред ген е р ацией события Page . Pr eRender .
По сле запуска собы ти я Page . PreRende r наступает че ред элемен тов
управления источниками данных , которые выполняют свои за про сы и
вставляют извлеченные данные в связанные с этими да нными элеме н ты
управления. При этом ни один обработчик событий элемен тов
отображения уже не БУдет им еть доступа к новым данным.

ЭТО последняя оста новка в ж изн е нном ЦИ ЮJе страницы. И стори чески
сложилось та к, что событие Page . PreRender обозначает посл еднее
действие п еред пр еобразова ни ем страницы в НТМL.

Очистка

В конце свое го жизненного ЦUluю страница пр еобразуется в НТМL.


По сле этого начина ется реальная о чистка и за п ускается событие
Page . Unload . В этот момент объекты стран ицы все е ще доступны ,
но окончательный НТМL уже сгенери р ова н и не может быть и зме н ен .
За т ем система т е ря ет ссылку на объект страницы и сборщик мусо р а
уничтожает б р о ше нн ую па мять. П ослед ним пр едсмер тным писко м
страницы становится событие Page . Di sposed, ко гда сборщик
мусора доберется до нее. С получением сервером очередного запроса
страницы все начина етс я за ново.

Пример страничного потока событий


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Проиллюстрируем рассмотренную последовательн ост ь собы тий


перехватом их обработчиками с выдачей на страницу соответствующего
текста . Для это го к предьщущему п римеру добавим новую страницу
Теперь будем использовать модель разделен и я де скрипторов и кода С# .

Добавление к сайту новой страницы

• ~ыполните оп ц ию меню оболочЮ1 Website/Add New ltem. .. и ли


такую же опц и ю в контекстном меню узла сайта п а н ели So lution
Exp lorer
• u;.;rЗаполните окно масте р а добавления как показано на снимке .
И мя странице пр и свойте PageFlow . азр х , ВЮlюч и те галочку
Place code in separate fiJe (размещать код в отдельном файле) ,
шабло н страницы выбери те Web Fо пn. Щелкните на кнопке Add
.1J~
Т""'pJ"""
ri! о:::


l/ШIiIIIII
D
м." ,... Р"9"
[!j]
_ с_

Ccn'ro l
00
КТf.1.. ""9"
!i
Web S• ..,~e
~
С",,,
~
stj i< SI"e"t

CiiJ
C~,

"«J 1 ~a~ ",


-
[}
crn~l;JJ a ~I ",
~
)(]vI.F,", хм.
\JjJ
Schotm
~
То" Fil2
~
R OЮ'JC .

.
Fi:"
ij
SQ..Doi'->Ь=

1m
Dазset -~, ~
5Ite М"!)
1J]r"
с

M:N e I'Joo
~
\'В5C r "" F(e
lf.jJ
,-,
~
.J5CfjX " "
Ib"diof ' ..m

~
rв::;"
I д form for Wob ц" ь""",
-"'" ~ ф1 jjJ

~W I p~ "w , ,,,p,

L~: I Vislя l С, iI ~ PliO:8 с сОэ n "'1R ае fii3


Г Selea rrвstef IВ'J"

• ~ы п олните командУ Website/Set As Start Page (сделать страницу


стартовой), чтобы при запуске проекта из оболочки она
вы п ол н ялас ь первой. Такая установка приме н яется только в среде
раэработки и не влияет на п орядок загрузЮ1 страни ц на
п ромышленном сервере.

• ~ оместите на стра ниц у из ВЮlадки Standard панел и Toolbox


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

серверный элемент управления Labe! и Вuttоп. О тцен трируй те и х в


режиме Design командой Fопnatl]ustify/Сепtе r
• r;;:;nереименуйте элемент Label1 в IbUпfo
• ~ ерез п а н ель Dосumепt Оutliпе в режиме Design вы д ели те
объект Ib П nfо и в п ан ели Properties уста н ов и те свойство
Е паЫеViеwStatе в состояние false

Отметьте для себя, что установленные отлич н ыми по умолчан и ю


значен ия свойств элементов yn р авления выделяются в поле значений
панели Properties полужирным стилем шрифга.

• Г;;:;=Очистите зн ачен и е свойства Text элемента Ib Uпfo


• ~Двойным щелчком на странице в режиме Design создайте
заготовку обработчика Page_LoadO и растиражируйте ее
редактором кода еще на три обработчика
• ~Двойным щелчком на кно п ке Buttonl в режиме Design создайте
для нее заготовку обработчика ButtonCClickO
• r;;:FЗаполните обработчики следующим кодом

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using Sуstеm.WеЬ.U I .WеЬСопtrоls.WеЬРаrts;
using System.Web.UI.HtmlControls;

public рапia ! class PageF!ow : System.Web.UI.Page


(
protected void Page_Load(object sепdеr, ЕvепtArgs е)
{
11 Объекты созданы и инициализированы начальными знач еJ
11 и возвращенным состоян ием вида
IbUпfо.Техt += "Ср аботал обработчик собы тия Load <br 1>";

if (Page.lsPostBack)
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

{
IblInfo.Text += "< Ь > Эта страница запрашивается не впеРВЫI
}
}

protected void Page_lnit(object sender, EventArgs е)


{
IblInfo.Text += "Ср аботал обработчик собы тия lnit < Ьг 1>";
}

protected void Page_PreRender(object se nder, EventArgs е)


{
IblInfo.Text += "Ср аботал обработчик собы тия PreRender < Ьг I~
}

protected void Page_ Unload(object sender, EventArgs е)


{
11 Не увидим, НТМL уже сгенерирован
IblInfo.Text += "С работал обработчик собы тия Unload < Ьг 1> ";
}

protected void Buttonl_Click(object sender, EventArgs е)


{
IblInfo.Text += "С работал обработчик собы тия Click кнопки <t
}
}

Листинг. Файл отделенного кода PageFlow.aspx.cs

<%@ Page Language="C#" AutoEventWireup=''true'' CodeFile=''PageFIc

< !DQCТYPE html PUBLIC "-/IWЗС/IDТD ХНТМL 1.0 Tгans[ionaVIEI

<html XmInS= ' huр ://www.wЗ.ог&,1999/xhtml' '>


<head runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nmat="server''>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<div style=''text-align: center">


<asp:Label ID="lb Unfo " runat::::"selVer" Enab leViewState=''False'';::
<br 1>
<asp:Button ID =' 'Вuttопl '' runat="selVer" Техt=''Вuttоп'' OnClick:
</div>
</fonn>
</body>
<lhtml>

Листинг . Разметха страницы PageFlow aspx


• ~3апустите прило жение первый раз. Сервер сге н ерирует
следующий НТМL - ответ

Сработал обработчик события


lnIt
Сработал обработчик события
Load
Сработал обработчик соБЫТИR PreRender

Butlon

ответ серве р а при первом запросе

• ~елкните на кнопке Subrnit (Button), чтобы инициировать


обратн ую отсылку. На эту и все последующие обратные отсылки
сервер бу,цет присылать такой НТМL-ответ

Сработал обработчик события Inlt


Сработал обработчик события Load
Эта страница э:апрашивается не впервые
Сработал обработчик события Cllck кнопки
Сработал обработчик события PreRender

8utton

ответ серве р а на обратн ую отсылку

Обратите внимание на файл подцержки PageFlow.aspx.cs. Он н е полон -


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

в проuэво дном КIlacce ст р аницы н ет объявлений объектов lbl lnf o и


Buttonl элемен тов управлен ия. Такое в языке С# недоп устимо.
Однако страница нормально ком пили руется и усп ешно выполняется.
Дело все в ключевом слове pa rti al (частичный) в объявлении
класса. Это н ововведе ни е в Visua! Studio 2005. Оболочка сама перед
компиляцией файла добавляет необходимые объявле ни я объектов на
ос н ова нии и нформации о дес криптора х, связа нны х с серверными
элемен там и на основной странице .aspx. Э ТО справедливо , п оскольку на
странице со сме шанны м кодом и раньше не было никаких объявлений
(как и н е было классов).

Обработч ики ст р аниц п одключаются явно с и с п ользова ни ем делегатов


в скрытой ча сти кода конструктора КIlacca стра н ицы . П оскольку этот
скрытый код конструктора с ч итается частью класса стра ницы , он
может подключить любой метод . Обработчики событий элементов
управления п одключаются с помощью иного м еха н изма - дескриптора
элемен та управления. Они привязываются на более по зднем этапе
обработки, после объеди нен ия разметки из файла .aspx и класса
скрытого кода. ASP.NET создает этот объедин ен ный класс п орожде ни ем
н ового класса из класса скрытого кода. Чтобы в этом созданном на лету
классе был и доступны наши обработчики , (теперь получается, чт о
разм еще нны е в баэовом Кf/acce), они д олжны и меть модификатор
доступа p r o te cted.

и е ще од но замеча н ие. Есл и бы мы не уста н овили свойство


EnableViewState метки l bl lnfo в значение fa l se , то

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


сохр аняемое в состоянии вида , до п олнялось бы новыми и зме н е ниями
элемен та п ри каждом следующем ответе . Мы с вами говорили, что если
состояние ви да н е выключ е н о (включено п о умол чанию ), то любые
и зменения состояния элемента уп р авления немедленно в н ем

сохр аняются.

Страница как контейнер элементов управления

При вызове Web-формы (страницы) она загружается в п амять сервера и


создается как объект с и ниц и ализац ией сво и х свойств и срабатыва ни ем
событий . Затем форма запрашивает ге н ерацию кода у всех элемен тов
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

управления страницы. Каждый из этих элементов управления в свою


очередь может содержать до черни е элемен ты управления и каждый из
них тож е отвечает за ге нер ацию собственного кода. По мере генерации
этих элементов управления qюрма собирает полученный HTML -кod в
заверше нную страницу

Ка ждый раз, когда страница создается в ответ на НТГР -за про с , система
AS P.NET инспектирует фай л .aspx. Для каждого найденного
дескри птора элемен та управления она создает и настраивает объект
элемента управления, а затем доба вляет этот объект к странице как ее
дочерний элеме н т управления . Сс ы л ки на все дочерние элеме н ты
страницы размещаются в коллекции Раgе.Сопtrоls.

Пример отображения дерева элементов управления

Прив едем пример пои ска и вывода т ип а и имен элементов управления


страницы. Найденную инqюрмацию БУдем размещать п оследовательно
в конец qюрмируемой НТМ L -стра ницы . Чтоб ы перебрать все до ч е рние
элементы управления страницы на необходимую глуби н у, будем
испол ьз овать рекурсивный вызов функции. Элементы управления
сгруппируем как дочерние в серверном элеме н те Рапеl

• Г;;:;-Добавьте к проекту новую страницу с именем

Con t rolTree . asp x с раздельным кодом в фа йле


С о пtго rrree. aspx. cs.
• ~OMeTbTe ее как стартовую
• ~ оместите на страницу элеме н т управления Рапеl из
вкrJaДКИ Standard пан ели Toolbox
• ~ оместите на панель три кнопки But t on , одну метку Label
и текстовое поле Te x t Bo x

• u;.;rp азместите за пр еделам и пан ели , но вн уг ри дескриптора


< f o r m> , внизу еще одну кнопку В и t ton
• ~ведите сверху и снизу за пределами дескриптор а < fo r m>
статический НТМL-текст внугри дескрипторов параграфа <р>
</р>

Код разметки для получен ной страницы долже н выглядеть при мер н о
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

так

<%@ Page L апguagе="С#" АutоЕvепtWirеuр=''truе''


С ode F ile=' 'с о пtго rrree .asp х. cs"
lпhег its="Со пtrоrrгее" %>

<html xm1пs="httр:llwww.wЗ.огgl1999/xhtml">
<head nmat="server">
<title> Дерево элементов ynравления </titlе>
</head>
<body>
<р>

< i>Это статический текст 1 </i></p>


< fопn kl="Controls" method ="post" runat="server">
<div>
<asp:Panel ID="MainPanel" runat="server" Height="121px" Wklth="267
< аsр:Вuttоп ID="Buttonl" runat="server" Text="Buttonl" 1>
< аsр:Вuttоп ID="Button2" runat="server" Text="Button2" 1>
< аsр:Вuttоп ID="ВuttоnЗ" runat="server" Теxt="ВuttоnЗ" 1>

<р 1>
<asp:Labe! ID=''Label1 '' runat="server" Text=''Labe!''>Name:</asp:La
<aspTextBox ID='TextBoxl" runat="server" Wklth="195px''> </asp:l
</asp:Pane!>
< аsр:Вuttоп ID="Button4" runat="server" Text="Button4" 1>

</div>
</foпn>
<р>

< i>Это статический текст 2</i></p>


<!body>
</html>

Листинг Код разметки страницы ControlTree.aspx

Представле ние этого кода р азметки в о кн е броузера и меет такой вид


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Это статич е ский текст 1

Bu1lon3

Name: L -_ _ _ _ _- '

Bu11on4

Это статический т ек ст 2

Пр едс та в л ени е страницы С опtгоrrге е . а s р х в окн е б р оузе ра

• Г;;:;=Установите для кноп ки Вuttоп4 свойство Тооl Tip


(всплыв аю щ а я по дсказка ) в состояние С ка ни роват ь вс е
• IJ$С о здай те об ра бо тчик кноnкн Button4
• ~3аnолни те кодовый файл так

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public рапial class Controrrree : System.Web.UI.Page


(
protected void Page_Load(object sепdег, EventArgs е)
(
// Начало сканирован ия всех нелитеральных элементов ynраI
DisplayControI(Page.Controls, О, false);

// Горизонтальная линия по окончании вывода


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Response.Write("<hr 1>');
}

protected void Button4_Click(object sепdег, ЕvепtAгgs е)


(
11 Начало сканирования всех литеральных элементов управш
DisрlaуСопtrоI(Раgе.Сопtrоls, О, true);

11 Горизонтальная линия по окончании вывода


Response.Write("<hr 1>');
}

private void DisрlaуСопtrоl(СопtrоlСоllесtiоп сопtrоls, int depth, Ьооl


{
foreach (Сопtrоl сопtrоl in controls)
{
11 Выявлять литеральные (статические) элементы управлеt
boolliteralControl:::: control is LitегаlСопtrо~

11 Отобразить элемент управления


if (litегаlсопtrоl == literalFlag)
(
11 Использовать параметр depth для определения
11 отступов в выводе дерева элементов управления
Rеsроnsе.Wгitе(пеw String('-', depth * 4) + "-->');

String literarrext = "";


if (litегаlсопtrоl)
literarrext = ''text'' + «LitегаIСопtгоl)сопtгоl).Техt;

Response.Write(controlGetTypeO.ToStringO + "- < Ь>"


+ сопtrоlID + literarrext + "<!Ь><Ьг 1>');
}

11 Проверять до черние элементы управления рекурсивно


if (controLControls != null)
(
DisрlaуСопtrоl(сопtгоlСопtгоls, depth + 1, literalFlag);
}

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

}
}
}

Листинг. Код файла ControlTree.aspx.cs


• ~3апустите стра ницу. П осле щелчка на кнопке Button4 должен
получиться примерно такой НТМ L· выход

-- > 5 ystem. Web.UI. НtmlCо пtrоls .нtmlН е а d -


------ >5 ystem. Web. UI.HtmlCo ntrols. Htmmtle -
-- > 5ystе m. Wе Ь .UI.НtmlCо пtrоls .нtmlF о гm - Controls
------ > 5уs tеm.WеЬ.U I .Wе Ь Со пtrоls.Раne l - М а inР а пеl
---------- >5ystem Web.UI. WebCo ntrols.Button - Buttonl
--------- -> 5ystem Web.UI. WebCo ntrols.Button - Button2
--------- ->5ystem Web.UI. WebCo ntrols.Button - Button3
---------- >5ystem Web.UI. WebCo ntrols. Label - Labell
--------- ->5ystem Web.UI. WebCo ntrols.TextBox - TextВoxl
------ > 5уs tеm.WеЬ.U I .Wе Ь Со пtrоls.Вuttоп - Butto n4
-- > 5ystе m. Wе Ь .UI. LitегаlCо пtrо l - text
-- > 5ystе m. Wе Ь .UI. LitегаlСо пtrо l - text

ЭТО стат и ческий текст 1

------ > 5уs tеm.WеЬ.U I . Litе гаlСо пtго l - text

--------- ->5ystem Web.UI. Litera}Control - text


---------- >5ystem Web.UI.Litera}Control - text
--------- ->5ystem Web.UI. Litera}Control - text
---------- >5ystem Web.UI. Litera}Control - text

---------- >5ystem Web.UI. Litera}Control - text


---------- >5ystem Web.UI.Litera}Control - text
------ > 5уs tеm.WеЬ.U I . Litе га lСо пtго l - text
------ > 5уs tеm.WеЬ.U I . Litе гаlСо пtго l - text
-- > 5ystе m. Wе Ь .UI. LitегаlCо пtrо l - text

ЭТО стат и ческий текст 2

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Это стат и ческ и й текст 1

ВuttопЗ

Name: LI_ _ _ _ _ _ __

Bu11on4

Это статический текст 2

Объекты LiteralControl , которые мы определяли в нашем коде и


отдельно р аспечатывали по кнопке Button4, предоставляют нем н огое в
отноше ни и функц и ональн ости . Например , мы не можем п рограмм н о
устанавливать инф:J р мацию, связанную со стилями, наподобие цвета
и ли шрифга. У них также нет ун и кальных серверных и дентификаторов .
Одн ако мы можем манипулировать содержимым Li teralCont r o l с
и спользован ием е го свойства Te xt, что и продемонстрировано в
п оследнем п римере.

Здесь при рекурсивном обходе дерева элементов ynравления мы


учитывали тот факт, что ASP.NET генерирует страницу ие р архичесЮ1 .
Она генерирует непосредственно тольЮJ верхний уровень элемен тов
ynравления , т.е. только свойство · контейнер ( коллекцию элемен тов
ynравления ) Controls самой страни ц ы. Если какоЙ·то элемен т
ynравления содержи т дочерние элемен ты , т. е . сам является

кон тейнером , то он имеет свое собственное свойство - контейнер


Controls.

Обратите в н имание, что задав свойство Тоо1 Т i p коно п ки Вuttоп4, мы


организовал и дл я пользователя п оявление всплыв ающей подсказки п ри
н аведении курсора мыши на кнопку Фактически серверный элемен т
But ton 4 с генерировал в своем НТМ L -выводе атрибyr
titlе= " Сканирова ть все ".

Прог раммное управление заголовком страницы

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Ранее мы говорили, Ч ТО чтобы сделать дескри п тор НТМL элемен том


управления, н еобходимо добав и ть в него атрибуг runa t = " serve r" .
Но в ска ни рованном выводе последнего п р и мера система ASP.NET
н аlШlа элемен т управлен ия заголовком стра ниц ы

System Web .ш.н tmlСопtrоkНtmlНеаd

VlSual Studio 2005 автоматически считает дескри п тор < h еа d>


серверным элементом. Значит мы можем управлять им про гр амм н о .

Объект HtmlHead наследует предо п ределенный интер~йс


IPageHeader и содержи т следУЮщие свойства:

• тi tl е - назва н ие НТМL-стран и цы , которое отображается в


заголовке броузера
• Lin kedSty l eSheets - коллекция объектов для настройки
стилей все го докумен та через вне lШl ЮЮ таблицу стилей
• StyleSheet - настройка встраиваемых стилей
• Metada ta - коллекция объектов для н астройки дескрипторов
метаданных

Пример:

Page.Header.1it1e := "Это программно задан ный заголовок";


Page.Header.Metadata.Add('Keywords", ' 'Рыжик, Пыжик, ГдеТыБыл ");
Page.Header.Metadate.Add(Descriptlon", ' 'Русские народные мелодии'');

Элеме н т управления HtmlНead п олезен на сверхдинам и ческих


стра н и ц ах, когда может возникнуг ь потребност ь в изменении Юlюч евых
слов и н азван и я НТМ L -стран ицы в зависимости от содержимого
запроса п ользователя.

Пример создания элемента управления во время


в ып олн е ния

с ис п ользованием коллекции Con t rols можно на лету создать и


добави ть к НТМL-выводу любой элемент управле н ия. Приведем
п ример , динам и чески создающий кн о п ку в HTM L -ВbIвоАе. Пусть у нас
и меется код

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• IJ$Добавьте к nр оекту nредыдщегоo при мер а новую страницу с


разделенным кодом и именем Dynam i cBu t ton . Сделай те
страницу стартовой.
• ~ оместите на ст р ани ц у из ВЮJaДКИ Standard элемен т
yn р авления Рапеl , метку Label , три кнопки Button , а из

ВЮJaДКИ НТМL - элемен т Hor i z on tal Rule

Настройте ин терфейс стра ницы време ни nр о е ктирования так

Dуn.зmicВutton.3SPХ.СS DvnamicButton,aspx*

ООелкните на динамически созданной кнопке

• Reset Text

Create Butlon Remove Butlon

• ~3аnолните обработчик за гр узки стра ницы следующим кодом

риы ic ра пial class DynamicButton: System.Web.UI .Page


(
protected void Page_Load(object sепdеr, ЕvепtArgs е)
(
// С о здать н ов ы й объект кн опки
Button пеwВ uttо п = пеw ВuttопО;

// При сво ить знач е ни я свойств


пеw В uttоп.lD = ''nеwВuttоп'';// П омет и л и
пеw В uttоп.Техt = "* ОynaпUc Button >!о";

// Добави ть кнопку в колле кци ю элеме н тов ynр а вле ни я фор м


fo rml .С о ntro Is.Add(newButto п) ;
}
}

. Начальный ход динамичесхого


Листинг создания хнопхи

• ~3аnусти те страницу на выполнени е . Получится такой

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

результат

Щепкните на динамически созданной кнопке

Resel Тю:l .

Сгезlе Bullon LRemove Bullon


± Dynamic Bulton ±

НТМL · вывод стра ниц ы ди на мического создания кно пки

Мы п олучили то, что дин амически созданн ая кнопка оказалась в конце


декскр иптора <fo r m> . Для получения большего контроля над
расположен и ем динамического элемента управления можно

использовать элеме н т управл е ния PlaceHolder. Целью элемен та


управления Р 1 асеНоl der (держатель места) является р азмещение
д ругих элементов управления. Если ра змест ить элемен т

PlaceHolder на форме и не добави ть в его коллекц и ю Cont r ols


Д Р)'П1х элементов, он ничего не и зме нит на окончательном HTML-
выводе .

• Г;;:;nоместите элем ент управления Р 1 асеНоl de r впереди


кнопки с названием 'Reset Text" и перепишите код так, чтобы
дин амически создаваемая кно пка добавлял ась н е в коллекцию
формы , а в коллекцию PlaceHolder

// Добави ть кнопку в коллекцию PlaceHolder1


р \асе Н о Id е г 1. С о пtго ls.Add (пеw Butto п);

Те п е рь НТМL·вывод должен бы ть таким

Щепкните на динамически создан н ой кнопке

"Dynamic Bulton" Reset Тех!

Creale Bulton Remove Bulton


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

НТМL-вывод страницы динамического создания кнопЮ1

При использовании динамических элементов управления следует


помнить, они создаются только при срабатывании обработчика , где
размещен их код. Чтобы элемент динамически создавался при каждой
загрузке ст р аницы, его код следует разместить в обработчике
Page Load () или Page I n l t ()

Невзирая на способ создания элемента управления, его информация о


состоянии вида автоматически посылается на сохранение клиен ту

Может получиться такая ситуация, что в текущей ст р анице мы создали


динам и ческий элемент управления и информация о состоянии вида
yumа юшенту Но при следующей обратной отсылке мы не стали
создавать этот элемент и информация о состоянии вида осталась
невостребованноЙ. Ну и ладно, ничего страшного.

Если мы собираемся взаимодействовать с динамически созданным


элемен то м управления дальше, то ему следУет присвои ть уникальный
идентификатор, что мы и сделали в нашем прим ере . Мы можем
использовать этот идентификатор для извлечения элемента управления
из коллекции Con t rols родительского контейнера. Можно найти

элемен т управления с использова ние м рекурсивной лотки поиска , как


мы это делали в стран иц е
Controrfree.aspx. Можно для поиска элемента
использовать статический метод Page . FindCont r o l () .

Для при мера добавим функциональность к кнопке с названием Rепюvе


Вuttоп, которая бу,цет у,цалять динамичесЮ1 созданную кнопку Если с
обратной отсылкой прид ет событие (сообщение), что пользователь
щелкнул на кнопке Rепюvе Button, то мы должны БУдем найти
динам и чески созданную ранее в обработчике Page Load () кнопку и
удалит ь ее из страницы. И в уже готовящемся н а шей страницей HTML-
выводе этой кнопки н е БУдет.

• ~Двойным щелчком на кнопке с названием Rепюvе Button


создайте для нее обработчик, который заполни те так

protected void ВuttопЗ_С liсk(оЬjе сt sender, ЕvепtAгgs е)


{
// П о иск кнопки вне зависим ости от иерархич е ского

,ОС
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

// уровня, в котором она расположена

Вuttоп fо uпdВuttо п = (Вuttоп)Раgе.FiпdСопtrоЧ"newВuttоп'');

// Удале ни е кнопки с п р о веркой услов ия , чтобы


// не пытались Удалить уже удале нный объект
if (fouпdВuttоп != null)
(
// Удаляем из коллекции родительского элеме н та управления
fouпd В utto п. Р агепt. С о пtrо ls. Remove( fo uпd Button);
}
}

Листинг Обработчик события кнопки Remove Button в


файле DynamicButton.aspx.cs

Следует заметить, что по след ний оператор п риведенного кода


Remove () не Удал яет объект кнопки физически, а удаляет только
ссылку на кнопку из коллекции Р 1 асеНоl de r . ЭТО значит, что кнопка ,
однажды созда нн ая в обработчике Page Load () , продолжает
существовать в контейнере Page стра ницы и мы всегда можем ее
использовать дал ьше.

Динамически добавле нные элеме н ты управления могуг обрабатывать


события. Нужно лишь п одключить обработчик события с
использован ием кода-делегата . Подключать события обязательно
нужно в обработчике Page_LoadO, иначе БУдет поздно , по скол ьку все
поступившие с обратной отсылкой события клиента ген ерируются сразу
после события Page . Load. Если код п одключения события с помощью
делегата разместить в другом месте, обработчик события не сработает,
поскольку система это событие уже с генерирует и, не найдя
соответствующий обработчик, оставит без внимания .

• г;;.:;='Добавьте в кон ец обработчика Page Load () следующий код

protected void Page_Load(object sепdег, ЕvепtAгgs е)


{
// Создать новый объект кнопки
Вuttоп пеwВuttоп = new ВuttопО;

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

// Присвоить значения свойств


пеwВuttоп .I D = ''nеwВuttоп'';

пеwВuttоп . Техt:::: "* Dynamic Button >!о";

// Добавить кнопку в коллекцию PlaceHok:ler1


Р \асе Ho!d ег 1.С о пtго Is.Add ( new Button);

// Подключение обработч ика собblТИЯ Button.Click


// ди намически созданно го элемента уп р авления
пеwВuttоп . Сlick += new EventHand!er(newButton_ Click);
}

void newButton_Clk:k(object sender, EventArgs е)


{
Labe!l .Text:::: "Э тот текст прислал обработчик" +
"дин амически созданной кнопки";
}

Листинг ПОДJCлючение обрабОТЧИJCа события динамичесJCИ


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

• г;;;?Сбросьте для метки Labell свойство сохранения состояния


ви да , назначив EnableViewState=fa l se

ОкончатеЛЬНblЙ вариан т страН ИЦbl д олж е н бblТЬ таки м

<%@ Page Lапguagе= "С#" АutоЕvепtWirеuр=''truе''


CodeFile="DynamicButton.aspx.cs" Inherits= ''DynamicButton'' %>

<html xmlns=''http://WWW.W3.0rgl1999/xhtml'' >


<head nmat="server">
< title >Uпtitled Page</tide>
</head >
<body>
< fопn id="fo rm1 " ruпаt="sеrvег' '>
<div>
<asp:Labe! ID="Label1" ruпаt="sеrvег" Теxt='Щелкните на динамичео
Width="431 рх" ЕпаЬ !е ViewS tate=''F alse"> </asp:Labe!> < Ьг />
<br />
<asp:P \aceHo!der ID::::"Place Ho!der1 " ruпаt:::: "server''></asp:P IaceHo!der>

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

&пЬsр;
< аsр:Вuttоп ID::::''Вuttоп1 '' ruпаt::::"sеrvег" Text::::''Reset Text" I>< br 1>
<ш 1>
< аsр:Вuttоп ID::::''Вuttоп2 '' ruпаt::::"sеrvег" Text::::"Create Вuttоп" 1>
&пЬsр;&пЬsр;
< аsр:Вuttоп ID::::''ВuttопЗ '' ruпаt::::"sеrvег" Теxt::::''Rепюvе Вuttоп" ОпСliсk=
</div>
</form>
<!body>
<lhtml>

Листинг
DупаmiсВuttоп.аsрх
Дескрипторная часть страницы
• файле

usiпg System;
usiпg System.Data;
usiпg Systеm. Со пfigша tiоп;
usiпg System.Collections;
usiпg System. Web;
usiпg System. Web.Security;
usiпg System.Web.UI;
usiпg System. WеЬ.UI.WеЬСопtгоls;
usiпg System. Web. UI. WеЬСопtгоls. WebParts;
usiпg System. WеЬ.UI.НtmlСопtrоls;

public partial class DynаmicВuttоп: System.Web.uI.Page


(
protected void Page_Load(object sепdег, EventArgs е)
(
11 Создать новый объект кнопки
Вuttоп пеwВuttо п :::: пеw ВuttопО;

11 Присвоить знач ения свойств


пеwВuttоп.ID :::: "пеwВ uttоп";

пеwВuttоп.Техt = ''* Dynamic Вuttоп *";

11 Добавить кнопку в коллекцию PlaceHolder1


Р !асе Н о k:ler 1. С о пtrо 1<;. Add( пеw Butto п) ;

11 ПОДЮIючение обработчика события Вuttоп.Сliсk

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

11 динами чески созда нного элемен та управления


пеwВuttоп. С liсk += new EventНandler(newButton_Clk:k);
}

уою пеwВuttоп_ С liсk(оЬjесt se nd er, EventArgs е)


(
Labell.Text = 'Э т от текст прислал обработчик" +
" динамически созданной кнопки ";
)

protected уою ВuttопЗ_С lk:k(о Ьjесt sender, EventArgs е)


(
11 Поиск кнопки вне завис и мости от иерархического
11 уровня , в котором она расположена
Button fОШldВuttоп = (B utton)Page.FindCo ntro ~ ' 'ne wButton' ) ;

11 Удале ни е кнопки с проверкой услов ия , чтобы


11 не пытал ись Удал и ть уже удале нный объект
if(foundButton != null)
(
11 Удаляем из коллекции родител ьского элемента управления
fo undButto п. Р arent. С о ntro Is. Remove( fo undButto п) ;
}
}
}

Листинг Кодовая часть страницы в файле

DynamicButton.aspx.cs

• ~Запустите и испытайте закодированную страницу

DynamicButton.aspx

в окне броузера мы ви дим, что при каждом вызове страницы


д инамическая кнопка создается на сервере и посылается ЮJИенту. При
нажатии кнопки Rепюvе Button послан ное на сервер событие вызывает
срабатывание обработчика удаления кнопки и з коллекции. Посылка
дан ны х на сервер при нажатии других незапрограммирова нн ых кнопок

опять создает динамическую кнопку и добавляет ее в контейнер .


Щел чок на ди н амической кнопке запускает обработчик смены текста в
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

метке Labe1 1 . Щел чок на любой другой кнопке восстанавливает


первоначальное содержимое метки Labe 1 1 , поскольку мы сняли

свойство сохранения состояния вида.

Создание динамического элемента управления дополняет


пользовательские элементы управления , явно размещаемые на ф:Jрме на
этапе проектирования (подцерживаемые дескрипторами). В некоторых
случаях это может быть мощным дополнением или единственным
средством при создании сложных страниц.

Класс Page

Класс Sys t em . Web . UI . Page является базовым для классов


создаваемых ст р ани ц . В локальных приложениях такую роль играет
масс Form . Это значит, что динамические страницы наследуют
множество полезных свойств и методов класса Page . Класс Page
служит контейнером имен всех элементов управления, входящих в
состав страницы. ASP.NET создает новое виртуальное пространство
имен , гара н тирующее всем дочерним элементам управления

уникальность имен в пределах всего дерева элементов управления.

Свойства класса Page можно разделить на три группы:

1. Внугренние объекты
2. Рабочие свойства
з. Специфические страничные свойства

На данном этапе мы коснемся только первой группы свойств.

Когда ASP.NET загружает страницу в память серве р а, она создает


объект, порож.ценныЙ от класса Page . Одновременно создаются
объекты первой группы и их имена становятся свойствами страницы­
объекта. В эти объекты записывается инф:Jр мация, важная для
управления всей страницей. Перечислим свойства-объекты страницы.

Внугренние объекты ASP.NET в составе класса PagE


Свойство­
Порож.цающиЙ класс
объект

'"
В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

ApplicationSys t em . Web . HttpApplicationSta t e

СасЬе Sys t em . Web . Caching . Cache

Request Sys t em . Web . HttpRequest

Response Sys t em . Web . HttpResponse

Serve r Sys t em . Web . HttpServerUtil i ty

Sess i on Sys t em . Web . Sess i onS t ate . HttpSessionSta

Ттасе Sys t em . Web . TraceCon t e x t

Use r Sys t em . Secu r ity . Principal . IPrincipal

Объекты Session, Application, Cache

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Объект Sessi оп предна з н ач ен для хранения любого тип а


пользовательских данных, ю:порый должен постоянно существовать
между за пр осами Web-страниц. Он предоставляет словарный достyn к
набор у пар имя=значение, содержащему пользовательские данные
текущего сеанса. Состояние сеанса часто применяется для
обслуживания информации наподобие имени и идентификатора
пользователя , покynат ельской тележки либо ДРYJl1х элементов ,
удаляемых, когда пользователь покинул страницы Web-саЙ та.

Объект Application содержит словарь данных имя=значение ,


гл обальных для всего при ложен ия.

Объект Cache также хранит глобальную информацию, но


предоставляет более динамичный механизм хр анения, по скольку
ASP.NET может удалять в н ем часть информации при нехватке памяти
сервера. ЭТО тоже коллекция объектов имя=значение , однако здесь для
каждого элемента можно также уста нав ливать специализированные

политики истечения срока и определять зависимости.

Объект Request

Этот объект представляет значения и свойства НТГР -за проса ,


вызвавшего загрузку страницы. Он содержит все п араметры URL и
другую инфор мацию , отправляемую клиен том. Мы можем использовать
объект Reques t, чтобы обнаружить, какой броуэер используется
клиентом, или устанавливать и анализировать cook ie -наборы (куки
). Ниже приведены наи более р ас про странен ны е свойства масса
System . Web . НttрRеquеst ,порождающегообъект Rеquеst

Свойства масса Sys tem.~

Свойство Порождак

ApplicationPath string

Physica l Path string

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

AnonymousID string

Browser Sys t em . Web . HttpBrowserCap

Cl i entCert i ficate Sys t em . Web . HttpClientCert

Cookies Sys t em . Web . HttpCookieColl

Fi l ePa t h string

Curren t ExecutionFilePathstring

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Form Sys t em . Collections . Specia

Headers Sys t em . Collections . Specia

ServerVariables Sys t em . Collections . Specia

IsAuthenticated bool

IsSecureConnec ti on bool

IsLocal bool
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

QueryS t ring Sys t em . Collections . Specia

Ur l Sys t em . Uri

Ur lR eferrer Sys t em . Uri

UserAgent string

UserHostAddress string

UserHostNa me string

UserLanguages string

Объект Response

Этот объ ект содержит июlюрмацию и методы qюрмирования ответа


Web - сервера на за пр ос ЮlИента. В таблиц е перечисл ены основные

'"
В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

свойства и методы объекта Response .

Основные свойства и методы объекта Respons(


Член Тип

Buffe r Outpu t boo l

СасЬе System . Web . Ht tpCachePolicy

Cook i es System . Web . Ht tpCookieCollec t ion

Ex pires i nt

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

IsClientConnec t ed boo l

Write(char) ;

Write(char [ ] ,
int , int) i

Write(objec t )

Write(string)

BinaryWrite(byte[
] )
В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

Wri teFi l e( I ntP t r ,


long , long) ;

Wri teFi l e(s t ring)

Wri teFi l e(s t ring ,


bool) ;

Wri teFi l e(s t ring ,


long , long)

Redirect(string) ;

Redirect(string ,
bool)
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Прим е р :

// Перенаправляем н а файл в текущем каталоге


Res ponse .Redkect(''newpage .asp х");

// Перенаправляем н а другой Web-сайт


Res ponse .Redkect(..http://www.dia)og-service .net•.) ;

Объект Server

Основные свойства и методы о бъекта Server


Член тип О пю

Представляет
ком п ьютера , f

за п ускается ст

MachineName str i ng и мя Web-серв


и с п ользуемое

с ц елью его и /

для остальной

Создает эюем
объекта , о п ре/
п ро гр амм н ым
CreateObject(string) i
и дентификато
CreateObject(System .T ype) Ис п ользуется
совмест ИМОСl

yn рощает взау

СОМ-объекта

И звлекает объ
п ослед н е го не

н улевую ССЫЛI

И СЮJюче ни я н
В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

ИСЮJюч е ния н
GetLas t E r ro r ()
Используется
событий при л
пров еряющеп

ситуации.

Осуществляет
кодирование (
допустимыми
Htm lEncode(st r ing) ;
которые н е БYi
Htm lEncode(st r ing , воспринимап

System .I O . Te x tWrite r ) ynравляющие

&g t ; & &аг

ж ес т к и й Пf
&пЬзр )

Htm lDecode(st r ing) ; Осуществляет


операцию по
Htm lDecode(st r ing ,
НТМL-кодиро
System .I O . Te x tWrite r )
строке симво.

Заме няет обы '


Ur l Encode(s t ring) ; строкой допус
символов UЮ
Ur l Encode(s t ring ,
проб елы и др:
System .I O . Te x tWrite r )
спец символы ,

кириллицу, %,
Url Decode(s t ring) ;
Раскодирует с
Ur l Decode(s t ring ,
символов uю
System .I O . Te x tWrite r )

Выполняет те

что и UrlEnc
работает с ба~
Ur l TokenEncode(byte[ ])
массивом, кот

сод ержит дaНl

Base64
Выполняет те
В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

работает с ба~
Ur l TokenDecode(s t ring)
массивом, кот

содержит дaНl

Base64
Возвращает фJ
файл , соответ,

MapPath(string) определенноrv

виртуальному

на Web-сервеI

Передает ист
другой Web-cl
текущем прил

метод по хож f
Transfer(string) ;
Response . 1
Transfer(string , boo l ) ; но работает бl
н ельзя примеl

Transfer(System . Web . I HttpHandle r, п еремеще ни я

bool) на сайт, распо


другом Web-сЕ
на страниц)'; с

ASP.NET (нап
или ASP)

При использовании метода


Se r ver . Transfer () не прои сходит
полного ЦИЮJa. Вместо этого механизм ASP.NET пр осто загружает
новую стра ниц у и начинает ее обработку. В результате URL,
отображаемый в броузере клиента, не меняется ( ... хотели кока , а съели
Кука).

Например:

// Мож н о п еремест ить ся н а фа йл в те кущем We b -п р иложе нии


5 erver.Тг ansfer(''newpage .aspx');

// П е р еме щат ь ся н а другой Web-сайт н ельзя .


// Э ТО вы зовет о ши бку! ! !
5 erver.Тг ansfer(''http :J/www.prosetech.com');

ш
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

5 erver. Тг ansfer(' 'http://www.prosetech.com'');

Метод Se r ve r . MapPath ( ) является еще одни м поле зным методом.


Пусть, например , мы собираемся загрузить файл под названием info.txt
из текущего виртуального катало га . Вместо жесткого кодирования пуги
можно использовать Reques t . Appl i cat i onPath () , чтобы
получить текущий относительный виртуальный каталог. Затем
применить метод Se r ver . MapPa t h ( ) - для преобразования его в
абсолютный физический пугь.

Например:

string physicaIPath = Server.Ma pPath(Request.ApplicationPath


+ "/info.txt");

// Открытие файла
StreamReader reader = new StreamReader(physicaIPath);
// Что -то делаем
reader.CloseO;

Объект User

Объект Use r содержит инф:Jрмацию о пользователе , запрашивающем


Web-сервер, и по зволяет про верить принадлежность этого пользователя
к роли. Он полезен только тогда , когда при ложение выполняет какую­
л ибо ауген тифи кацию , ограничивающую доступ анонимных
пользователей. ЭТО отно с ится к вопросам безо па сности.
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Серверные элементы управления

Серверные НТМL-дескрипторы. Программная устан овка свойств


серверных НТМ L -дескри пторов. Программное создание серверных
НТМL-дескрипторов. События серверных НТМL- элемен тов. Обработка
событий ServerClick и ServerChange. Web-элементы управления. Базовый
масс WebControL Программное управление свойствами Web-элементов
управления. Обработка соб ы тия Changed. Списковые Web-элементы
управления. Элемен ты пр оверки достоверности (валидаторы). Элемен т
RequiredFieldValidator. Элеме н т CompareValidator. Элемент RапgеVаlidаtог.

Файлы к лекц ии Вы можете скачать здесь скачать:

http://Oи. intШ . ruld epartment/intemet/p rasp пеt/4/О4 _ We bS ite з. zip

Серверные элементы управления п озволяют реализовывать миен тский


ин терфейс управления страницей. Большинство из них в режиме
про ектирова ния отображается на НТМL- дескри пторы , но в режиме
выполнения они представляют экзем п ляры массов, допускающих

прогр амм но е управление. Некоторые элемен ты управления MOryr


генерировать сложный HTML-Kod и дополнять е го кодом сценариев
Java Script, по зволяющим ор гани зовать требуемую функциональность на
стороне миен та. Такие элементы управления на зывают

пол нофункциональными .

Чтобы элемент управления был серверным, он должен иметь в


дескрипторе НТМL-представления атрибуг runa t= " server ". Только
при это м условии среда исполнения ASP.NET при загрузке страницы
создаст для него объект (экземпляр соответствующего масса) и
по зволит пр ограммно управлять этим объектом. В про тивно м случае
НТМL-дескриптор будет отправлен миен ту без соответствующей
обработки.

Дескрипторы серверных элементов и представляющие их массы в


среде ASP.NET находятся в однозначном соответствии. По это му на
этапе nраектираванuя мы можем и зме н ять свойства элемен тов
управления как через дескри п торное представление, так и через

свойства представляющих их массов. Естественно , что программное


управление элементами (на этапе выполнения) возможно только через
код пр едставляющих их массов.

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Совреме нн ые серверные элементы управления с вкладки Standard


п анели инст р ументов Toolbox в своем НТМL- представлении обязаны
соде р жать атрибyr runat= " server ", в то время как в случае
п риме н е ни я элементов управления с вкладки НТМL разработчик волен
сам р аспоряжаться свойством их серверности. Назначение элемен та
НТМL сервер н ым можно выполнить П РЯМОЙ вставкой атрибyrа
run а t = " зе rve r " в дескри п тор элемента или через контекстное

меню для это го элеме н та выполнением кома н ды Run As Server Со пио!

011 Cut

I~ сору

~ Paste
Р aste Alternate
'х Delete

Style ...
Rlfl As Server ContIoI
I I
V~w code
V~w Component Dбignег

i!l View in Бrоwsеr


-

Edit Image

Show Smзгt Tag

liJ Re~esh

i;;\ Properties

Группы элеме н тов управле ни я по и х назначе ни ю распределены в VlSua!


Studio 2005 по вкладкам , п е речислим ос н ов н ые и з ни х:

1. Standard серверные элементы упр авления с развитой


функциональностью и программным управлением. Среди них
имеются полнофункциональные элемен ты управления ,
вы п ол н яющие гене р ацию сложно го HTML -кod a и клиентских
сценариев JavaS cr~t для создания и н терфейса на клиен те. ЭТО
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

такие элементы как Calendar, AdRotator, TreeView. И х н азывают


серверными Web-элемента ми yn р авления. Он и с п особны
генерировать н есколько НТМL -дескрипторов. Они даже с п особны
сами за пр ашивать и о пр еделят ь ти п броуэера кrlИе нта и
ав томати ч ески п одст р аивать под эти возможности свой
рен де ринг (НТМL -в ывод)
2. НТМL - типовые НТМL- элементы (представляются тип овыми

НТМL -д ескрип торами), но с преобразованием их в серверные


до пускают программное ynравление и самостоятельн ую

генера цию клиен тской НТМ L - разметки. Их называют серверными


НТМL - элемен тами ynравле ни я. Они с п особ ны генерировать
только один НТМL-дескриптор и оставле ны для совместим ости с
р анней техноло гией AS P
з. Validation - элементы ynравле ни я проверкой достовер н ости . Э тот
набор элемен тов ynравле ния п озволяет быстро провери ть
достоверность связа нн о го элемента ynравления ввода на предмет

соблюде ния нескольких ста н дартных ил и пользовательских


пр авил. Н апример, мы можем указать , что ввод не может бы ть
п устым, что это ДОЛЖНО бы ть ч и сло, что оно д олжно находиться в
определенны х пр еделах, и т.д. В случае нарушения таких условий
можно отме ни ть пр инятие данных, отобрази ть сообще ни е дл я
пользователя, напр авить на другую страницу для ликвидации

безграмотн ости или п окояния, н аконец , - по слать куда- ни будь.


4. Data - элемен ты управления данными. Они позволяют ynравлять
источниками данных с при вязкой декла р ати вно, через свойства ,
без напи са ния дополнительного кода. И меются , также , элементы
отображ е ни я больших объемов данных в требуемом формате , с
подце р жкой до полнительн ы х настро ек наподобие возмож н ости
редактирования , сортировки, разби е ни я на стран ицы .
S. Navigation - элеме нты ynравления н авигаци ей. Они позволяют
п ользователю п е р емещаться с одной стра ницы на другую ,
отображают карту сайта и др.
б. Login - элементы ynравления входом в си стему. Э ти элементы
yn р авления п одцерживают аутентификацию пользователя с
помощью форм с хране ни ем хэширова нны х (закодированных)
сведений в базе да нны х и отслежива ни ем их состоя ни я. Вместо
написания своих собстве нны х и нт е р фейсов для р аботы с
аугентификацией можно испол ь зовать готовые решения с
настройкой стра ниц входа в систему, восстановления паролей и
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

мастеров создания новых пользователей.


7. WebParts - элементы управления для построения компо н е нтны х,
легко конфигурируемых Web-порталов (больших саЙтов).
8. Mobile Web Forms - элементы управления для подцержки
моб ильны х клиентов. Эту вкладку (как и много других) МОЖНО
получить, если вызвать на пан ели Too lbox контекстное меню и
выполнить команду Show AIL Мобильные элементы управления
обладают высокой степенью адаптации. При создании страницы
с использованием этих элементов страница может генерировать

НТМL - разметку в зависимости от типа запросившего ее


устройства . ЭТО может быть стандарт НТМL 3.2, WML 1.1, XHTML
или НТМL 4.01 , включая код JavaScript - в зав иси мости от
возможностей броузера мобильного юшента.

Серверные НТМL-дескрипторы

Ранее мы говорили , ЧТО любому дескр ип тору НТМL можно присвоить


атри буг r unat= " server ". И система про ектирования при
разработке стран ицы , и среда исполнения - после компиляции, сразу
поставят ему в соответствие свой подцерживающий масс из
библиотеки .NET Framework 2.0. А это значит, что таким элемен том
можно БУдет программно управлять. Нам, как прогр амм ис там ,
страждущим управлять элементами управления, важно знать свойства и
методы подцерживающих их библ иотечных классов, с использованием
которых и возможно программное управление.

Класс, пораждающий объект элемента управления , является конечным


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

Все серверные элементы управления имеют в качестве одного и з своих


предков масс Sys t em . Web . UI . Cont r ol . Этот факт можно
использовать для манипулирова ния элементом управления на странице

даже в случае, если е го конкретный тип неизвестен. Следующий в


цепочке наследования серверных НТМL-элементов является класс

m
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

System . Web . UI . Ht mlCont r ols . Ht mlCont r ol . Ни ж е на

ри сунке п р и в еде но дер е во на сл е дования с е рверны х НТМL·элем ен тов

By s"tвm Obj ffi

r ------ - -- ------- \
Пространство имен System.Web.UI.HtmIControls
I I
rttmlCQntrQI
f--- I
I
I Htmll npuК: Q n trQ I
I I rtt mICQnt..inerCfJ ntгQ I
I --1 ~m l l mage II

Н ~ ГГ1 ~ прutВutroп
I Н НVnlAnc t"юг
I --1 HVnllink
II
н HtmllnputSubmit
I Н HtmlButton
I --1 Н tmI Ме1З
I I
н HtmllnputRaset
I Н НtmI FQПТ1
I --1 H tmrТi ll e
I i I
Н ~m llnputC~сkБQХ I Н H(mlSe-lect
I
Н Нtm llп put FПе
I Н Htmrтable
I

Н Htm ~n ~ idde n
I Н Нtmrfa bIeCel1
I
Н Himllnputlmage
I Н Htm rтabkoR ow
I

Н HiJТIll nputR adiQButtQn I Н нtm ГfextP.re <!


I I

Html l npufТext
I Ч Html(ienericContro l нtm lHe<! d II
I
I нt m n n putPa ssword I I
)
" --------
Пока за нны е на р и сунке массы
-----------
и м еют следую ще е соо тветст в и е с

дескрип торным пр едст авл е ни е м

'"
В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

Серверные эл ементы упра вл ения НТМL и и х массы

Сер верный дескр иптор НТМL Подцержива ющий м асс

<а r unat= " server " > Ht mlAncho r


<button r unat= " server " > Ht mlButton
<fo r m runat= " serve r " > Ht mlFo r m
<img r unat= " server " > Ht mll mage
<input type= " button "
Ht mllnputButton
r unat= " server " >
<input type= " reset "
Ht mllnputReset
r unat= " server " >
<input type= " subm i t "
Ht mllnputSubm it
r unat= " server " >
<input type= " chec k bo x "
Ht mllnputCheckBo x
r unat= " server " >
<input type= " fi l e "
Ht mllnputF i le
r unat= " server " >
<input type= " hidden "
Ht mllnputH i dden
r unat= " server " >
<input type= " image "
Ht mllnputl mage
r unat= " server " >
<input type= " radio "
Ht mllnputRadioBut t on
r unat= " server " >
<input type= " te xt"
Ht mllnputTe x t
r unat= " server " >
<inpu t type= " passwo r d "
Ht mllnputPassword
r unat= " server " >
<selec t r unat= " server " > Ht mlSelec t
< t able runa t = " se r ve r" > Ht mlTable
< t r runat= " se r ve r" > Ht mlTableRow
< t h runat= " se r ve r" > , <td
Ht mlTableCell
r unat= " server " >
<te x tarea runa t = " se r ver " > Ht mlTe x tArea
Для всех других дескри пт оров НТМL с
Ht mlGenericCon t rol
атр и бyrом runat= " se r ve r"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Большинство атрибугов дескр ипторов серверных элементов управления


явно прописаны в одноименных свойствах подцерживаю щих классов.
Но если мы собираемся программно установить значения атрибугов, не
представленных никакими свойствами, то нужно воспользоваться
свойством-коллекцией Аt t r i Ьut es , которую предоставляет всем
НТМL-элементам базовый для них класс Ht mlCont r o l . Э та
коллекция представляет собой словарь, в котором атрибугы
представлены парами атрибуг(ключ)=значение , включая события.

Продемонстрируем программно е управление серверными HTML-


дескрипторами на примерах.

Пример программной установки свойств серверных


Н~L-дескрипторов

• ~Создайте новую страницу с отделенным кодом и им ен ем


PropertiesControl и сделайте ее стартовой
• r;.:Fиз вкладки НТМL панели Toolbox поместите на страницу
элемент Input (Text) и сделай т е его серверным командой
контекстного меню Run As Server ControL Про след ите , что на
элементе появил ся маркер с зеленой стрелкой.
• ~3адайте элементу имя Te x tBo x l
• г;;;?Откройте на редактирование файл скрытого кода, выполнив
на странице командУ контекстного меню View Code, и введите в
обработчик события Page Load () следующий код

public partial class PropertiesControl: System.Web.UI.Page


(
protected void Page_Load(object sender, EventArgs е)
(
11 Выполнять инициализацию только при п ервой загрузке страниц
11 Далее информация бу,цет отслеживаться в состоянии вида
if (!Page.lsPostВack)
(
11 Установи ть атрибугы стиля для н аст р ойки внешнего ви да
ТехtВохl.Stуlе[ "fопt-size"] = ''20рх'';
TextВoxl.Style[ "co lor '1 = ''red'';

В,
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

11 Использовать слегка отличающийся, но эквивалентный синтаJ


TextВoxl. 5 tyle . Аdd('Ъасkgrоuпd-со lor ", ''yellow');

11 Установить текст по умолчанию


TextВoxl.Value = ' 'Введ ите здесь адрес электронной почты ";

11 Установить другие нестандартные атри бугы через коллекцию


TextВoxl.Attribute s["onfocus' 1 = "а lеп(ТеxtВохl. value )";
}
}
}

Листинг . Код программного задания свойств серверного HTML -


дескриптора в файле РrореrtiеsСопtrоl.аsрх.сs

Р езул ьтат долже н п олучи ться пример н о таким

,111 Untitled Page - Microso


File Edit View Favorites
~~~ O@1 Gj ш FаVОritеs

hti+J:j,1ocallost: 1043;WebSite l;f'roperbesC

I Введите здесь адрес электронной почты

Мicrоsоft Internet Explorer

Введите здесь адрес электроt-t-lой почт ы

еж

Doпе I n 1J"anet

Все на ши п рограммные н астройки элемента lnput (Text) п рев р атятся на


ЮJИенте в следующий HTML-кod
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

<input naше='ТеxtВох l " type=''text'' id='TextBoxl "


style=''width:428px;fo nt-size:20px;color:red;background-color:yeIlow;"
vаluе=''Введите здесь адрес электронной п о ч ты"
onfocus= "аlert(ТеxtВох l . value)" 1>

Пока за нный в прим е ре до стyn к атрибуга м с е рверны х HTML-


дескриптор о в яв л яется , по суги , одинаковым дл я в с ех эле ментов.

Пример программного создания серверных НТМL­


дескрипторов

Иногда инте рфейс пол ьзова тельской НТМL - страницы тр ебуется


формирова ть ' 'на лету" в зависимос ти от конкретны х усл о вий.
Например , мы з ар а нее не з нае м, ско л ько данны х нужн о вы б ра ть и з ба з ы
дл я р азмещения в табл иц е, или какие ср едст ва ynр а в л ения
предоставить кrlИ е нту в з ави с имос ти от его пр едп о чтений.

AS P.N ET nредлага ет р е шение эт ой пр облем ы. Можно , на ос новании


nоявившей ся информации , динами чес Ю1 со зда ть эле ме н т ynравления ,

nрогр а м м но уста н о вить его с вой ств а и до бавить в колле кцию


Co n t r ols с траницы - кон тейнера .

• IJ$Д обавьте к nрил ожению новую страниц у с раздельным кодом


и им е н ем Dynam i cTable и сдела йте ее с та рт о вой

Се йчас со зданная страница п устая. Н а ша задач а дин а мичесЮ1


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

• ~в еди те в класс Dyna micTable сл едующий код

риыic рапia l class ОynaшiсТаЫе : System.Web.UI.Page


(
protected void Page_Load(object sепdег, ЕvепtAгgs е)
{
11 Создаем объект заголовка, настраиваем
11 и добавляем к объекту-стра н ице
HtmlGenericCo ntro l header =
пеw НtmlGепегk::СопtrоЮ;
ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

hеаdег.lпnегНtml = "< h1 >Динамическая<Ьг/> таблица <1h1> ";


hеаdег.Stуlе[ "со Юг"] = "red";
this. Сопtгоls.Аdd(hеаdег);

11 Создаем объект-таблицу HtmIГaЫe


HtmlТabIe table1 = new HtmIГaЫeO;

11 Установим свойства таблицы


table1.Border = 1; 11 Толщина внешней рамки
table1.CellPadding = З; 11 Отступ содержимого ячейки от рам
table1.CellSpacing = З; 11 Зазор между линиями рамки
table1.BorderColor = ''red''; 11 Цвет линий рамки

11 Объявляем вспомогательные ссылки на строки и столбцы'


HtmlТabIeRow row;
HtmlТabIeCeU сеll;
in! maxRow = 5, maхСеП = 4;
for (int i = 1; i <= maxRow; i++ )
{
11 Создаем строку и настраиваем ее свойство
row = new HtmlТabIeRowO;
row.BgColor = (i % 2 == О ? ''lightyellow'' : ''lightcyan'');

11 Создаем ячейки и добавляем к строке


for (intj = 1; j <= тахСеll; j++ )
(
11 Создаем ячейку
сеll = new HtmlТabIeCeU();
11 Заполняем ячейку содержимым
сеlllпnегНtml = 'Row: " + i ToStringO + "< Ьг 1>"
+ "Cell: " + j.ToStringO;
11 Добавляем ячейку к текущей строке
гow.Cells.Add( сеП);
}

11 Добавляем строку к таблице


table 1.Rows.Add(row);
}

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

// Добавляем таблицу к странице


this. C ontrols.Add(table 1);
}
}

Листинг . Код динамического создания таблицы в файле


DynamicTable.aspx.cs
• ~ы п олните ст р аницу и должен п олуч иться такой ~еЗJmьт,1Т
11 Untitled Page - Мicrоsоft Internet Ех ..
----------
File Edlt y~.". FavoГltes Tools Help

hl:ljo:!~ocalhost: 1043(WebSite ljC • !PGo

Динамическая
таблица

[ROW: 1[ ROW: 1[ ROW: 1[ ROW: 1[


Cell: 1 Cell: 2 Cell: 3 Cell: 4
[ROW: 2[[ ROW: 2[[ ROW: 2[[ ROW: 2[
Cell: 1 Cell: 2 Cell: 3 Cell: 4
[ROW: 3[[ ROW: 3[[ ROW: 3[[ ROW: 3[
Cell: 1 Cell: 2 Cell: 3 Cell: 4
[ROW: 4[[ ROW: 4[[ ROW: 4[[ ROW: 4[
Cell: 1 Cell: 2 Cell: 3 Cell: 4
[ROW: 5[[ ROW: 5[[ ROW: 5[[ ROW: 5[
Cell: 1 Cell: 2 Cell: 3 Cell: 4

Local in1J"anet
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

События серверных НТМL-элементов

Большинство серверных НТМL-элементов в инqюрмации, прибывшей


на сервер с об р атн ой отсылкой, распознают события , которые
ПРОИЗОlШlи с их НТМL-представлением на стороне клиента. В
основном это два события:

1. Собы тия щелчка - ServerClick


2. Собы тия изменения - ServerChange

Событие Se r ve r Cl i ck отображает щелчок, происшедший на стороне


ЮlИента, но обрабатываемый на стороне сервера. В обработчике этого
события можно переопределить ожидаемое поведение , например ,
прервать отсылку e-mail при обнаружен ии ошибки в адресе , проверить
полномочия и т.д.

Событие ServerChange генерируется при внесении изменений в


текстовое пол е или элемент выбора. При поступлении на сервер
обратной отсылки ( постинга ) для каждо го измененного элемента
управления генерируется событие Serve r Change . Самым последним
в ц е поч ке событий генерируется событие Se r verCl i c k кнопки ,
инициировавшей постинг.

в таблице пока зано, какие элементы управления подцерживают


событие Se r ve r Cl i c k, а какие - событие Se r ve r Change .

Подцержка событий серверными элементами управления


НТМL

Событие Подцерживающие элементы управления HTML


System.Web.UI.HtmlControls.HtmlAnchor

Sys tem.Web.U I.HtmlCo ntrols.HtmlВutton

S ystem. Web. U I. HtmlC ontro Is. HtmlInputButto n


ServerClick
System.Web.UI.HtmlControls.HtmlInputSubmit

S ystem. Web. U I. HtmlC ontro Is. HtmlInputReset


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

System.Web.UI.HtmlControls.Htmllnputlmage

System. Web. UI. HtmlC ontro Is. HtmlS е !ect

System.Web.UI.HtmlControls.HtmrrextArea

System.Web.UI.HtmlControls.HtmllnputCheckBox

ServerChange System.Web.UI.HtmlControls.HtmllnputHidden

System.Web.UI.HtmlControls.HtmllnputRadioButton

System.Web.UI.HtmlControls.HtmllnputText

System.Web.UI.HtmlControls.HtmllnputPassword

Пример обработки событий ServerClick и ServerChange

Приведем пример , демонстрирующий перехват и порядок генерации


рассмотренных событий серверных НТМL·элементов управления.

• IJ$Добавьте к приложению новую страницу с разделенным кодом


и им е н ем EventsContro~ и сделайте ее стартовой
• Г;;:;nоместите на ф:Jрму с вкладки НТМL панели Toolbox
следующие элементы:

о Select · окно списка с именем L i stl


о Inpu t (Te x t) · текстовое поле с именем Те х tbo x 1
о Input (Checkbo x ) - флажок с именем Checkbo x l
о Input (Submit) -кнопкус именем SuЬm i tl
• ~ реобразуйте элементы в серверные командой контекстного
менюRun As Server Сопио!
• ~ режиме Design редактора HTML · кoaa выполните команду
Edit/Se!ect All, а затем командУ FопnatJJustify/Сепtег дл я
выравнивания элементов в центре окна

в результате, интерфейс страницы долже н быть представлен


следующим HTML·кaaoм

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

<%@ Page L апguagе="С#" АutоЕvепtWirеuр=''truе''


С ode F ile=' 'EventsC о пtrо Laspx. cs"
lпhеr its=''ЕvепtsСо пtrоl'' % >

<html xmIпs="httр :lIWWW.W3.0rgl1999/xhtml">


<head nmat="server">
< title >Uпtitled Page</tide >
<lhead>
<body>
< fо пn id="forml" ruпаt="sеrvеr''>
<div style=''text-align: сепtеr">
<se lect id="List1" ruпаt="sеrvе r" style="width: 202рх" muhiple size="3">
< орtioп sе lесtеd > Опция 1 <Ioption>
< орtioп > Опция 2 <lорtioп>
< орtioп > Опция 3 <lорtioп>
</select>
<br 1>
<br 1>
< iпрut id='Textboxl" nmat="server" typ e= ''text'' 1>
<br 1>
<br 1>
< iпр ut id="Checkboxl" runat="server" type="checkbox" 1>
<br 1>
<br 1>
< iпр ut id="Submitl" nmat="server" type="submit" value="submit" 1>
</div>
</foпn>
<!body>
<lhtml>

Ли стинг Де С lCрипт ор н ое представление страницы

ЕvепtsСопtrоl.аsрх

Элеме н т mul t i ple в списке дает во зм ожность пользователю


выбирать несколько элементов списка , Уде р жив ая клавишу CtrL Ат ри бyr
s iz e задает число видимых элементов списка при скролирова нии.

Элеме н т selec t ed указывает, какая опция должна быт ь в ы делена при


за грузке списка.

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• ~ ерейдите в режим редактирования кода С# и создай те


обработчики соб ытий для текстового поля , с пи ска и кнопки

Самым легким cnособом создания обработчика дл я серверного HTML-


элемента является д войной щелчо к на нем в режиме Design. В этом
случае среда разработки создаст заготовку об р аботчика в файле С# и
свяжет ее с элементом ynравления , до бавив соответсвующий код в
дескриптор.

Но об р аботчик таЮ1М способом будет создан только дл я того события ,


которо е определен о в элементе его изготовителем как событие по
умолчанию с помощью атрибyrа
[Dе f аul t Еvеп t ( " И мя соб ы ти я" )] . Для других же событий
элеме нта упр авления обработчиЮ1 созда ются с помощью явной
п одписки на них в вызывающем коде.

Изменение содержимого текстового поля и состояния флажка мы


привяжем к одному и тому же обработчику. Для эт ого

• ~С копируйте из дескриптора элеме нта текстового поля


Te xt bo x l созданную при вязку обработчика в дескриптор
флажка Checkbo x l

После созд ания об р аботчиков дескри пторы серверных HTML-


эл ем ентов ynравления БУдУГ иметь ви д

<se lect id=''List1 '' runat="server" style=''width: 202 р х" multiple size="З"
оnsеrvегсhапgе=''Listl_SеrveгС haпgе''>
< iпрut id='Textboxl " runat="server" type=''text'' оnsеrvегсhапgе='ТехtЬохl_Sе J
< iпрut id="C hec kboxl " runat="server" type="checkbox" onserverchange='Textb
< iпрut id="Submitl" nшat="sеrvег" type="submit" value="submit"
onserverclick="Submit l ServerClick" 1>

• ~3аполните созданные обработчиЮ1 событий следующим кодом

usiпg System;
usiпg System.Data;
usiпg Sуstеm.Сопfigurаtiоп;
usiпg Sуstеm.СоlIесtiо пs;

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

using System.Web;
using Sуstеm.WеЬ.Sесшitу;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

риыic рапial class EventsControl: System.Web.UI.Page


(
protected void Page_Load(object sender, EventArgs е)
{
if (!this.lsPostBack)
(
List1.ltеm;.Аdd( "Д ОП. опция 4 '');
List1.1tеПl5.Аdd( "Д ОП. опция 5'');
List1.Itеm;.Аdd( "Д оп. опция б '');
}
}

protected void Textboxl_SelVerChange(object sender, EventArgs е)


{
Response.Write("<li>SelVerChange перехваче но дл я " +
«Control)sendeг).lD + "</Ii>');
}

protected void Listl_SelVerChange(object sender, EventArgs е)


(
Response.Write("<li>SelVerChange перехваче но дл я List1. "+
' 'Пользователь выде л ил следующие опции:< IIi> < Ьг 1> '') ;
foreach (ListItem li in Listl.Items)
(
~ (IlSelected)
Response.Write("&nbsp;&nbsp;- " + IL Value + "< Ьг 1>'');
}
}

protected void Submit1_ServerClick(object sender, EventArgs е)


(
Response.Write("<li>ServerClick перехвачено для Submitl <1Ii>'');
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

}
}

Листинг Обработчики событий в файле

EventsControl.aspx.cs
• Г;;:;=Запустите страни ц у на выполнение и получите примерн о
такой результат

"г' i
-
,

в качестве дополн ит ельно го действия при п ервой загрузке страницы


обработчик Page_LoadO добавляет еще три элемента к окну с пи ска .
Эти м демо н стрируется простота прогр амм нorо добавления элементов
списка.

Следует отметить, что собы тия изменения MOryr ге н ерироваться


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

Web-элементы управления

Мы так подробно рассматривали элементы управления с вкладки НТМL


только для того , чтобы больше к ним н е возвращаться. В основном
рекомеНдУется пользоваться элементами управления с вкладки Standard,
которые не только полностью покрывают возможности первых. но и

значит ельно превосходят и х по своей функциональности. Серверные


НТМL-элементы управления были р азработаны для существующих
НТМL-дескрипторов с целью обратной совместимости. Web-
элементы являются современным самостоятельным произведением.

Web-элементы изначально счи таются серверными и обязательно


должны содержать встроенный атр и буг runa t= " server ". Поэтому

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

и х можно и н е называть серверными , итак понятно , о чем идет речь .

Для луч шей узнаваемости соответствующие им дескрипторы

начина ются с префикса азр . WеЬ · элементы мо гуг автоматически

определять тип броузера кл и е н та и подстраиваться под него , генерируя


сложный HTML ·Koa из н ескольких т е гов и JavaScript ·сценариев. Они
и меют богаты й н абор событий, которые можно выбират ь прямо из
пан ели Properties. С Web-элементами можн о р аботать так же легко, как с
объектами локальных приложений.

Web-элементы управле ни я также пр едставляются цепочками

на следов ания классов. Часть и ерархии наследования приведена на


рисунке.

'"
В.М С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

I Sушm Object I
I S~te m Web.UI, ContJol I
- - - - -- -
Пространство имен
-------- -
System.Web.UI.WebControls
- ,
I
~t<:'.1ntfQl

I
I I
Н 6цасп
I Н L i te Г1il I
I ваsе~ШВСun ОСQП1ГQ I

Н ctJo<;k6Qx
I Н РI~ еНQIO-е'
I I D;lt<JE\Quno:.:lC<>ntrol I
Lr Rэdi: >6u\toп I Н Сэ l$nd"г
I -1 AdRoWoI
I
Н H~perlink
I -1 'т' I -1 СQmрсsiteDэmВСUnclCoП1rоll
Н I mэge
I -1 VЭhdati опSu mmэ ry I Н Doe1ai~V i ew
I
-1 I m~ge6...tton I I 6-;J$еv", ]id;Ш>l
I Н FQIfТIV~w
I
--1 Image"-lap I IВ<llseCоmрз rеV.аlkjз lo г I Н Qrl dVlew
I
Н l.oI" ,
I Ч- C()mj);'lteVi! lid;'\kJt I Н LlstControl
I
Н Llnt:BullOn
I Н СU зt)m\lll l l~kJ.
I Н Ch~ k.ВC~Llst
I
Н F ane l
I Н RangeVa lldator
I Н DIOpDawnL Is1
I
Н т.".
I -1 Reguta rExprer;,sl() nValidaoor I Н LlslВo~
I
Н TableC e~
I --l RequlredFieldValidator I --1 RadloBullOnL ls1
I
Ч-Т3tjенеS(1е tCеl l l --1 Bulete(j,..Ist
I
Н ТэЬ\оеRow
I -i Н ierэ гс hiсэ lDэtэВОu ndC ()П1rol I
Н Text60x
I --1 Menu
I
Н TreeView I )
I
---------------- - - - - -- - -

Базовый класс WebContro!

Все элем е нты уп р авле ни я Web унаследованы от класса WebCon trol .

'"
В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

который, в свою очередь, наследуется от Con trol . Поэтому многие его


свойства и методы , например , Cont r ols , Vi s i ble,
FindCon t rol () таЮ1е же, как и у НТМL-элементов ynравления. Но
есть и свои до п ол ни тельные свойства , основные из которых п риведены
в таблице .

Дополнительные свойства базового КIIacca WebControJ


Свойство Описание

Возвращает или устан авливает сокращенную


комби нацию , позволяющую быстро
п ереместиться на элемент ynравления.

АссеззКеу Например, при установке свойства в значение А


п ользователь может п еренести фжус на этот
элемент ynравления , на жав комбинацию
<Alt+A>
Набор дополнительных атрибугов элеме н та
ynравления. Коллекция, позволяющая вводить
Attri butes до п ол ни тельные атрибугы, которых нет в
открытых свойствах, н о которые вообще может
иметь генерируемый НТМL-тег

BackColo r Возвращает или устан авливает цвет фона

Borde r Color Возвращает или устанавливает цвет гран ицы

Одно из предо пр еделенных значений


BorderSty 1 е : Da shed ,
п еречисления
BorderStyle Dotted , DоиЫе , Groove , Inset ,
None , NotSet , Outset , Ri dge ,
Sol i d
BorderWi dth Возвращает или устан авливает ширину границы

Возвращает или устанавливает стиль каскадной


таблицы стилей CSS элемен та ynравления .
СтильCSS может быть определен в разделе
CssClass
<style> в верхней части страницы или в
отдельном файле, на который ссылается
страница

Список свойств каскадной таблицы стилей


Style CSS, которые можн о приме ни ть к элементу
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

ynравления

Возвращает или устанавливает достynность


элемента ynравления. Недостynный элемент
присугствует на проектируемой странице ,
отображаясь серым цветом, но участия в
Enabled
формировании рендеринга не принимает и на
юшенте не отображается. Но при необходимости
его можно программно ВЮIючить и он начнет

генерировать полноценный HTML-коJ

Булево свойство, ВЮIюченное по умолчанию и


EnableThem i ng
разрешающее применять темы оформления

Булево свойство, ВЮIюченное по умолчанию и


разрешающее сохранять текущее состояние
EnableV i ewState
элемента ynравления вместе с ОТЮIиком на

компьютере ЮIиента

Возвращает объект со всей информацией о


стилях шрифга , используемого для текста
Font элемента ynравления. Э ТО свойство содержит
nодсвойсmвй , которые можно устанавливать с
помощью синтаксиса прохода по объекту

Возвращает или устанавливает цвет перед него


ForeColor
плана элемента ynравления

Возвращает или устанавливает высоту элемента


He i ght
ynравления

Назначает СКИН дЛЯ применения к элементу


Sk i nID
ynравления

Определяет порядок обхода элементов


TabInde x
интерфейса страницы по ЮIавише < ТаЬ >

Определяет короткую подсказку для элемента


Тооl Tip
ynравления

Width Определяет I.Шiрину элемента ynравления

Каждый элемент ynравления при вносит свои допо л нительные


свой ства и метод ы , главное назначение которых - ynростить начальную
на стройку и программное ynравление элементов , сделать его

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

интуитивно пон ятным и уменьшить возможные ошибки . Большой Билл


сказал: зачем программистам знать НТМL , п усть о ни правильно
на строят свойства элементов управления, а уж сами элементы
сгенерируют такой НТМL , какой нужно.

Заполн ение свойства Тех! данными из ненадежного


источника

Мно гие элементы управления MOryr пр инимать данные через свое


свойство Te xt . Это может быть элемен т управления Label ,
Te x tBo x, CheckBo x, Rad i oBu t ton , But t on и другие. Если
данные мы не генерируем сам и , а они п оступают из внешнего

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


база данных) , то для безо па с н ости мы должны считать их
н енадежными и п еред записью в свойство Te x t обязательно
обрабатывать на пр едмет ИСЮJючения возможны х управляющих
символов. Для такой обработки предназначен метод

public static strmg Systеm.WеЬ.Нttрutilitу.НtmlEпсоdе(string)

Программное управление свойствами Web-элементов


управления

Управление размером элемента

Из пр едыдущей таблицы ви д но , что все элементы управления Web


на следуют от класса WebControl такие свойства размера, как
BorderWi d t h , Height , Width . Их можно задавать не только в
режиме проектирования, но и пр о граммно в режиме выполнения

страницы. Все о ни будуг отображаться в соответствующие атрибугы


дескрип то р а . Размеры задаются не только значением, но и единицами
измерения (рх - пикселы, %- про ц е н ты).

Пусть, например, у на с имеется Web-элемен т уп р авления Panel ,


который отображается дескрип тор ом
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

<asp:Pane l ID="pnl" runat="server" Неight= "ЗООрх" Width="50%" 1>

Здесь свойства р азмера заданы в панели Properties на этапе


проектuрования. Для пр о гра ммной установки значения свойств а
размера можно:

• П ервый вариант: и с поль зовать структуру

Sys t em . Web . UI. WebControls . Unit и ее статические

методы

11 Задание высоты элемента рnl в пикселах


рпLНеight = Unit.Рixе~ЗОО);
11 Задание ширины элеме н та рnl в процентах
рnL Width = Unit.Percentage(50);

• Второй вариант: создать эюем п ляр структуры


Sys t em . Web . UI . WebCon trol з . Uni t и сразу е го настроить ,

затем и с поль зовать для установки свой ст в размера с


при ме н е ни ем предо пр еделен ного п е речи сления

Sys t em . Web . UI. WebControls . Unit T ype

11 Заготавливаем эюемпляры структуры Unit для хранения


11 высоты и ширины в нужных единицах измерен и я
Unit height = new Unit(ЗОО, UnitType.Pixel);
Unit width = new Unit(50, UnitType.Percentage);

11 Устанавливаем свойства элемента уп р авления


рпLНеight = height;
рпL Width = width;

Управление стилем

Управл е ни е стилем также использует пр едУста новл е нно е перечисление


System . Web . UI . WebControls . BorderStyle

pnlBorderStyle = BorderStyle.Dashed;

На клие нте получим такое пр едставление пан ели

'"
.--------.
В.М. С""",,,в

I I
Про,раммupoвtJNШ' 110 ASP. N ET

I I
I I
I I
I I

.. _------_ ..
I I

Управление цветом

Для задания значений свойств цвета элеме н тов управления, таких как
BackColor , BorderColor , Fo r eColor , используется структура
System . Drawing . Colo r с п редопределенными цветами и ее
методы , или статические методы класса
System . Drawing . Colo r Translator . Для сокращенного
использован ия на стра ниц е такого арсенала н ужно импортировать в

кодовый файл .aspx.cs о пр еделение простра н ства им ен System.Drawing

usiпg System.Drawing;

или п рименять полное имя кnacca или структуры при обраще нии к их
компонентам .

Приведем пр имеры разных способов определения цвета. Для этого


поместим на форму три элемента уп р авления Button . Управляющий
код С# будет таким

usiпg System;
usiпg System. Web.UI. WebControls;
usiпg System.Drawing;

public partial class Тmр : System.Web.UI.Page


(
protected void Page_Load(object sender, EventArgs е)
(
11 Использов а ни е свойств структуры System. Drawing.Co lor
Buttonl.BackColor = Color.Red;

11 Использов а ни е метода структуры Systеm.Dгаwiпg.Соlог


int alpha := 255; 11 Пол но стью н е пр озрач ныи
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

int red = О, green = 255, bIlle = О;


Button2.BackColor = Color.F romArgb(alpha, red, grееп, bIlle);

11 Использование статического метода


11 класса System.Drawing.Colo rTranslator
ВuttоnЗ.ВасkСоlог = СоloгТгаnsLз tог.FгоmНtml( ' '#ООООFF');
ВuttоnЗ.FогеСоloг = Co lorTranslator.F romНtml( ''white');
}
}

Листинг

PropertiesControll.aspx.cs
Управление цветом
• файле

в результате , п ользователь в броузере увиди т следующее

: lM3;WebSite lrrrr т

[ Button2 '
Оопе Local iп1Тапеt

Управление шрифтами

Каждый элемен т управления наследует класс WebCon trol , который в


свою очередь содержит свойство Font . Факти чески, свойство Font
представляет собой эюем п ляр класса

System . Web . UI . WebCont r ols . Fontlnfo , и имеет все

необходи мые свойства для определен и я шрифга. Ниж е пр иведен


при мер кода , н астраивающего шрифгы надписей кно п ок

llsiпg System;
llsiпg System. Web.UI.WebControls;
llsiпg System.Drawing;

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

public partial class Тmр : System.Web.UI.Page


(
protected void Page_Load(object sender, EventArgs е)
(
Buttonl .BackColor:= Color.Red; // Настройка цвета
Buttonl .Fo nt.Name:= 'Vernada"; // Настройка шрифга
Buttonl .Fo nt.Bok:l = true; // Полужирный

// Настройка цвета
int alpha = 255;
int red = О, green = 255, blue:::: О;
Button2 .BackColor:= Color.FromArgb(alpha, red, grееп, blue);
// Исп ользуем ст р уктуру Sуs tеm.WеЬ.U I .WеЬСопtrоls.FопtUnk
// уста н овки отн осительного размера шрифга
Button2 .Fo nt.Size:::: FontUnit.Smaller;

// Настройка цвета
ВuttоnЗ . ВасkСоlог:::: СоloгТгаnsLз tог. FгоmНtm1(''#ООООFF');
ВuttоnЗ . FогеСоЮг:::: Co lorTranslator.FromНtm1(''white');
// Исп ользуем ст р уктуру Sуs tеm.WеЬ.U I .WеЬСопtrоls.FопtUnk
// уста н овки абсолютного размера шрифга в пунктах
ВuttоnЗ . Fо пt.Size:::: FontUnit.Point(16);

ВuttоnЗ . Fо пt.Uпdег linе:::: true; // Подчеркнем


}
}

Листинг
РrореrtiеsСопtrоl1.аsрх.сs
Управление шрифтом
• файле

в результате таких программных на стр оек сгенерируется HTML-кod ,


который посмотрит на клиен та следУЮ ЩИ МИ глазами (трехглазое
чудовище)

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

11 Untitled Page - Мicrоsоft Internet Explorer


FMe Edit View Favorites ТОols Help

у .. у ID Ш t::! I ~ Search tiJ Favorites


: 1043!WebSite l(rmp.aspx .....

Button2
Оопе Local iп1Т.:nеt

Чушь!, ко н ечно, зато знаем как .. Студент З и боров - н е спи, а читай


дальше.

Управление фокусом ввода

В отли ч ие от НТМL-элементов , все элемен ты Web н аследуют метод


Focus () , но оказывает он влиян и е только на элемен ты ввода (
прини мающие клавиатурный ввод пользователя ). При появлении
страницы на стороне клиен та курсор сразу уста на вливается на поле

ввода, для которого на сервере был выполнен метод Focus () , а


страница автоматически прокручивается до видимого положения.

Пользователь может п е ремещаться по элементам с помощью клавиlШ1


< ТаЬ > .

Конечно , в самом HTML нет средства установки фокуса , но с п омощью


скриптов на JavaScript такой эфрект можно задать . Что и генерирует
соответствующий Web-элемент при вызове для него метода Focus () .
Если метод Focus () вызывался для нескольких элементов ввода , то на
кrlИенте JavaScript выбирает тот, кото рый получил фокус раньше д рyrnх.

Вместо программно го вызова метода Focus () можно назначить


элемен т управлен и я, который всегда долже н п е рвым пр инимать фокус
ввода при отображении страницы в броузере. Э ТО делается с п омощью
свойства Dе f aul tFocus дескрип тор а формы следующим образом
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

< fо пn id =''Fопnl'' DefaultFocus='TextВox2" runat="server''>

После такого назначения клиенту будет сгенерирован JavaScript-


сценарий по установке фжуса ввода на текстовое поле с именем
Te x tBo x2 .

Еще один способ ynравления фокусом заключается в использовании


клавиш уско ренного достynа (горячих клавиш). Например , если дл я
текстового поля (Web - элемент Te x tBo x ) установить свойство
Access Key в значение А, то пользователь комбинацией клавиш
<Alt+A> может быстро перевести ф:Jкус ввода на этот элемент.

Еще один способ ynравления фокусом - использование метки Label .


Если установить в свойстве Assoc i atedCon t rol ID значение ID
элемента ввода , то при адресации по горячим клавишам к ф:Jкусу метки
фокус получить связанное с меткой текстовое поле. Например ,
следующая метка переносит ф:Jкус ввода на элемент Te x tBo x2 при
нажатии клавиатурной комбинации <Alt+2>

<asp :Label AccessKey= ''2'' AssociatedCo ntro UD= 'TextВox2" runat="server''>


Введите TeKcT:</asp:Label>
<asp:TextBox ID='TextBox2" гuпаt="sеrvег" />

Кроме элементов ввода можно на странице назначить кнопку по


умолчанию, которая БУдет ожидать нажатия пользователем клавиlШ1
Enter. Например , может потребоваться превратить кнопку Submit формы
в кнопку по умолчанию, чтобы при нажатии пользователем клавиlШ1
Enter на клиенте инициировался постинг, а на сервере запускалось
событие В и t ton . Cl i c k этой кнопки.

Для назнач е нии кнопки по умолчанию нужно указать в свойстве


Ht ml Fo r m . DefaultBut t on (или прямо в дескрипторе формы)
значение идентификатора кнопки. Например

< fо пn id=''Fопnl'' DеfauhВuttоп= ' ЪtпSuЬmit" nшat="sеrvег''>

Кнопкой по умолчанию можно сделать элементы Ви t ton .


LinkBu tt on , ImageBut t on .

Элемент Рапе ] также подцерживает свойство кнопки по умолчанию.


ш
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Если на страни ц е н есколько пан елей со своими кнопками, то для


каждой панели можно назначить свою кнопку по умолчанию, которая
должна срабатывать в активной панели при пользовательском нажатии
ЮJaВИШИ Enter.

Элеме н т Рапеl обладает возможностью скролирования. Если


размещенные на панели элеме н ты не помещаются в уста новленные

размеры и для пан ели установлены свойства прокрyrЮ1 , то панель


генерирует поло сы пракруmки. ВЮIючение прокрyrки элеме н та Рапеl
осуществляется за счет установки ее свойства Sc r ollBars в одно из
значений: Vertical , Horizontal , Both, Auto.

Следующий простой дескрипторный код демонстрирует свойство


прокрyrЮ1 элемента Рапеl

<%@ Page Lапguagе= "С#" АutоЕvепtWirеuр=''truе''


С ode F ile=' 'Рапе lS сго lLas рх. cs "
Inherits= ''PanelScroU'' %>

<html xm1пs="httр :llwww.wЗ.огgl 1999/xhtml">


<head nmat= "server">
<title>Untitled Page</tide>
<lhead >
<body Ьgсо!ог=' '#ffffб6''>
< fопn kl ="fопnl " ruпаt="sеrvег' '>
<div style=''text-align: сепtег">
<asp:Pane! I D="Рапеl1" runat="server" ScroUВars=''Vertical''
Неight= "З ООрх " Width="261px" BackColor="Red" BorderWklth="lp
< h1 > Привет BceM!!! <lhl >
<asp:TextBox ID='TextBox2" ruпаt="sеrvег' '>доцент C HeTКOB </asp
< Ьг 1>
<asp:TextBox ID='TextBoxl" ruпаt="sеrvег' '> студент Зиборов< /аs]
< Ьг 1>
< Ьг 1>
< аsр:Вuttоп ID= "Buttonl " runat= "server" Text="CTepeTb доцента" ;:

< Ьг 1>
< аsр:Вuttоп ID= "Button2 " runat= "server" Text="CTepeTb студента " I

</asp:Pane!>
</div>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</form>
<!body>
<lhtml>

Листинг Код файла PanelScroll.aspx

Клиентский вывод БУдет таким

11 Untitled Page - Мicrоsоft Internet Е ...


----------------------------
FMe Edlt V~W Fаvопtes Tools Нер
т .. т liiII l1J GI I[1se"Ch
: 1043;WebSite 1;1' т !(>GJ

Пример обработки события Changed Web-элементов


управления

Се рв е рные события WеЬ~элементов рабо тают такж е, как события


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

серверных НТМL-эл емен тов. Только изм е н е ны на зва ния событий .


Вместо на з вания ServerClick используется универсальное на звание
Cl i ck . Общее событие Se r verChange заменяется специфическими
названиями CheckedChanged - для элементов Rad i oBut t on и

Chec k Bu t ton , Te xt Changed - для элемента T e x tBo x . Но их


поведение остается прежним.

Основное различие состоит в том , что Web-элементы имеют свойство


AutoPostBack для возможности ШШЦUQЦUU С помощью клиен тского

Java Script немедленного п остинга, после чего на сервере запускается


соответствующее событие.

Приведем пример , в котором всем элементам ynравления , кроме списка ,


установим свойство AutoPostBac k в значение True . Будем
отлавливать в постинге событие CheckedChanged и обрабатывать
его одним общим обработчиком, добавляю щим строки в с пи сок .

Обработчик события создадим через панель Properties, задав для одного


из элеме н тов, ге н е рирующих событие, имя CtrlC hanged в поле события ,
затем нажав кrJaВИШУ Enter. Для остальных элеме н тов этот обработчик
подключим через раскрывающий ся список п оля панели Properties. Коды
страницы , реализующие пример , приведены ниже .

<%@ Page Language="C#" AutoEventWireup=''true''


С ode F ile=' 'с hecked С hanged .as рх. cs "
Inherits="C hec kedChanged" %>

<html xmIns="httр ://www.wЗ.оrgl1999/xhtml">


<head nmat="server">
<title>Untitled Page</tide>
<lhead>
<body>
< fо пn kl="fопnl" runat="server''>
<div>
<h2>
С пи сок событий
<1h2>
<asp:ListBox ID = "ListВo x l " nmat="server" Height="107px" Width="Зl :
<р />

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<р 1>
<ш 1>
< р 1>
<h2>
Элеме н т ы управления, <br1>
генерирующие событие < Ьг 1>
C hanged
<1h2>
< р 1>
<asp:TextBox ID='TextBoxl" runat="server" AutoPostBack='True"
ОпТехtСhaпgеd="СtгlСhaпgеd ''> Привет BceM!!! </asp:TextBox>
< р 1>
<asp:CheckBox ID="CheckBoxl " runat="server" A utoPo stВac k ='True'
OnCheckedChanged="CtrlChanged" />
< р 1>
<asp:RadioButton ID=''RadioButtonl '' runat="server"
AutoP ostBack='True" Checked='True"
GroupName=''radioGroup'' OnCheckedChanged="CtrlChanged" 1>
&nbsp;
<asp :RadioButton ID=''Rаd iоВuttоп2 '' runat="server"
AutoPostBack='True" GгоuрNаше=''rаdiоGгоuр''
OnCheckedChanged="CtrlChanged" 1>
</div>
</form>
<lbody>
</html>

Листинг ДеСlCрипторное представление страницы

СhесkеdСhапgеd.аsрх

using System;
using Systеш.D а tа;
using Systеm. С опfigша tiоп;
using System. Collections;
using System.Web ;
using System. Web.Security;
using Systеш. Web.UI;
using System. Web.UI.WebControls;
using System. Web. UI. WebControls. WebParts;
using System. Web. UI. HtmlContro ls;
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

public partial class CheckedChanged : System.Web. UI.Page


(
protected void CtrlChanged(object sender, EventArgs е)
(
11 Добавим имя элемента, сгенерировавшего событие , в список
striпg ctrlName = ((Control)sender).ID;
ListВox1. Items.Add( ctrlN ате + '~Changed '');

11 Позиционирование на последний элемент списка


ListВox1.SelectedIndex = ListВохl.1tеms. СОШlt - 1;
}
}

Листинг Код файла CheckedChanged.aspx.cs

Представление в броузере будет, примерно , таким


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

11 Untitled Page - Мicrоsоft Internet Explorer


FMe Edt Ylew Favorites Tools Help
' Bockt -+т О t[\ search Ш FаVОГitеs

СШlСОК событий

CheckBox1_ Changed
RаdlOВuttоп2 _ Сhапgеd
RаdiоВuttоп 1_Сh"пgеd
CheckBox1 Changed

Элементы управлеlПIЯ,
генерирующие событие
Changed
I Привет всем!!!

r. r
Оonе Local iп1Т.:nеt

Списковые Web-элементы управления

Как ВИДНО из n риведенной р анее схемы иерархии кnaccoв, общим

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

базовым КIlaccaм дл я СП исковых элементов управления является класс


Sys tem . Web . U1 . WebCon t r ol s . Li s tControl , который
п ередает им все свои свойства и методы, а также событие
SelectedlndexChanged. В таблице приведены классы ,

пр едставляющие спи сков ы е Web-элементы .

С п исковые Web-элементы

Класс Представляющий дескр ипто р Описание

Выпадающий спи(

заполненный колл
объектов
<asp : L i stlten
DropDownList <asp : DropDownList>
НТМLон
трансqюрмируется
дескри п тор <selE
атрибугом size=
ОКНО списка, запо.
коллекцией объект
<asp : L i stlten
НТМLоно
ListBox <asp :Li stBOx> трансqюрмируется
дескри п тор <selE
атрибугом size=
Х - количество ви )

элеме н тов

Его элементы в Н1
трансqюрмируютс
CheckBoxList <asp :C heckBoxList> флажки, выровнен
таблице с одним и
н есколькими стол{

То же , что и
<asp : CheckBo}
RadioBu t tonLis t <азр : RadioBu t tonLi s t> но элементы

трансqюрмируютс
радиокнопки

Статический

'"
в.м. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

маркированный и.
нумерованный СПl
НТМLон
трансqюрмируется

Bu l letedLis t <asp : Bulleted List> дескрипторов <ul


unordered list -
маркированный) у

< о 1 > ( ordered list


нумерованный) .Е
можно применять,

для создания тпе]

Из цепочки насл едования через базовый кла сс


Sys tem . Web . U1 . WebCon t rols . Li s tControl элементы

управления наследУЮТ некоторые важные свойства

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


ListControl
Свойство Описание

При значении t r ue qюрма отправляется


AutoPostBack обратно на сервер, когда пользователь
изменяет текущий выбор

Коллекция элементов Lis tl te m


списка. Э лементы можно, также ,
I t ems добавлять демаративно в режиме
проектирования с помощью

дескрипторов <азр : Li st 1 t em>


Возвращает или устанавливает ин д екс
выбранного элемента. Для списков с
множественным выбором необходимо
Se l ectedlnde x
ЦИ ЮlИчески пройти по коллекции
элементов и про верить свойство
Selected каждого Lis tlt em
Возвращает ссылку на первый
выбранный L i st lt em. Для списков с
множественным выбором необходимо
Se l ectedltem
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Se l ectedltem ЦИ ЮlИч ес ки пр ой ти по коллекции


элементов и про верить свойство
Selected каждого Listl t em

DataSource ,
DataMember , Использую тся для отображения данны х
DataTextField ,
и з базы данных
DataValueF ie ld,
DataTextFormatString

Э лементы управле ни я CheckBoxList и RadioBu ttonL i st


доб авляют свои индивидуальные свойства

Доба вл е нны е свойства п ереключателей C heckBoxList и RadioButtonList


С в ойство Описание

Э ТО свойство принимает значение перечисления


Repea tLayou t , равное Fl ow (л ин ей но) и ли
RepeatLayout
Table (в таблице) . ОНО указ ыва ет, какбудуг
расположены п ереключатели

Определяет, как будет расположен список


RepeatDirection (Значение п е речисления RepeatDirection :
Horizontal , Vertical )
Определяет количество столбцов в случае
RepeatColumns
установки RepeatLayout в Table
Ce l lPadding, Если свойство RepeatLayout установ ле но в
Ce l lSpacing, Table , эт и свойства конфигурируют интерв алы
TextAlign и выравнивание ячеек таблицы

Пример списковых Web-элементов

• ~Добав ьте к при ложени ю новую страницу ListControls.aspx с


р азделе нны м кодом

• ~ оместите на qюрму и з вкладки Standard элеме н т ы управления


и на стройте их в соответствии с прив еденным дескр и п то рны м
пр едставле ни ем стра ницы . Декларативн ое (в режиме
пр оекти р ова ни я) добавление элементов списка выполняйте через

,СО
В.М. С""",,,в

Llstltem Соllеctюn

[1e mbers:

:
Editor

i:СЩ;D~'В'• • • • • • • ~
=== Про,раммupoвtJNШ' 110 ASP.NET

.1J.RI

~
._ ","ИЯ2

i!,dd &е гооуе

ОК CCIГJo::el

<%@ Page Language="C#" AutoEventWireup=''true''


С ode F ile= '1.istC о ntro Is.asp х. cs"
Inherits='1.istControls" %>

<html xmIns= ' huр ://www.wЗ.or!j'1999/xhtml" >


<head runat= "server''>
<tide >ListControls</tide>
<lhead>
<body>
<form id ="forml " nmat="server''>
<div>
< asp:ListВox ID='1.istBoxl " runat="server" SеlесtiоnМоdе=''МuI
<asp:ListItem Sеlесtеd='Тruе' '> Опция 1</asp:ListItem>
< аsр:ListItеm> Опция 2 </asp:ListI tem>
</asp:ListВox>
<р 1>
<asp:DropDownList ID=''DropDownListl '' nmat="server">
<asp:ListItem Sеlесtеd='Тruе' '> Опция 1</asp:ListItem>
< аsр:ListItеm> Опция 2 </asp:ListItem>
</asp:DropDownList>
< р 1>
<asp:CheckBoxList ID= "C heckBoxList1 " runat= "server" RepeatC
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<asp:CheckBoxList ID= "C heckBoxList1 " runat= "server" RepeatC


<asp:ListItem Sеlесtеd='Тruе' '> Оnция 1 </asp:ListItem>
< аsр:ListItеm> Оnция 2 </asp:ListI tem>
</asp:CheckBoxList>
< р 1>
<asp:RadioButtonList ID="RadioButtonListl " runat="server"
RepeatColumns="2 " RереаtDirесtiоп= "НOI
<asp:ListItem Sеlесtеd='Тruе' '> Оnция 1</asp:ListItem>
< аsр:ListItеm> Оnция 2 </asp:ListItem>
</asp:RadioButtonList>
< р 1>
<asp:Button ruпаt="sеrvег" ОпС liсk= ' 'Вuttопl_Сliсk '' Text="OTn
</div>
</fonn>
</body>
<lhtml>

Листинг Десхрипторное представление страницы


ListControls.aspx
Отметьте, что для п р и мера мы Удалили и де н ти фикатор кнопки
Вuttо п, поскольку н е соби р аемся ею nporpaMMHo ynравлять.
• ~3аnолните фай л скрытого кода так

usiпg System;
usiпg System.Data;
usiпg Sуstеm.Сопfigurаtiоп;
usiпg System.Collections;
usiпg System.Web;
usiпg System.Web.Security;
usiпg System.Web.UI;
usiпg Sуstеm.WеЬ.U I .WеЬСопtrоls;
usiпg Sуstеm.WеЬ.U I .WеЬСопtrоls.Wе ЬРаrts ;
usiпg System.Web.UI.HtmlControls;

public рапial class ListControls : System Web.UI.Page


(
protected void Page_Load(object sепdег, Еvе пtAгgs е)
{
if (!Page.I s Po stВack)
{
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

{
ListВохl.ltеП15.Аdd("Опция" + i То5triпgО);
DгорDоwnList1.ltеms.Аdd("Опция" + i То5triпg());
С hесkВоxLis tl.1tеms.Аdd("Опция " + i То5 tгiпg()) ;
RаdioВuttопListl.1tеms.Аdd(''Опция'' + i То5triпg());
}
}
}

protected void Buttonl_Click(object sепdе г, ЕvепtAгgs е)


{
// Пер ебо р для элемента ListBoxl , до п уска ющего множествен
Rеsроnsе.Wгitе("< Ь > Выделенные опции в ListВoxl:< Ib >< br /> '
foreach (ListItem li in ListВo x l.1tems)
{
if (IlSelected)
Response.Write("- " + liText + "< Ьг /> ');
}

// Одиночный выбор для Drop DownList1 , п ереб ират ь элемеН1


Response.Write("<p />< Ь > Выделенная опция в DropDownListl:
Response.Write("- " + Drop DownListl .5elected ltem.Text + "< Ьг /> '

// Пер ебо р для элемента C hec kBoxListl , допускаю щего множе


Response.Write("<p />< Ь > Выделенные о пции в CheckBoxListl
foreac h (ListItem li in CheckBoxList1. ltems)
{
if (IlSelected)
Response.Write("- " + liText + "< Ьг /> ');
}

// Одиночный выбор для RadioButtonListl , п еребирать элеме н


Response.Write("<p />< Ь > Выделенная опция в RadioButtonListJ
Response.Write("- " + RаdiоВuttоnL ist1.Sеlес tе d ltеm.техt + "< Ьг /~
}
}

Листинг. Файл поддержхи ListContro l s.aspx . cs


• ~3а п устите п р и ложени е. В броуэере п о я ви тся п р и мер н о така я

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• ~Запустите прилож ение. В броуэере появится примерно такая

I lв"'''"'~""Ы '''Щ",'" CheckBoxList1:

II ~~:::: 1 О Опц~.я 3 [j Опция 5


11\ 2 ~ОПЦИf1 4

1 :~ ~::::: QОПЦИf1
31 Q ОПЦИf1 4
5
2
1

Пример статического списка BulletedList

Этот элемент ynравления генерирует либо НТМL -список <и 1 > , либо
<01> . Набор элементов списка задается чере з свойство-коллекцию
1te ms . Им е ются и другие свойства , приведенные в таблице.

Некоторы е свойства элемента System.Web.UI. WebContmls.BulletedList


Свойство Описание

Определяет тип списка. Допустимые


значения определяются п е речислением

Bulle t Sty 1 e : Numbe r ed ( 1 , 2 , 3 ,


.) LowerAlpha (а, Ь , с ,
.) UpperAlpha (А, В , С ,
.) LowerRoman (i, l l , i i i,
Bu11etStyle .) UpperRoman (I, 1 I, II I,
. ) . Форма маркеров при установленном

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

значениями этого же п е речисления

Bulle t sty l e : Disc , Circle ,


Square , Custom l mage
Если свойствоBul l etS t yle установлено в
Customlmage , то это свойство
Bu l letl mageUrl Bulle t lmageU r l должно указывать на
изображ е ни е, используемое в качестве
маркера

Устанавливает первое значение , с которого


FirstBu l letNumber ~
начнется нумерованныи список

Имеет значения HyperLink ,


L i nkButton , Te xt и определяет, во что
Display Mode
трансqюрмируется текст каждого элемента
(текст,2unерссылка)

• ~Добавьте к приложению новую страницу с совмещенным


кодом. Поместите на страницу элементы Label и
BulletedL i st . Н астройте свойства элементов в соответствии
с приведе нны м кодом.

<%@ Page Lапguagе= "С#" Аutо ЕvепtWirеuр=''truе'' %>

<script nшat= "sе rvег">


protected уою BuIletedListl_Click{object sепdег, ВuIlеtеdListЕvепtAгgs е)
(
Labell.Text = ВuIlеtеdList1.Itеms[е.lпdехJ.Техt;
)
</script>

<html xmlns ="httр ://www.wЗ.огgl 19 99/xhtml">


<head nmat="server">
< title > Uпtitled Page</tide>
<lhead >
<body>
< fопn ю ="fоrml " ruпаt= "sеrvег''>
<div>
Выбрано свой ств о:
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Выбрано свойство:
<asp:Labe! ID=''Labe!l '' ruпаt="sеrvег' '></аsр:LаЬе!>
< р />
< аsр:ВullеtеdList ID =''Вullеtеd Listl '' nшat="sеrvег"
BulletS tyle= "N шnЬегеd" DisрlaуМоdе=''LiпkВuttоп''
ОпСliсk= ' 'ВullеtеdListl Click''>
<asp :ListItem> N otSet</asp :ListItem>
<asp :ListItem> N umbered </asp:ListItem>
<asp :ListItem> Lower Alpha</asp :ListItem>
< asp :ListI tem> U р регAlp ha </asp :ListI tem>
<asp :ListItem> LowerRoman</asp :ListItem>
< asp :ListI tem> U р perRo man</asp :ListI tem>
<asp :ListItem> Disc </asp:Listltem>
< asp :ListI tem> С ircle </asp :Listl tem>
< asp :ListI tem> 5 quare</asp :Listl tem>
< asp :ListI tem> С ustomImage </asp :Listl tem>
</asp:BulletedList>
</div>
</form>
</body>
</html>

Листинг Код страницы примера в файле Bul letedLi st . aspx

Задав ДЛЯ списка атрибуг Dis play Mode= " LinkButton ", мы т ем
самым ВЮJючили на ЮJиенте постинг ДЛЯ каждого пункта с пи ска .

Р езул ьтат примера БУдет таким

,ее
П""'?'W"'~""'"" ASP.NET

Выбрано свойство: UpperRoтan

1. NotSet
2. NшnЬегеd
З. LowerA1IJha
4. UpperA1pha
5. LowerRoтan
6. UIJIJerR&тan
7. Disc
- -
8. Circ1e
9. Square
10. Custoтlтage

jаvasсфt:_, Local in1J" anet

Элементы проверки достоверно сти (валидаторы)

ОДН ОЙ и з важных задач НТМL~ дескр ип тора < f or m> является сбор и
передача данных у сво и х элементов управления. Часто Web-страницы
запрашивают у п ользователя какую-либо информацию, за т ем сохра н яют
ее во вспомо гател ьной базе да нн ых. Всегда нужно пр оверять введен н ую
пользователем информацию на предмет СQЦержан ия ошибок или
злонамеренного кода , которые мо гуг вызвать сбой в р аботе саЙта .

Существует три с посо ба про верки да нных поль зователя на


корректность:

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

1. Проверка да нны х на клие н те


2. Проверка данных на сервере
з. Проверка да нны х и на клиенте и на сервере

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


методов на языке сценариев JavaScript. Недостаток таких методов
состоит в том, что броузер кrlИента может не подцерживать JavaScript
или клие н т на мерен но ОТЮlючил в броузере эту подцержку для
безопасно сти . Таким образом, на ЮlИентскую проверку полагаться не
стоит, хотя она реализуется проще и выполняется быстрее.

Проверка на сервере не зависит от настроек Юlиента и ее выполнение


можно предусмотреть всегда. Недостаток такой проверки состоит в том ,
что данные пр ежде должны поступить на сервер , и только после этого

их можно проверять. При обнаружении некорректных данных их н ужно


отправить назад Юlиенту с сопроводительным предУПреждением. Такие
никчемные пересылки могуг повторяться м ного кратн о до тех по р, пока

мы н е дождемся корректных дан ны х. Э то может занять мно го времени.

Самым эфрективным будет реализация пр оверки и на Юlиенте и на


сервере. При таком способе , если на клие н те работает JavaScript, то при
обнаружении ОlШfбки обращение к серверу отсугствует и клиенту сразу
на месте выдается предупреждение. В случае , если JavaScript не
работает, то да нны е проверяются на сервере .

в VlSua l Studio 2005 на ВЮlадке Validation панели Toolbox содержится ряд


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

да нных, а именно

1. Requ i r edF i eldVal i dato r ко нтр олирует, не п уст ли


пр оверяемый элемент управления при отправке формы
2. Compa r eVa l idator - проверяет, соответствует ли значение
связанного элеме н та управления о пр еделенной операции
с р авнения (больше, меньше и т.д.) с другой констан то й
з. RangeValidato r контролирует, находится ли значение
связа нного элемента управления в задан но м диапазоне. Диапазон
может быть числом , датой или строкой
4. Regu l arE x p re ssionValidator - пр оверяет, соответствует
ли значение связанного элемента управления определе нному

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

регулярному выражению

S. Cus t omVal i dator позволяет определить собственную


логику проверки достоверности на JavaScript
б. ValidationSu mma r y отображает на странице или

всплывающем окне итоговую июlюрмацию с сообщениями о


найденных ошибках про верки достоверности

Эти валидаторы позволяют организовать проверку данных как на


кrJИентской стороне, так и на сервере. С их помощью можно
формировать сообщения об ошибках. Н екоторые элементы управления
можно проверить по содержимому свойства Value, которое является
скрытым атрибугом и в броуэере не отображается.

За каждым элементом управления можно закрепить несколько разных


валидаторов даже одного типа , наделив каждый из них своими
полномочиями.

Элемент RequiredFieldValidator

Самым простым валидатором является элемент


RequiredFieldVal i dator . Он проверяет, не является ли
связанный элемент п устым. Можно задать и пр едопределе нное
значение для проверЮ1 совпадения через свойство 1 ni tia l Val ие . В
этом случае проверка считается неудачной, если содержимое элементов
управления совпадает с 1 ni t i al Va l ие . Валuд аmар
RequiredFieldVal i dator связывается с проверяемым элементом

ч е рез свойство Соп


tr ol ToVal i da te .

Индиви дуал ьное сообщение об ошибке в валидаторе можно задать в


свойстве Te xt или разместить между открывающим и закрывающим
дескриптор ами валuдаmора. Наприм е р

<asp:TextBox ID='TextBoxl " гuпаt="sе rvег"></аsр:ТеxtВох>


<asp:ReqlliredFieklValidator ID='Val1" nmat= "server"
Co ntrorro Validate= ' TextВoxl " Width= ''2 1 7рх' '>
Запол ни те поле TextВoxl
</asp:RequiredFie ldValidator>

,СО
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

< Ьг />
<asp :TextBox ID='TextBox2 " гuпа t="sеrvег">< /аsр :TextBox>
<asp:ReqlliredFieklValidato r ID='Val2" nmat="server"
Co ntrofГo Valid a te='TextВox2" Width= ''2 1 7рх''
Техt= "З апол ни те п оле TextBox2" />

Есл и мы хотим вы дать сообще ния о всех ошибка х сраз у, то это делается
ч е рез элемент ValidationSumma r y , а предупреждение от текущего

вал uдаmора нужно записать в его свойство Er r orMessage .

Разместить элемент RequiredFie l dVal i dator можно в любом


месте стра ниц ы , гд е мы хотим ви деть сообщение об ошибке .
Использование отведе нн ого места дл я вывода сообщения об ошибке
опред еляется свойством Di splay вал uдаmора , которое может
принимать следующие значения:

• Dynami с - не за ни мать м е сто , если нет ошибки


• Stat i c - держать место н езависимо от ошибки (устан овлено по
умолчанию)
• None - валuдаmор есть , но место н е занимает и ошибки не
отображает, а скрытн о контролирует элемент управления для
элем е нта суммарных ошибок Val id a tionSumma r y

Ниже пр иведен пример , в котором вал uдаmоры


RequiredFieldVal i dator следят за за п ол н е ни ем текстовых

полей и предупреждают п ользователя . Вал uдаmоры различаются


значен и ем свойства Dis play.

<%@ Page Language="C#" AutoEventWireup=''true'' %>

<html xmlns=''httр ://www.wЗ.огgl 1 999/xhtml''>


<head nmat="server">
<title>Untitled Page</tide>
</head>
<body>
< fо пn ю ="fо rm l " runat="server''>
Фамилия:
<asp :TextBox ID='TextBoxl " гuпа t="sе rvег''></аsр :TextBox>
<asp:ReqlliredFieklValidator ID='Val1 " nmat="server"
'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Controrro Validate= 'TextBoxl " Техt="З аполните поле TextВoxl " Dis!=
!Оynашic!
< Ьг />
Имя:
<asp :TextBox ID='TextBox2 " runat="server''> </asp :TextBox>
<asp:ReqlliredFiek:lValidator ID='Val2" nшat= "sе rvег "
ControrroValidate='TextBox2" Техt="З аполните поле TextВox2" />
!Static!
< Ьг />
Отчество:
<asp :TextBox ID=' ТехtВохЗ " runat="server''> </asp :TextBox>
<asp:ReqlliredFieklValidator ID ='Vа lЗ" nшat="sе rvег"
Controrro Vаlidаtе= ' ТеxtВохЗ " Техt="З аполните поле ТехtВохЗ " Dis!=
!None!
< Ь г />
<aspButton ID="Buttonl " runat="server" Теxt='Заре гистрироваться" />
</form>
</body>
</html>

Листинг Применение валидаторов RequiredFieldValidator в


файле Validl.aspx

Страница с приведенным кодом ге н е рир ует на броузер следующий


результат

111 Untltled Page - MICrosoft Internet Explorer

Фawшия:: I Зшrошште поле TextВoxl !Dynamic!


Имя: I Зшrошште поле TextВox2 ! Static!
Отчество: rl------:::::O:· !None!
I Зарегистрироваться

1~i)~Dтe~======:::::'--------ГГГ~LОС3iltrа~t
Если исследовать поведение страницы, то можно сделать несколько
важных выводов:
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

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


текстовые поля и сообщений об этом нет.
• При нажатии кнопки инициации постинга против пустых полей
появляются предупреждающие сообще ния и форма не отсылается.
Это работает JavaScript, который сгенерировали валидаторы
страницы.

• Валидатор с атрибугом Di splay= " Dynaт i c " при скрытии


сообщения сразу освобождает место. Валидаторы с д ругими
значениями этого атрибуга ведУГ себя так, как говорил ось ранее.
• Кнопка обратной отсылки начинает действовать только тогда ,
когда все поля будУГ непустыми.

Попробуйте ОТЮlючить в своем броузере подцержку активных


сценариев. Для этого:

• Г;;:;=Выполните команду броузера Toolsllntemet Орtioпs ... Откроется


окно lntemet Options, в котором перейдите на вкладку Security

m
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET
--~.;......;...
Internet Options ? Х

Geners.1 Security IPri\tв.C'y' I Content I Соnnеctiоnз I Progrsms I АdV8Лсеd I


Select ~ WеЬ content zone (о specify its security setlings.

о о
Trusted sites Restricted
sites

Local intranet
This соnе conts.ins sll Web sites thst ше
Sitез ..
оп your org ~n iz~tion's intr~net.

Security level forthis шnе

Custom
Custom sеttingз.
- То chsnge the зеttingз с dick OJstom Level ~
- То use the recommended settings, click DefOO!l Level

Custom Level" Def ~uK Level

ОК OTMeH~ Применить

• ~ыделите на вкладке з ону Local intemet и щел кните на кн о пке


Custom Level
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Securitv Settings

Settings:

о Disable
o Enable
О Prompt
~ Userdata pers isterce
О DisablB

, o ЕnaЫв
S[фt~

~ A[ti\le s[ript~
О Disable
o
u
Enable
О Prompt
~ Allow paste operations \lia scфt
О Disable
o ЕnaЫе
О Promot

, "езе, cu,tom settlngs
"ese' 10 I M8dum-lоw _ R888
------"1 1

СЗхвl

• r;:;'в открывшемся окне отметьте n ереЮIючатель ScriptlnglActive


scriptlngIDisable , тем самым ОТЮIючится поддержка броузером
сценариев JavaScript

Теперь можно увидеть, что валuдаmоры срабаты вают только после


п остин га, по скол ьку обрабатыв аются н а сервере .

Есть общее булево статическое свойство Page . IsVal i d для


страницы. Если его значение равно tr ue , значит п роверка всех

вали даторов стра ниц ы nрОlШlа усnеllllЮ . Небольшой п ример


демонстрирует nрименение этого свойства страницы. В нем , если
п роверка n РОlШlа успешно, то пользователь регистрируется (услов н о).

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<%@ Page Lапguagе="С#" %>

<script nmat="server''>
protected void ЬtпRеgistег_Сlk:k(оЬjесt serкler, EventArgs е)
(
ЩР age.ls Valid)
{
11 Все введено, можно реrnстрировать
Labell.Text = "Вы зареrnст рир ованы";
Label1.ForeColor = Systеm.Dгаwiпg.со!ог.whitе;
Label1.BackColor = Systеm.Dгаwiпg.Со lor. Gгееп;
}
}
</script>

<html xmlпs=''httр ://www.wЗ.огgl1999/xhtml''>


<head nmat="server">
<title>Registered Page</title>
<lhead >
<body>
< fопn kl="fопnl" ruпаt="sеrvег''>
<div>
<asp:Labe! ID=''Labe!l '' ruпаt="sеrvег" Теxt=''Просим зареrnстриров
< Ьг 1>
First Name:
<asp:TextBox ID="tbFirst" nmat="server" 1>
<asp :ReqlliredFieklValidator ID= 'ReqlliredFieklValidatorl" nmat= "serve
ControfГo Validate= ''tbFirst'' Теxt=' 'Введите первое имя" 1>·
Last Nаше:&пЬsр;
<asp:TextBox ID="tbLast" nmat="server" 1>
< asp :Reqllired F ie kl Valida to r ID= 'Reqllired F ie kl Validato г2" nmat= "serve
ControfГo Validate=''tbLast'' Техt=''Введите второе имя" 1><
< Ьг 1>
<aspButton ID='ЪtпRе gistег" runat="server" ОпСliсk='ЪtпRеgistег_Сliс
</div>
</foпn>
<!body>
<lhtml>

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET
Листинг Пример ИСПОЛЬ90ваНИR свойства Page.IsValid в файле

IsValidTest.aspx

Элеме н т yn р авления Requi r edF i e l dVal i dator может

и спользоваться не только с текстовыми п олями , но и с д ругими

элемен тами ynравле ни я, например , CheckBo xL ist .


Chec k Bo x.
Rad i oBu t ton . Rad i oBu t tonL i s t , Dr opDownLi s t , L i s t Bo x .
Приведем пример ко нтр оля за выбором в с пи ске с при мен е ни ем
свойства 1 ni tial Val ие . БУдем и с п ользовать скрытый валuдаmор, а
его с игн ал БУдем пр оверять п о свойству Page . IsVal i d . Валuд аmор
будет уста н авливать это свойство в f alse (с игн ал ошибки) , если
н еотоб р ажаемый атрибуг Value выбранного пун кта списка сов п адет
п о значению со свойством 1 ni t i al Va l ие валuдаmора. Код стра ницы
с при мерам будет таким

<%@ Page L апguagе="С#" %>

<script nшat="sеrvег''>
protected void Buttonl_Ctick(object sender, EventArgs е)
(
if ('Page.lsValid)
(
11 С р абатыв ает при ОТЮlюченной подцержке JavaScript
11 в броузере. Инач е JavaScript на юш е н те
11 н е разрешает постинг. пока есть неправильный выбор
Labell .Text = "Э та опция запрещена!";
)
e~e
(
Label1 .Text = "Разр еше нный выбор!";
)
}
</script>

<html xm1пs=''httр ://www.wЗ.огgl 19 99/xhtml''>


<head nmat="server">
< title > List Valida te </title >
<lhead>
<body>

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

< fо пnid="forml " runat="server''>


<div>
<asp:Labe! ID=''Labe!l '' runat="server" Теxt=' 'Вы дели те опцию " />
< Ьг />
<asp:DropDownList ID=''DropDownList1 '' runat="server''>
<asp :Listltem Vа luе =' 'Н е вы д ел яемая ' '> Пус тышка </а s р :Listltem>
< а sр:L istltе m> Оnция 1 </asp:Listltem>
<asp :Listltem>O nция 2</asp:Listltem>
<asp :Listltem>O nция З</а s р:Listltе m>
</asp:DropDownList>
<asp :RequiredFieklValidato r ID='RequiredFieklValidatorl" runat= "serve
C ontrofГo Validate=''DropDownListl '' Display=''N опе " lnitia!Va!lle= "Н
< Ьг />
<aspBlltton ID='Buttonl " runat="server" Те xt="SllЬшit" OnC lk:k='Blltt(
</div>
</foпn>
</body>
</html>

Листинг Страница с примером в файле ListValidate.aspx

в последн ем при мере мы д олжны понима ть, что при ВЮJюч е нной н а
ЮJи е нте поддержке JavaScript nр едУЛ реж.цение об ошибке никогда не
будет выдано кодом страницы , п отому что п остинг броузером будет
заб локирован , п ока польз овател ь не сдел ает пр авильный выбор.
Обратите внимание н а н астройки в ал uдаmорй. О н не сможет выдать
те кстово е nр едynреж.це ние пользователю , по тому что мы сделали его

н еот об р ажаем ым ( Display= " None " ) и удалил и за ненадобностью


свойства-сообще ни я ErrorMessage и Te x t .

Элемент CompareValidator

Этот э лемент позволяет сравнивать введенное поль зо в ателем зн ачение


с этало нным з нач е ние м или срав нив ать тип вв еде нны х да нных с

за р а нее заданным типом. О н имеет следующие основные свойства

Основные свойства Sуs tеш.WеЬ.UI. WеЬ Сопtro/s.С ошр а геVаlidаtor

Свойство Описание
В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

ЭТО свойство контролирует ти п вводимого


значения в закрепл енное поле и может

принимать з начения :

• Currency - следит за соблюдением


ф:Jрмата денежного представления
Туре • Dа te - кон тролир ует ф:Jрмат даты
• Double - р азрешает только число с
плавающей то чкой
• In teger - ожидает ц елое число
• S t r ing - позволяет принимать любую
строку

Определяет, какую операцию сравнения


нужно вьшолнять. Подцерживает следУЮщие
операции сравнения:

• Equal - следит за соблюдением


равенства значений междУ
контролируемым полем ввода,
заданным в свойстве
Соп trol ToVal ida te , и эталонным
полем Соп trol ToCompare , либо
между Cont r o l ToVa l ida t e и

установленной константой, заданной в


Value ToCompare
• NotEqual - то же, что и Equal ,
только наоборот - следит, чтобы
соблюдалось неравенсmво
• Gr eate r Than - следит, чтобы
контролируемый ввод был больше, чем
в эталонном поле или установленной
константе

• GreaterThanEqua l - следит, чтобы


Opera tor контролируемый ввод был не меньше,
чем в эталонном п оле или

установленной константе

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• LessThan - следи т, чтобы


контролируемый ввод был меньше, чем
в этало нном поле или уста нов ленной
константе

• LessThanEqual - следи т, что бы


контролируемый ввод был н е больше,
ч ем в этало нном поле и ли

уста нов ленной константе


• DataTypeCheck - следи т, что бы тип
данны х в контролируемом вводе

совпадал с типом , определенным в

свойстве Туре . При установке этого


режима свойства
ControlToCompare и
Value ToCompare игнорирую тс я (в
данном случае важен формат данных, а
не и х з н аче ние)

Взаимоисключающие свойств а,
Control ToCompa re,
определяющи е либо эталонное поле
Va lue ToCompare
сравнения, л и бо ко н стан ту

Прив едем прим ер:

<%@ Page L апguagе="С#" %>

<script nmat="server''>

protected void Buttonl_Ctick(object sender, EventArgs е)


(
if (Page.lsValid)
(
Response .Write("<hl > З а каз прин ят! <lhl >'');
Buttonl .Enabled = false;
}
}
</script>

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<html xmlns=''httр ://www.wЗ.огgl1999/xhtml'' >


<head nmat="server">
< title > С ошраге Valid ator</title >
<lhead>
<body>
< fопn ю="fоrml" runat="server''>
<div>
<h2 >
Товар ''Ро га и копыта"< Ih2>
Им еется в наличии:
<aspTextBox ID='TextBoxl" runat="server" EnabIed=''False''> 25 </asp :
Сколько хотите заказать:
<aspTextBox ID='TextBox2" runat="server" I>< br 1>

<asp:RequiredFieklValidator ID='Val1 " nmat="selVer" ControrroValidatE


Display=''Dynamk:'' Техt=''Укажите количество товара" 1>

<asp:CompareValidator ID='Val2" runat="selVer" ControrroValidate=''Ji


Display=''Dynamk:'' Техt="Заполните прави льно поле заказа"
Type= '1nteger" Controrrocompare= 'TextВoxl" О perato r=''LessThar

<asp :Соmра ге Validator ID ='VаlЗ" runat= "selVer" Controrro Validate=''Ji


Display=''Dynamk:'' Техt="Заполните прави льно поле заказа"
УашеТоСоmраге=''О'' Орегаtог="GгеаtегТhaп" I>< br 1>

runat="selVer" Теxt="Отправить
< аsр:Вuttоп ID=''Вuttопl '' заказ"

OnClick='Buttonl Click" 1>


</div>
</form>
<!body>
<lhtml>

Листинг Пример использования валидатора CompareValidator в


файле CompareValidator.aspx

в п римере в поле Tex tBo xl указа н о имеющееся кол и чество товара.


Поле Text Bo xl является недоступным для редактирова ни я. За п олем
Te x tBo x2 закрепл е ны три валuдаmара:

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

1. Первый валидатор ( Vall ) следит, чтобы поле не было п устым


2. Второй валидатор ( Va12 ) контролирует, чтоб ы введенное
значение было цеЛО20 типа и было меньше или равно значению
п е рв ого поля

з. Третий валuдатор обеспечивает, чтобы введенное знач е ние было


больше н уля

Все валид аторы примера выводят сообщение в одно и то же место.


Если данные , введенны е поль зователем, Удовлетв о ряют установленным
критериям , то об р атн ая отсылка страницы прини мается , о ч ем
пользователю посылается и зве щение.

Элемент RangeValidator

Этот элемент подобен предыдущем у. В е го обязанность входить


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

в зада нном диапа зо н е. Диапазон может быть числом , датой и ли


строкой. Перепишем предыдущий пример , где вместо двух валидаторов
CompareValidator прим е ни м один RangeVal i dator .

<%@ Page Lапguagе= "С#" %>

<script nmat="server''>

protected void Button1_Clk:k(object sе пdег, Еvе пtAгgs е)


(
if (Page.lsValid)
(
Rеsро пsе . Write("<h1> Заказ принят! <1h1> '');
Button1.Enabled = false;
}
}
</script>

<html xmlns=''httр://www.wЗ.огgl 1 999/xhtml''>


<head id=''Неаd 1 '' nmat="server">
< title > С ошраге Valid ator</title >
в.м. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

</head >
<body>
< fопn id="forml " runat="server''>
<div>
<h2 >
Товар ' 'Ро га и копы та "< Ih2 >

Имеется в наличии:
<aspTextBox ID='TextBoxl " runat="server" EnabIed=''False '' Text= "25 '
Сколько хоти те заказать:
<aspTextBox ID='TextBox2 " runat="server" I><br 1>

<asp:RequiredFieklValidator ID='Val1 " nшat="sеrvег " ControrroValidatE


Display= ''Dynamk:'' Техt= ''Укажите количество товара " 1>

<asp:RangeValidator ID='Val2 " runat="server" Controrro Validate='Textl


Display= ''Dynamk:'' Техt="Заполните правильно поле заказа "
Type= '1nteger" MirllmumVarue="l " MaximumValue= "25 " I><br 1>

<aspButton ID= 'Buttonl" runat="server" Теxt= "Отп р авить заказ "

ОпСliсk =' 'ВuttопС С liсk '' 1>


</div>
< /foпn>
<lbody>
</html>

Ли стинг . Пример и с пользовании валидатора RanqeValidato r в


файле RanqeValidator.aspx

Элемент RegularExpressionValidator - пока пропустим!

Элемент Custom Validator - пока про пустим!

Элемент ValidationSummary - пока пропустим!


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Применение серверных элементов управления

Прим е р исследования жизненного ЦИЮJa страницы. Перехват событий


жизненного цикла страницы в обработчиках. Ди на ми ч еское добавление
элементов ynравления.

Серверные элементы управления можно добавлять к странице как


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

пользователя . Она анализирует постynившую инф:Jрмацию, генерирует


н еобходи мый код , отдает е го НТГР и автоматически выгружается из
памяти .

Такой порядок существования ст р аницы уста новл ен для экономии


ресурсов и масштабируелюсти (стремления обработать как можно
больше пользователей). Он называется жизненным циКIIОМ страницы .
Жизненный циКII страницы сопровождается рядом знаковых событий ,
для которых можно создать обработчиЮ1. Для ди намич еского
добавления элементов ynравления на страницу нужно знать, в
обработчике какого события страница готова принять свои дочерние
элементы.

Пример исследования жизненного цикла страницы

Давайте на практике исследУем порядок ген ераци и событий на


про тяжен ии жизненного ЦШU/Q страницы. Названия событий можно
получит ь даже из п устой .aspx -страницы, если включить трассировку в
испол няющей среде ASP.NET

• ~Создайте в выбранном каталоге п устой проект Web-


приложе ния LifeCyc!eEvents командой FilelNewlWeb Site оболочЮ1
Visua! Studio 2005
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

.1J~

..•
T...-rpl ..,... Гf! ;:;:

~ ~ ~
АЧ' r.ET \', 00 ASP J-ET W3!J ж-sma l Vloo
Sib SOfYEO Si'" stoc"" K~

• r;:;'в панели Solution Explorer (или в меню Website ) вызовите


контекстное меню для узла проекта и выполните команду Add
New ltem Настройте диалоговое окно мастера так
.1J~
T<><rpla>?> ri! ;:;:


l/ШIiIIIII
D
м.",..- Р"9"
[!j]
_ с_

ccrn-o l
00
КТf.1.. ""9"
!i
Web S• ..,~e
~
С ",,,
~
stj l< SCe" t

CiiJ
C~,

"«J 1 ~a~ ",


-
[}
crn~l;JJ a ~I ",
~
)(]VL F,", ХМ-
\JjJ
Schotm То"
~
Fil2
~
R о=л: .

.
Fi:"
ij
SQ.- о..:..ь=

1m
Dазset -~, ~
5Ite М"!)
1J]r"
с

M:N eVIOO
~
\'В5C r "" F(e
lf.jJ
,-,
~
J5CfjX ""
I-I.rd e.. ' ..m

rв::;" ~ -"'" ~ ф1 jjJ


I д form for Wob ц" ь""",

~W I Def<OJ lt<bpx

L~: I Vislя l С, iI ~ PliO:e с сОэ n "'1R ае fii3


Г Selea rrвstef IВ'J"

Обратите вниман и е, что мы добавляем страницу с отделенным

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

кодом (ВЮlючен флажок Р!асе code in separate fi]e ).


• ~Запустите добавленную стра ницу на выполнение щелчком на
кнопке Start Debugging.

Появится о кн о с предупреждающим сообщением, что для режи ма


отладки нужно создать канфигурацuонный файл Web.Config с
параметром ВЮlючения отладки

DеЬugglпg Not EnabIed .1J x


The Pag.:J carrot Ье run il ооЬщ modе because debuggilg is гюt enabled il lhe Web,crnf1g
file, what wo u(J ~ou Ii<:e to оо?

r- Act1 а new lNeb,crnf1g пе with deЬLЩiпg enctJled,

..n DeЬ uщ iпg Яlоu (J ье drsabled in Ihe W8b,crnf1g Ш:о before deplщilg the
W8b site to а prod..ctial ооугrnmепt,

r Rm wilhxit deb.Jggilg, (ECf-liузlепt to ClrI+F5)

• г;.:.=щелкните на кнопке ОК и оболочка создаст


конфигурационный файл в корневом каталоге пр оекта

Автом атически запустится встроенный броуэер с п устым


рен де рингом.

• ~Закрой те броуэер и вновь е го зап усти те кома н дой оболочки


FileNiew in Browser (или одноименной командой контекстн о го дл я
страницы меню)

в строке адреса броузе р а будет прим е рно следующий текст

ссылка: httр :l!lосаllюst :12 0бlLife Сус lеЕvепtslDеfauh . а s рх

• г;.:.=Замените в строке адреса броузера блок Default.aspx на


Trace.axd и ПОllИите запрос примерно с таким адресом

ссылка: httр :l!lосаllюst :12 0бlLife Сус lеЕvепtsfТга се. ахd

Сер вер выдаст сообщение об ошибке с предложением внести в


В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

конфuгурацuонный файл предлагаемый блок кода

< сопfigшаtiоп>
<system.web >
<trace enabled= ''true''/>
</system. web>
</соnfigшаtiоп>

• IJ$Скопируйте строку <trace enabled= " true " />


параметра , включающего трассировку страниц приложения , и

поместите ее в файл Web.Config проекта в секцию <system.web>,


где уже находи тся параметр <compilat i on
debug= " t r ue " /> , включающий отладку
• Г;:;=Запустите приложение и в строке адреса броузера вновь
введите вызов страницы Trace.axd

Появится страница трассировочных данных, в которой щелчком на


гиперссылке View Details (показать подробности) мы получим распечатку
трассировЮ1 нашей пустой страницы. В секции Тгасе Information
приведен список событий, генерируемых страницей на разных этапах
жизненного ЦШU/Q

Тгасе Iпfопrntiоп

Ргот
Category Message Ргоm First(s)
Last(s)
aspx.page Beg i n Pr eln i t
aspx.page End Prelni t 0,01754301175149360,017543
aspx.page Beg i n In i t 0,020 14781208226190,002605
aspx.page End Ini t 0,03765702065485980,017509
aspx.page Beg i n I nitComplete 0,0381149000780825 0,000458
aspx.page End In i t Complete 0,04003078603565540,001916
aspx.page Beg i n PreLoad 0,04203327517882860,002002
aspx.page End PreLoad 0,04339266582764010,001359
aspx.page Beg i n Load 0,0438189 76992886 0,000426
aspx.page End Load 0,04991751744984350,006099
aspx.page Beg i n LoadComplete 0,0503580762359462 0,000441
,ее
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

aspx.page End LoadComplete 0,05169120656396270,001333


aspx.page Beg i n PreRender 0,05257651461289070,000885
aspx.page End PreRender 0,0658033353401061 0,013227
Beg i n
aspx.page 0,06823520866478840,002432
PreRenderCo mple t e
aspx.page End PreRenderComplete 0,07015891684557670,001924
aspx.page Beg i n SaveState 0,164382065318358 0,094223
aspx.page End SaveState 0,39629729476791 0,231915
Beg i n
aspx.page 0,39674344085631 0,000446
SaveSta t eCo mple t e
aspx.page End SaveStateComplete 0,398069307691341 0,001326
aspx.page Beg i n Render 0,398760456985455 0,000691
aspx.page End Render 0,646856234521427 0,248096

Этот порядок следования события не меняется. Некоторые из них, пока


е ще страница способна прини мать управляющий код , можно
п ерехватить в обработчиках. Давайте для тренировки сделаем это.

Перехват событий жизненного цикла страницы в


обработчиках

• ~ змените код разметки страницы Defauh.aspx, чтобы он


выглядел так

<%@ Page Language="C#" AutoEventWireup=''true''


CodeFile= "Defauh. aspx.cs" Inherits="_Default" %>

<html xmIns='hup ://www.w3.or!j'1999/xhtml" >


<head runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form ю ="foгm1 " nmat="server''>
<div id="div1 " nmat="server">
<h1 align="center" style="co lor: Red ''>
Д иагностика со б ы тий стр а ницы < 1h1 >
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</div>
</fonn>
</body>
<lhtml>

Листинг . Разметочная часть страницы Default


• Г;;:;=Откройте файл отделенно го кода Defauh.aspx.cs и заполните
е го так

using System;

риыic рапial class _Defauh: System.Web.UI.Page


(
protected void Page_Load(object sепdег, ЕvепtAгgs е)
(
System. Diagпоstk: s . Debug. WriteLine(
"** ** ********Page_Load ** ** ** ** *'');
Resp о пsе. Write("P age _ Load < Ь г> \п '');
divl.lппегНtml += "Раgе_Lоаd < Ьг> \п ";
}

protected void Page_PreLoad(object sender, EventArgs е)


(
System. Diagпоstk: s . Debug. WriteLine(
"************Page_PreLoad*********'');
Respo пsе. Write("P age _ Рге Load < Ьг > \п'');
divl.lппегНtml += "Раgе_РгеLоаd < Ьг>\п";
}

protected void Раgе_Ргеlпit(оЬjесt se nder, EventArgs е)


(
System. Diagпоstk: s . Debug. WriteLine(
"** ** ********Page_Pre l пit* ** ** ** ** '');
Resp о пsе. О utp ut. Write Line("P age _ Р ге lпit < Ьг > '');
divl.lппегНtml += ' 'Раgе_Ргеlпit < Ьг > \п'';
}

protected void Раgе_lпit(оЬjесt sender, EventArgs е)


{

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

System Diagпоstk:s. Debug. Write Line(


"************Page_lnit*********'');
Resp о nsе. О utp ut. Write Line(''P age _ lnit<Ь г> '');
div1.lппегНtml += ''Раgе_lnit < Ь г>\п'';
}

protected void Page_PreRender(object se nder, EventArgs е)


(
System Diagпоstk: s . Debug. Write Line(
"** ** ********Page_Pre Render* ** ** ** ** '');
Resp о nsе. О utp ut. Write Line(''P age _ Р ге Rerкler < Ь г> '');
div1.lппегНtml += ' 'Раgе_РгеRепdег< Ь г> \п'';
}

protected void Page_Rerкler(object sender, EventArgs е)


(
System Diagпоstk: s . Debug. Write Line(
"************Page_Rerкler*********'');
Respo nsе. О utput. Write Line(''P age _ Rепdег < Ь г> '');
div1.lппегНtml += ' 'Раgе_Rепdег < Ьг>\n'';
}

protected void Page_ UnLoad(object sender, ЕvепtAгgs е)


(
System Diagпоstk: s . Debug. Write Line(
"** ** ********Page_ UnLoad******** *");
/lResponse .Output. WriteLine(''P age_ UnLoad < Ь г> ''); // По здно, уже
div1.lппегНtml += ''Page_UnLoad <br>'';// По езд ушел , выводим]
}
}

Листинг . Кодовая часть страницы Default

в каждый обработчик событий жизненного циКIIa ст раницы мы


включили т екстовы й вывод в три места:

1. В окно Output оболочки в режиме от ладки (вызывается командой


меню Vtew!Output
2. В генерируем ый отклик страницы впереди разметочной части

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

з. в разметочную ч асть страницы динами ч ески добавляем


инqюрмацию

• г;;;?Запустите страницу п од ynр авле ние м оболоч ки


сгенерируется следУЮЩИЙ рендеринг
Р.., у, ­
~"'"--'''
Р"""-",",-",,,
р.,,_Сood
~ . .. _P< , R , Мo ,

Диагностика событий стра ницы

Р'''''-'''-
Р ... _""
Р . .. _",,,• ..,
Р. .. _,-
POI"_"""" _

в окне Output оболо чки посл едние строки будyr такими

************ Р age_Pre lnit* ********

************ Р аgе_I пk*********


************ Page_PreLoad*********
************ Page_Load*********
************ Р age_PreRender* ** ******
************ Page_UnLoad*********

Ин терес но заметить , что код отладки и з готовой страницы уби р ать не


н ужно. Он автоматически не включается в компиляцию, если из
конфигурационного файла убрать пар аметр < compi 1 а t i оп
debug= " tru e " /> или выполнить стр аницу без отладки.

Стра ниц у без отл а дки мож но запустить напрямую , вызвав броузер
че р ез контекстное меню разметочной части стра ницы командой VIew in
Browser, или выполнив командУ оболочки DebuglStart Without Debugging
(выполнить без ВЮlючения отл а дки). В любом случае с р еда исполнения
AS P.NET п ерекомпил и рует страницу (если был и по след ни е изменения
в исходном коде по сравнению с DLL) и выполнит ее , направив
сгенерированный HTML-КОd броузеру.

Динамическое до бавление элементов управления

Приведем пример п рorрамм ного добавле ния элемен тов ynравления на


страницу.

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• ~ома н дой меню FilelNewlWeb Site создайте новый Web-проект


типа ASP.NET Web Site
• Г;;:;=Откройте файл Defauh.aspx.cs и заполните е го следУЮЩИМ
КОДОМ

usiпg System;
usiпg System.Data;
usiпg Systеm. Со пfigша tiоп;
usiпg System. Collections;
usiпg System. Web;
usiпg System.Web .Security;
usiпg System. Web.UI;
usiпg System. Web. UI. WebControls;
usiпg System.Web.UI.WebControls. WebParts;
usiпg System. Web.UI.HtmlControls;

public partial class _Defa uh: System.Web .UI.Page


(
11 Поля для видимости в методах
Labellbll , 1b12;
TextВox te xtВox;
Button Ьtn;

11 Свойств о для генерации тега <Ьг> < !Ь г>


protected HtmlGenericControl BR
(
get { геtшп new НtmlGепе гiсСопtго~ 'Ъг''); }
}

protected void Page_Load(object sender, EventArgs е)


(
Ibll = пеw L а Ь еЮ;
IbI2 = пеw L а Ь еЮ;
textВox = new TextBoxO;
11 Подписка на событие с реrnстрацией обработчика
textВox.TextCha nge d += new Eve ntНandle r(textВox_TextC hanged);
btn = new ButtonO;

fо nnl .Сопtrоls.Аdd(lbll );

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

10nnl.Сопtrоls.Аdd(ВR);
10 nnl. С о пtrо Is.Add(1b 12);
10nnl.Сопtrоls.Аdd(ВR);
fo пnl. С о пtrо Is.Add( textВo х);
10nnl.Сопtrоls.Аdd(ВR);
10 nnl. С о пtrо Is.Add(btn);
textВox.FocusO;

if (! this . I sPostВack)
(
11 Настройки при первом запросе,
11 далее сохраняемые в ViewState
Ibl1.Text:= ''Label'';
Ibl1.тооrпр = "Э то текстовая меткаl";
Ib12.Text:= ''Labe2'';
Ib12.тооrпр = "Э то текстовая метка2";
textВox.Style.Value := "color: red; foпt-stуlе: italic";
tехtВох.тооrпр = 'Это текстовое поле";
Ьtп.Техt = 'К нопка ";
Ьtп.ТооШр:= 'Э то кнопка Submit";
)
}

уою tеxtВох_ТеxtСhaпgеd(ОЬjесt sе пdег, ЕvепtAгgs е)


(
striпgstr := "< Ь > " + te xtВox.Text + "<!Ь > ";
lbl1.Text:= str;11 Интерпретируемый вывод
lb12.Text:= Нttрutilitу.НtmlEпсоdе( stг) ; II Неинтерпретируем ыЙ вывод
)
}

Ли стинг Динамическое до бавление элементов управления на


стра ницу

Для п риема да нны х и з н ен адежных источников все дескрипторы н ужно


превратить в обычные текстовые с и мволы. Для это го п риме н яются два
од инаковых метода

• Sys t em . Web . Ht t pUt i l it y . Ht mlE n code ( st rin g )


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. NET

• Sys t em . Web . U I. Page . Se r ver . HtmlEncode(st ri ng)

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Пользовательские элементы управления

Пользовательские элементы управле ния : создание, реrnстрация.


Порядок генерации событий инициализации. Добавление событий.
Доступ из кода Web-страницы к составным компонентам
пользовательско го элемен та управления. Ди на мическое создание
пользовательско го элемента управления. Преобразование ст р аницы в
пользовательский элемент управле ни я. Управление динамической
за грузкой многих пользовательских элементов управления (портальные
каркасы).

Файлы к лекции Вы можете скачать здесь скачать:

httр :l/оkl.iпtШ. ruld е р аrtmeпtliпtеmеtlр rasp пеtlБЮБ _ We bS Ке4. zip

Пользовательские элемен ты управления (user contro!) разрабатывает сам


прогр аммист в тех случаях, ко гда ста н дартные элемен ты управления его

не удовлетворяют или он разработал удачный вариант кода . Такой


элемент управления можно мно гокр атно использовать на мно ги х

страницах и последующие е го модернизации немедленно будyr


отображаться на всех страницах, где он и с пользуется. Часто
пользовательские элеме н ты управления применяются для

стандартизации (единообразия) интерфейса страниц , например ,


оф:Jрмления верхнего и нижнего колонтитулов.

Пользовательский элемен т управления представляет собой небольшую


часть страницы , которая может содержать статический HTML-кod и
стандартные элементы управления. В пользовательских элементах
управления можно предУсмотреть свои свойства , методы и события .
Пользовательские блоки кода MOryr многократно использоваться на
разных страницах, но только одн ого саЙ та. Для применения в другом
сайте е го либо нужно ско пировать в этот сайт, либо создавать
библиотечные специальные серверные элемен ты наподобие
стандартных ( custom server contro! ).

Файл пользовательского элемен та управления может содержать то же


самое, что и файл обычной исполнимой страницы, включая файл
п оддержки .cs, статический HTML -кod, стандартные элементы
управления. Они получают те же самые события , что и объект Page,
и меют доступ к таким важным объектам-свойствам, как Аррlkаtiоп,

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Session, Request, Response. Но есть и существенные отличия:

1. В отл и чие от страниц, файлы которых и меют р асширение .aspx,


пользовательские элеме н ты управлен и я должн ы хра ни ться в

файлах с расширен ием .ascx


2. Объект страницы п роизведен от масса Page , а объект
п ользовательского элемента управления производится от масса

UserControl . Но учи тывая, что оба масса


( Page и
Use r Con r o l ) наследУЮТ масс Temp l ateControl . они
п ри обретают много один аковых свойств и событий от этого
масса

ObJect Browser
Browse: .NEТ Framework ... ,.. I
System.WebUITempo.teConb"d •
EJ ..·'I$ System.WebUITempo.teConb"d
Base Types
Derived Types
",'1$ Page
8 '1$ UserCoob"ol

з. Среда исполнения не может напрямую вызвать файл .ascx, а


должн а это делать через .aspx, в который внедряется ссылка на
файл .ascx
4. Файл пользовательского элемен та управления не является
отдельной ст р аницей, поэтому н е должен содержать дескрипторы
<htm l > , <head> , <body> , <form>
s. Вместо директивы @Page файл пользовательского элемен та
управления соде р жит директиву @ Сопио!

Среда проектирования п озволяет видеть внедренный в страницу


п ользовательский элеме н т управлен и я на пове р хности конструкто р а
Design страницы.

Создани е пр остого пользовательского элеме нта

уп р авления
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Рассмотрим эту задачу на при мере. Заготовку поль зовательского


элемента ynравления легко создает мастер среды п роектирования .

Создадим пользовательский элеме нт ynравления , который будет


п редставлять собой про сто й верхний колонтитул стра ницы и состоять
и з статического НТМL-текста .

• г;:;=в,ыполните командУ Website/Add New ltещ выберите шаблон


Web User Сопtrо! и задайте имя Header.ascx

Add Ne\·, Item - C:\Chalr\Book\WEB\ASPJ\JET 2.0\Examples WebSlte4\ .1J~


Terrp~tes : 111 "
е -~

1'100 Fe< m
D
Мао"" Р"'9" •
l1li
1!1
н тм.. Р"'9" 1'100
~
_Y O: ~
~
C~,
~
sty k> ShGot

с <ы
~ iЭ
"оо
~
хм.. Fi" хи..
tm Schema
li1
Text Fi"
!IJI
Pescиce Fi "
IJ
SQ.. Database
"W1o:atL " Crnfg.xati",

tm -~, ~ шf· ~ ~ ~
DataSet
~ff
Si l9~ ~ i "Web
Fe<m
VВScr"t Fi "
"-' JScr " t Fi"

ri=\;" g' ,811 1,;; Ф .1 R1


IAn дsp , f.EТ ""по<" crntro l crected """'9 1he viou.:> l deogoer

Name : IНeader ,asc,


L~: IVisual С, iJ р" Росе [ ode n sEp<f"ate fi"
Г 58 ее! m.ster рзgе

Посмотрите , что создал мастер. Файл .ascx содерж ит только одну строку
директивы

<%@ Control Lапguagе="С#" АutоЕvепtWirе uр=''truе'' CodeFile="Header.asc:

Пользовательский элеме нт ynравления редактируется в оболо ч ке точн о


также, как и обычная ст р аница. Файл поддержки .ascx.cs содержит тот
же код, что и для обыч н ой страницы . В данном п римере он нам не
н уже н , поэ тому ничего в нем делать не БУдем (п усть болтается п устой) .

• ~ оместите в фай л Header.ascx следУЮЩУЮ НТМL- разметку


,ОС
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<table width="100%" border=''O'' Ьgсоlог= ' Ъ!uе ">


<tr>
<td >
<font face ='Vernada, Arial" size="б" color= ''yellow''>
< Ь > Тестовая страница User Control<lb>
</font> </td>
</tr>
<tr>
<td align=''right''>
<font size='З" color=''white''>
< Ь > Время создания: март 2007 г. &сору; Все права защищены < lb;
</font> </td>
</tr>
</tab)e>

Листинг НТМL - ход файла Header.ascx

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

Тестовая страница User Соп!го!


..
-""""'_ ",,"', "' ............ --
Регистрация пользовательского элемента на странице

Продолжим рассмотрение наше го при мера. Поско льку )ФД

пользовательского элемента ynравления предполагает его

использование в страницах, то преж.це всего создадим тестовую

страницу.

• Г;:;=Создайте новую страницу с именем HeaderTest. aspx для


внедрения в нее пользовательского элемента ynравления

Чтобы использовать элемент ynравления на странице, нужно


интегрировать его в ф:Jрму. Для этого нужно выполнить следующие
шаrn:

1. Зарегистрировать элемент на странице, т.е. с помощью


директивы @Register, помещенной в начале страницы, нужно
сообщить ASP.NET, что где-то на странице есть ссылка на
пользов ател ьский элемент ynравления.

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

2. Поместить пользовательский элемен т управлени я на страницу,


вставив в нужно е место внyrри дескриптора < f or m> ссылку-те г
на этот элеме н т.

Д ир ектива @Register для нашего примера имеет следующий ви д

<%@ Register TagPrefix= ''myElem'' ТаgNаme= ' 'Неаdег'' Sгс=''Неаdег.аsсх'' %;

Мы знаем, что для р азличен и я ста н дартных элем е нтов управлен и я в


нач але их дескрип торно го пр едставления используется конструкция

< преФи к с : т ип эле м ента а т рибу т ы . 1> , например

<asp:TextBox ID='TextBoxl" гuпаt="sеrvег" />

Здесь азр играет роль префикса TagPre f i x (и ли условного


пр остранства имен), а Te xt Bo x - тип элем е н та уп р авле ния TagName .
Д ир ектива р е гистра ции также для лучше го ра зли чения
п ользовательских элементов управлени я подцерживает одинаковый
синтаксис . З начения myElem и Heade r мы задал и произвольно , но
далее эти значе ния на странице мы д олжны строго соблюдать, а
з нач ен ие атр ибyrа S r c ( So urce - источ ни к) означ ает ПОДЮlючаемый
файл с пользовател ьским элеме н том уп р авления.

в зарегистрироваННblХ обозначе ни ях п ользовательского элемен та


управления синтаксис е го ПОДЮJючения к ст р анице HeaderTest.aspx будет
таким (н у, как обычно ! ):

< mуЕlem :Неаdег ID=''Неаdе гl '' nmat="server" ></myElem:Header>

и ли таким

< mуЕlem:Неаdег ID=''Неаdе гl '' nmat="server" />

в Visual Studio 2005 нам не н уж но руками ПР О П ИСblвать приведенную


регистрацию. Достаточн о в окне Sоlutiоп Exp lorer п еренести в н едряемый
файл Head er. ascx в нужное место страницы и подправить , пр и
н еобходи мости , сгенерированную оболочкой регистрацию.

в резул ьтате п ользовательская страница HeaderTest.aspx до лжна иметь


такую НТМL- ра зметку

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<%@ Page AutoEventWireup=''true'' CodeFile='HeaderTest. aspx.cs" lnherits="


Language="C#" %>
<%@ Register TagPrefix= ''myElem'' TagName= 'Header" Src='Header.ascx" %;

<html xmlns="httр ://www.wЗ.огgl1999/xhtml">


<head nmat="server">
<title>TecT элемента user control</tide>
<lhead>
<body>
< fо пn id="forml" runat="server''>
<div>
< mуЕlem:Неаdег ID='Headerl " nmat="server" 1>
</div>
</foпn>
<!body>
<lhtml>

Листинг НТМL - ход файла HeaderTest.ascx

Вот таким образом к стран иц е подключа ется файл , в котором


соде р жи тся внешний частичный код. Этот код реально может бы ть
любой сложно сти , ВЮlючая все мыслимые элементы ynравления.
Обратите вниман и е, что код файла Head er. ascx не соде р жи т ссылок на
другие страни цы и готов использоваться на любой стран иц е как
допол н ение. С другой стороны, на файл п ользовательского элемен та, в
свою очередь, может быть помещен другой пользовательский элемент,
разработанный ранее. В таком случае этот ПОДЮlюч аемый элемен т
н ужно заре ги стр ир овать на родителе точно так же, как это делается пр и

п одключе нии к коне чн ой страни ц е .

• ~Запустите тестовую страницу на вы п олнение , должен


получиться такой результат

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

'!i ТССТ ~лсмеltТа user control Мicтosofl Intcrnct [~plorcr ::::::::=- ____~~-ID I ~
----


Тестовая страница User Control
ВР!;'J\lЯ о.:U~Д<lНИЯ: МЩП 20071 ~ В(!;' IIp<lB<I j<lЩИЩ!;'НЫ

Добавление кода в пользовательский элемент

управления

в пр едьщущем примере мы н е использовали код файла поддержки, хотя


и создали его. Но чаще всего это н ужно делать, чтобы добавить
функциональность, которая может понадобиться ЮlИенту. Как это
делать, рассмотрим на прос тых примерах.

Обработка событий

Для начала воспользуемся стандартным элементом управления


Lin kBu t t on , который будет снимать с таймера сервера и отображать
клиенту текущее время. Для разнообразия код С# и разметку поместим в
одном файле.

• ~ызовите мастер для создания пользовательско го элемента


управления, выполнив команду Website/Add New Item. Установи те
ша бло н в значение Web User Co ntro~ сбросьте фrыжок Рlaсе code in
separate Ше и задайте имя файла ТImeDisplay.ascx
• ~ оместите в редактор Design стандартный элеме н т управления
LinkButton из вкладки Standard
• r;.:.=через пан ель Properties измените ID элемента на !nkТШlе
• IJ$Двойным щелчком на свободном месте редактора Design
создайте обработчик Page Load ()
• u;.;rп ри выделенном элементе lnkT i me установите панель
Properties в режим Events (кно пка с и зображением молнии вверху
панели), найдите событие Click и двойным щелчком на поле его
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

значе н ия создайте об р аботчик


1 n kT l me С 1i сk ()
• Г;;:;=Заполните файл следующим кодом

<%@ Control Language="C#" C lassN ame='TuneDisplay" %>

<script nшat="sе rvег''>

protected vo id Page_Load(object sender, EventArgs е)


{
Rе frеs hТпnео ;
}

protected vo id InkТпnе_С liс k(о Ьjе сt sender, EventArgs е)


{
Rе frеs hТпnео ;
}

public void Rе frеs hТпnе О


(
InkТпnе. Техt = DateTune .N o w. ToLongТnneString( ) ;
}
</script>

<asp:LinkButton ID=''lnkTune'' runat="server" ОпС liс k =' 'lnkТпnе_С liс k '' 1>

Листинг Код файла TimeDisplay.ascx

в коде мы добавил и свою функцию RefreshT i me () , п оскольку ее код


н ужн о вызыват ь в двух местах. Без этой функц и и вполне можно
обойтис ь , но мы п редставили себе, будто ее тело состоит из болы.lюоo
количества строк

• ~тобы протестировать наш код, добавьте к приложению новую


страницу с и менем TuneDisplayTest.aspx
• Г;:;=Перетащите на нее из п ан ели Solutlon Ехрюгег файл
ТпnеDisрlaу.аsсх с п ол ьзовательсЮ1М элементом управле ни я
• ~ыполните ст р аницу, кото р ая н а юш ен те бу,цет такой

т,
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

17:32:39

При каждом щелчке пользователя на ссылке-кнопке она будет снимать


(и отоб р ажать) с таймера серве р а н овое з нач ение времени.

Понятие свойства класса

Свойство, это специальн ый чле н класса С#, который управляет


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

• типа , равного типу п оля , доступом к которому оно управляет

• из им е ни с модификаторам доступа , п о которому бу,цуг ч и таться


или писаться знач е ни я п оля , контролируемые свойством
• из пары аксессоров get и se t, содержащих кон трол ирующий
поле код

Основное досто ин ство свойства состоит в том , что его можно


ис пользовать в вы р ажениях и инструкциях при сва ив ания как обыч н ую
п еременную-член класса , хотя на самом деле здесь автоматически будуг
вызываться get - и set - аксессоры. Си н такис свойства таков:

модификатор.....Доступа ти п имя_свойства
(
get
(
11 код аксессо р а чт е ния поля

",
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

гешm поле;

}
set
{
11 код акс есс ор а записи поля

поле := value;
}
}

П усть, н а при мер, пер еме нной x F i eld целого типа тр ебуетс я
обеспечить ко нтролир ую щий доступ с помощью свойства с и мен ем х,
которому в пр о грамме можно при св аивать тол ько н еотр и ц ат ель ны е

чи сла. То гда простейший код свойства можно за пи сать так

class М УС Iass
{
public MyClassO
{
xField = О;
}

private iпt xField; 11 ЭТО поле будет управляться свойством х

1/ Э Т О свойство подцерж ив ает доступ к закр ытом у полю xField


// чер ез имя доступа х, равное им е ни с вой ств а
// Для юшен та это го Юlасса х видна как переменная
public iпt х
{
get
{
гешm xField;
}
set
{
1/ П е рем е нная value - зар езерв ир ованн ое имя переменной
1/ обобщенного типа , прини маю щей значение от Юlиента
1/ Э Т О имя менять н ельзя
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Щуа!ие >= О)
xField = value;
}
}
}

Теперь клиент класса БУдет ви деть только перем е нную х, но при


присваивании ей з начения эта операция БУдет контролироваться кодом ,
следящим за т ем, чтобы присваемые значения были неотрицательными.

Добавление свойств

Вернемся к нашей т еме р аз р аботки пользовательского элемента


управления. РасlШfРИМ возможности пред ы дуще го при мера. Добавим в
код общедоступное свойство Forma t , которому в клиен те
(использующая элемент страница) будем п ередавать либо п устую строку,
либо строку qюрматирования. В зависимости от этого по льзо ват ельский
элемент управления БУдет способен отображать надпись н а кнопке
Lin kBu t t on в разных qюрматах.

• ~ змените код файла ТпnеDisрlaу.аsсх следующим образом

<%@ Сопио! Language="C#" ClassName=''xx'' %>

<script runat= "server''>

protected void Page_Load(object sепdег, ЕvепtAгgs е)


{
Refгe shTllI1I'O;
}

private striпg fопrnt; // Контролируемое свойством поле


риыic striпg Fопrnt // Определение свойства Fопnat
{
get { геturп fопnat; }
set { format = уа!ие ; }
}

",
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

protected void lnkTnne_ Clic k(object sender, EventArgs е)


{
RefгeshTllI1I'O;
}

риыic void RefreshTnneO


{
~ (югта. == ''')
lnkTune.Text = DateTune.Now.ToLongТuneStringO;
else // З н ач ени е fопnat задаем в кrJИенте чер ез свойство Рогта
lnkTune.Text = DateTune.Now.ToString(format);
}
</script>

<asp:LinkButton ID ="lnkТlП1е " runat="server" OnClick ="lnkТIme_Click " /

Листинг. Улучшенный код файла TimeDisplay.ascx


• ~ змените КОД тестовой страницы TuneDisplayTest.aspx
следУЮЩИМ образом

<%@ Page Language="C#" %>

<%@ Register Sгс =' ТпnеDisрlaу.а sсх " TagName='TmleDisplay" TagPref

<h.m1 xmIns= . huр ://www. wЗ.ог&.1999/xh.m1.. >


<head runat= "server''>
< tidе > Стран ица TnneDisplayTest</title>
<lhead>
<body>
<form id ="forml " nшat="sе rvег ''>
<div>
< исl :TuneDisplay ID='TnneDisplayl "
runat="server"
Format= "" />
< Ьг />
< Ьг />
<hr />
< Ьг />
< исl TnneDisplay ID='TnneDisplay2 "
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

гuпаt= "sеrvе г"


Fоrmat="С его.цня dddd, dd ММММ уууу< Ьг I> Текущее вр(
</div>
</fonn>
<lbody>
<lhtml>

Листинг. Код тестовой страницы TimeDisplayTest.aspx

Тестовая стра ница является кrJИентом п ользовательско го элемен та


ynравления. Им ен но в дескрипторе элеме н та на ЮJИенте мы
определяем значе ни е доб авленного свойства For ma t как атрибyr этого
дескриптора. Обратите внимание, что в подсказч ике кода IntelliSense,
при ме н яемом п ри редактировани и дескриптора пользов ательского
элемен та ynравления, появилось новое свойство Forma t .

Представление тестовой страницы с пользовательским элемен том


ynравления на броузере ЮJИента БУдет вы глядеть так

22:06:57

Сегодня воскресенье, 18 марта 2007


Текущее время 22:06:57
[11 Оопе [П г ~ Loca injyanet

Здесь создаются два экзем п ляра элеме нта ynравления Ti meD i splay,
первый из которых отображает дату в ф:Jрмате п о умолчанию , а друго й -
в задан ном ф:Jрмате.

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Порядок генерации событий инициализации

При создании пользовательских элементов ynравления и добавления в


них своих свойств важно знать, в каком порядке происходит создание и
шшцuалuзацuя объектов на странице, использующей по льзо вательский
элемент ynравл е ния. Этот порядок следующий:

1. Производится Удаленн ый запрос страницы и она загружается в


память сервера

2. Создается и инициализируется конструкторам масса

по льзовател ьский элемент ynравления


з. Присваиваются значения атрибугов , предусмотренные в

дескрипторе пользовательского элем е нта ynравления


4. Создается объект род ительской страницы
S. Выполняется событие Page . Load родительской страницы, в
обработчике Page Load () которого можно предусмотреть
п е реназначение атрибугов-свойств пользовательского элемента
ynравления

б. Выполняется событие Page . Load пользовательского элемента


ynравления

Отсюда важный вывод, что если мы БУдем инициализировать


пользовательский элем е нт ynравления в его обработчике
Page L oad () , ТО он перезапишет все свои настройки , выполненные
в родительском коде , поскольку срабатывает по следним . Так, если бы в
послед н ем примере обработчик Page Load () пользовательского
элемента ynравления инициализировал поле f o rm at и имел бы вид

protected void Page_Load(object sender, EventArgs е)


(
format = о п ,;
if (!Page.lsPostВack)
RеfrеshТпnео;
)

ТО мы бы всегда получали результат варианта без qюрматирования , а


именно

",
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

23:25:40

23:25:40

I iп1Тю еt ~
AJ

Применение дополнитель ных классов при создании


сложных п ользовательски х элеме нтов управле ния

Ин огда п риходится создавать специальные классы для орган изации


взаимодейств и я между nользовательсЮ1М элемен том yn р авления и Web-
страницей. Рассмотр и м п ример , в котором создадим сложный
n ользовательсЮ1Й элемен т ynравления L i n kTable , п редназначенный
для генерирования набора ги n ерссылок в форматированной таблице .
Для удобства часть кода размести м в отдельн ом самостоятельном классе
Lin kTableltem .

• Г;:;=Создайте страницу Web Form с раздельн ым кодом и имен ем


LinkTableTest.aspx
• ~Сделайте эту страни цу стартовой
• г;.:.='Добавьте к n роекту новую папку с зарезервированным имен ем
App_Code

",
C:\ ... \WebSite4\
~ Build Web ~te
PubIish Web ~te

ill Add New Item ...


D Add ЕХlStJпg Item ...
New FoIder
Вп Add ASP.NEТ Fdder ~ I
Add Reference".
Арр _ GlobalResources Add Web Reference.,.

Арр _LocalResources G. View Class Diagгam


App_WebReferences biii Сору Web ~te
App_Вrowsers Start ОрООns."
ТПете [!l View in Bгowser
Browse With,,,
[!!] RefГesh Folder

~ CUt

Сору

Paste
§I Property Pages

• ~ерез кон текстное меню на созда нн ой п ап ке выполни те


командУ Add N ew Item

",
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

в .1"=-- - - - - - - - - '1
Add Existing Item".

В··, New F~der

View Class Diзgгат

R e~esh F~der

Cut

Сору

Paste

'Х Delete
Rеn.зmе

• ~ ерез окно маст е р а добавьте к п р и ложе н и ю нов ый класс С# с


име н ем LinkTable 1 tem . с s

,,,
В.М. СН"",,,В Про,раммupoвtJNШ' NQ ASP.NET

.1J~
ri! о:::


T""l""»>

~ !;]J ..;
[!jJ ~
IШII Тех! f ile D<Ot1oS,t

"- е:,,, D"Ч,m

Этот масс в своих полях бу,цет хран и ть информацию ,


необходимую пользовательскому элементу уп р авления, а через
свойства осуществлять доступ к ней .
• u;.;rЗаполните вс п омогательн ый масс в файле
Lin kT able 1 tem . cs следУЮЩИМ кодом

using System;
using System. Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebContro ls;
using System.Web.UI.WebContro ls.WebParts;
using System.Web.UI.HtmJControls;

/// <summary>
/// Вспомогательный масс LinkTableItem
/// </summary>
public class LinkTabIeI tem
{
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

// Хранимые поля закр ы того ти па


private string text, ur!;

// Конструктор по умолчанию
риыic LinkTable Item()
{
// Пустой ко нстр уктор по умолчан ию обязателен
// поскольку есть общий конструктор
}

// Общий конструктор
public LinkTabIe Item(string text, string ur!)
{
// Внугренним полям присваив аются з начения ,
// переданные и з родительского объекта
this.text == text;
this.ur! == ur!;
}

// Определение свойств доступа к внугренним полям


public string Text
{
get { return text; }
set { text == value; }
}

public string Ur!


{
get { return ur!; }
set { ur! = value; }
}
}

Листинг. Код файла App_Code/LinkTableItem . cs

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


упра в лять э ти м в с п омо гательн ы м массом .

• ~Создайте за го товку п ользо в ательского элемен та уп равле ни я с


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

р аздельн ым кодом и им е н ем LinkTable. Для этого выполните


командУ Add N ew ltem, вызвав кон текстное меню для узла п роекга
(самый верхний узел) в пан ели Sо!utiоп Ехрloгег и устан овив
шабло н Web User Со пtго !
------.11~
T...-rpl~""

lliJ

~
с _,
~C

Vlю Fa m

ДPP l t,~",
D

-
§ -
М38:В- Р ",?,

C001:g..<"'i.. ,
l1li

~
_о .
~
НТf<\. Р ",?,

liJj
Xf<\. Schetm

~

~
Sff, t e

Те х ' f ie
~
("'8'

~
Rеюcrcе г1е SQ.-
~
,-
Щle 5Сев!

[j
С<озь.> ",

11!J ~ ~ 111f' i ~ ~
D,bSot -,
~.
Siw М"I' ~,A:blQ щоо

l,'В3cr ipl: FIQ
00

"-, JScrp ' Fi"

liI=
~
gi" ,001 Rt ~ f!.J
Iм ~SP , I.ET _yвr (00.-0 1crе,Зd us r __ 1tJe ,~ш l ms от'"
~~ "I'-;;~"
'''·'''-------------------C,

CI'-;;~~·C"",------:iJ" го' PllIce code n "Р"'* fi e


г ~ ~ 7I3$ter p3~e

• r;:;n оместите в таблицу пользовательско го элемента следующие


стан дартны е компоненты:

о ТаЫе из вюыДки НТМL, который будет форматировать


размещение стандартных элементов управле ни я

о Label из вкладки S tа пdагd в верхнюю ячейку таб ли цы ,


который будет определять заголовок н абора ссылок
о Iтage из вкладки НТМL, определяющий р и сунок марке р а
ссылок

о Da taLi s t и з вкладки Data в нижнюю ячейку таблицы


о Hype rLink из вкладки Standard
• ~ астройте дескрипторный код пользовательского элемен та
управления так

<%@ Со пtго l Lапguagе="С#" АutоЕvепtWirеuр= ' 'truе '' CodeFile="LinkTabIe.a


Iпhег its=''LinkТа Ь!е '' %>

<tab!e border="l" cellpadding=''2'' cellspacing=''O'' width="lOO%''>


ш
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<tr>
<td>
<asp:Labe! ID= ' 'lbrПtle'' runat="selVer"
F orеСо!ог= ''#С ООООО'' F ont- Bok:l=''true''
F ont- N ames= 'Vemada" F о п!: - 5 ize=''Small''>
< !--Здесь будет за головок-- >
</asp:Labe!>
</td>
</tr>
<tr>
<td>
<asp:DataList ID="listCo ntent" runat="server">
<ltemTemplate>
<img width=''25'' hеight="lЗ" src=''Yes.gif' a!t="MapKep''>
< аsр:НурегL ink I D=''НурегLiпk1 " runat="server"
NavigateUr!='<%# Dа tаВindег.ЕvаI(Сопtаine г. Dаta l tещ 'Ur!'') (
Text=' <%# DаtaВindег.ЕvаI(Со пtаinег.Dа tа l tещ 'Text'') %>' 1>
< lItеmТеmр1з tе >
</asp:DataList>
</td>
</tr>
</tab)e>

Ли с тинг Код фа йла Link Table . a scx

Дескриптор <i mg> дл я кра с оты о п ределяет маркер , котор ы й вы


можете сами и з готовит ь р а змером 25хlЗ и л и взять из да нн ой р а боты
(файл Yes .gif, который и меет и зображен и er;$). Атри буг аl t задает
альтер н а ти вную н адп ись в п оле рисун ка , есл и последни й не будет
н айде н .

Те п е рь П Р ИlШlа пора р а сширить функцио н ал ьность п оль зов ател ьского


эл ем ен та управл е н ия LinkTable . Для этого

• ~ызовите на реда ктирова н и е файл LinkTable.ascx.cs и


за п ол ни те его сл едующим кодом

usiпg System;
usiпg System.Data;

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

us iпg Systеm. С опfigша tiоп;


us iпg System. Collections;
us iпg System.Web ;
us iпg System. Web.Security;
us iпg System. Web.UI;
us iпg System. Web.UI.WebControls;
us iпg System. Web. UI. WebControls. WebParts;
us iпg System. Web. UI. HtmlContro ls;

public partial class LinkTable : System.Web.UI.UserControl


(
public string Tlt1e
(
get { геtшп Ibmde .Text; }
set { lbmtle.Text = value; }
}

private LinkTableItem{J items;


public LinkTableItem[] Items
(
get { геtшп items; }
set
(
items = value;

11 Обновляем сетку
listСопtепt.DаtaSошсе = items;
listCo ntent.DataBindO;
)
}
}

Листинг Код фала LinkTable. ascx. cs пользовательского

элемента управления

Разработка пользовательского элемента управления закончена. Теперь


нужно поместить его на пользовательскую тестовую страницу

LinkTableTest.aspx, которую мы создали в самом начале выполнения


этого примера и сделали ее стартовой.

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• ~ыполнит е кома н ду Window/C lose All Documents, чтобы


закрыть все окна р едактирования

• Г;;:;=Откройте через панель Solution Explorer н а редактирование


файл LinkTableTest.aspx в режиме Design и п еретащите н а форму из
этой п а н ели узел LinkTable.ascx пользовательско го элемен та
уп р авления

После этого форма ст р аницы должн а выглядеть так

l,r[inkTabIeTest,aspx j

r,;.;r Databound
[;.;i'" D шаЬ оun d
~ Databound
[;.;i'" D шаЬ о un d
~ Databound

Дескрипторное п редставление тестовой страницы с


зарегистрированным на ней пользовательским элементом управления
имеет такой в и д

<%@ Page L апguagе="С#" АutоЕvепtWirеuр=''truе''


С ode F ile= "LiпkТаЬ leTest. asp х . cs" Inherits= ' 1.iпkТаЫе Test" %>

<%@ Register S гс ="LiпkТаblе. аsсх" TagName='1.inkTable" TagPrefix="ucl" %

<html xm1пs="httр:llwww.wЗ.огgl1999/xhtml">
<head nmat="server">
< title >Тестовая страница сложного элеме н та ynравления </tit1e>
</head>
<body>
< fопn id="fопnl" ruпаt="sеrvег' '>
<div>
< uсl:LiпkТаЫе ID='1.iпkТаblеl" runat="server" 1>
</div>
</foпn>
<!body>

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</html>

Листинг Дескрипторное представление тестовой страницы


LiпkТаblеТеst.аsрх

• г;.:.=ОткроЙте на редактирование файл п одцержки: страницы


LinkTableTest.aspx.cs и за полните его следующим кодом

using System;
using System.Data;
using Systеm. Со пfigша tiоп;
using System. Collections;
using System.Web;
using System. Web.Security;
using System. Web.UI;
using System. Web.UI.WebControls;
using System. Web. UI. WebControls. WebParts;
using System. Web. UI. HtmlControls;

public partial class LinkTableTest: System.Web.UI.Page


(
protected void Page_Load(object sender, EventArgs е)
(
// Формируем заголовок списка
LinkTab lel .Тide = "Список жизненно важных гиперссылок";

// Создаем список элементов - гиперссылок


LinkTableItem[] items = new Linkтаыetеm[з ];;
items[O] = new LinkТаblеItеm("Ссылка Nq l к Большому Биллу",
•.http://www.mk:roso ft. со т');
items[l] = new LinkТаblеItеm("Ссылка Nq2 к автошколе \"Диало г-СеРЕ
·.http://www.dialog-service.net·.) ;
items[2] = new LinkТаblеItеm("Ссылка NqЗ к затыч ке JavaScript",
'1avascript:void(O)');
LinkTablel.Items = items;
}
}

Листинг Файл LinkTableTest.aspx.cs поддержки тестовой


страницы

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• ~Запустите приложе н ие и убедитесь, что ге н ерируемый


пользовательским элеме н том управле ни я набор гиперссылок
р аботает исправно

ffi:j Favorites
http:/~ocalhost lО б9/Wе Ь~tе4iln kТаt>eТеst.аs р х ... r6> Go

Список жизненно важных гиперссылок

~ Ссьшка Но 1 к Большому Бruшy


r..:> Ссьшка Н22 к автошколе "Диалог-Сервис"
r..:> Ссьшка Н23 к затычке J avaScript

[i) oone inIYanet

Добавление событий

Событие - это встроен н ый меха ни зм С#, с помощью которого


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

Технически событие представляет собой н екую адресную переменную ,


ссылающуюся н а зюем п ляр масса, поддерживающего собы тие. Если
значен ие этой ссылки рав н о null, то собы тие не прОИЗОllИо, п оскольку
нет соответствующего объекта . Один объект генерирует собы тие
(создает эюемпля р ) и п осылает уведомление через канал сообщений
опе р ационной системы. Другие, подписанные на это собы тие объекты
приложения , получают это сообщение вместе с дополни тельн ой
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

ин форма ц ией и за п ускают соответствую щи е обработчиЮ1 ,


п редва р и тельн о п е р едав им до п ол н и тел ьн ую и н форма ци ю в качест ве
ар гуме нтов.

Для объявле ни я адрес н ой п ереме нн ой событи я ис п ользуются деле гаты.


Делегаты представляются с п е ц иальным массом , определяющи м
сигн а туру (ти п ы, коли ч ество и п орядок следования ар гуме н тов)
п ередаваемой с соб ы тием и н форма ции от п равляющей сторо н ой , и
сигнатуру обработч иков соб ыти я п р ини мающей сторо н ы. Делег а т
объя в ляется в глобал ьн ой обл асти видимости уровня масса , чтобы
сд елать событие в и д и мым во всех кла ссах пр иложен ия. Объект,
п орожде нн ы й классом-делегатом , и является событи ем .

С п омо щью конструктора делегата п р и создан и и е го ново го эюемпля р а


в событ и е добавляется сс ы лка на обработчик и уста н авливается
кон троль за си гн атурой этого обработч ика . Э т от п ро ц есс н азывается
ре гистра ци е й событи я в массе и л и п одпи ской на соб ытие. Собы тия
п оддерживают м н о гоад р есат н ую п е р едач у (mu/ticasting). Э ТО з н ач и т, чт о
од н о и тоже собы тие мо гуг п р ин и мать мно гие объект ы , но
обрабатыва ть это собы т ие кажд ы й объект буд ет своим методом ,
кото ры й он указал в ко н структоре дел егата п ри п од пи ске на это
соб ы ти е.

Вот так ле н иво, об щи ми сло в ами , без соответствующих п р и меров кода


мы обозрел и меха ни зм и с п ользо в ания соб ы тий и делегатов в ч истом
С#. БУдем с ч и тать , что мы будто бы вс п ом ни ли те азы языка С #,
кото ры е нам должн ы б ы ли да в ать вместо Па скаля н а младших курса х (я
же не могу оди н р асхлебывать за всех). Те п ер ь пр и ступ и м к
рассмотр е н ию на шей темы - как доб а вит ь событ и е к пользовательскому
элемен ту уп р авле н ия , чтоб ы он д олж н ым образом реа гир овал на
соб ы ти е, п р и сла н ное ему кrlИе нтом ст р аницы.

М ы эту задач у поста ви м как р азв и тие предьщуще го пр и мера, п оэтому


для дал ьней ше й р аботы н уж н о создать ко пию фа йлов это го п р и мера .

• ~ п ан ел и So lutio n Explo rer, Уд е р жи вая мави шу Ctrl, вы д ели те


узлы LinkTable.ascx и LinkTableTest.aspx
• u;.;rч ерез ко н текстн ое ме н ю п а н ели в ы полн и те кома н дУ Со р у, а
затем че р ез кон текст н ое ме н ю н а узле пр оекта (ввер>о') выполни те
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

командУ Paste
• ~ ереименуйте созданные копи и в имена оригиналов , но с
добавле нием Ext (extension расширенный), а именно:
LinkTableExt.ascx, LinkTableExtTest. aspx (файлы подцержки
LinkTableExt.ascx.cs и LinkTableExtTest.aspx.cs оболочка
п ереименует сама)
• r;;,;:rСделайте страницу LinkTabIeExtTest.aspx стартовой, вып олн ив
на ее узле в представлении пан ели So lution Ехрюгег командУ Set А5
Start Page кон текстно го меню
• r;;:;noAnpaBbTe в файле LinkTableExtTest.aspx демарацию
@Register, чтобы новая тестовая страница применяла
п ользовательский элеме н т управления из друго го файла

<%@ Register Src='1.inkTableExt.ascx" TagName='1.inkTabIe" TagPrefu

• ~Запустите новую тестовую страницу на выполнение , чтобы


убедиться в ее работо с пособности с пр ежней функциональностью

Все, те п ерь мы готовы модернизировать новые файлы пред ы дущего


при мера . Посмотрим , что мы хотим сделать.

В предыдущем пр имере мы с помощью вспомогательного масса


Lin kTableltem мо гли доб авлять в массе пользовательского
элемен та управления LinkTableTest новые 2uперссЬ/лкu типа

asp : Hyper Link к элементу а sp : Da taLi s t . По щелчку мие н та на


одной из гиперссылок он безусловно направлялся по указанн ому адресу
Теперь же мы хоти м перехватывать и распознавать щелчок на любой
2uперссылке для ко н троля за действ и ями пользователя: о н хочет туда · то ,
а можно ли ему Вдруг п ользователь хочет в закрома, а мы считаем, что
он не имеет на это достаточных прав. Сейчас мы не будем оцен и вать
п ользователя , просто распознаем 2uперссылку и выведем ее н а экран.

Ранее в дескр ипт ор но м представлении пользовательского элемен та


управления мы применяли стандартный элемен т asp : HyperLink .
Если посмотреть на масс это го элемен та
System . Web . UI . WebControls . HyperLink через панель Object
Browser, то можно увидеть , что он не имеет никаких событий
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

ObJect Browser ..... -Q- Х

Browse: Му Solutюп

<Search> Г 9 MdAl:IYit<JtesToRender(System .
II----,---=~=---,---:-.,...:;::;...-i I (. . ~o MdParsedSubObject(obj€ct)
щ- . 4t$: GridViewUpdateEven.... ;
: · о НурегLlПkО
ffi··~ HiddenField '
: "о LoadVieWState(obj€ct)
,
4:
ci:J ... Hlerarc:hio:alDataBouг .
i,··-" ORenderContents(System,Web.U
1i>. '11 Hots~t
C~ :!5' ImageUrl
"''11 ....
ц оt:'jXJЬ:оПесооп .(~ NavigateUгl
';''11
~,'. 4$ HyperLinkColumn i···· .- Target
(. . !5' Text
ffi··~ HyperLinkConuolBuil

с д ругой стороны , масс LinkBu t ton име ет д в а событ и я , которые


ге н е р ир ует э л ем ент пр и выбо ре п оль зо в ател я

m
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

ObJect Browser '" J;l Х

Browse: му SoIubOll

<Search> • .....</ AddAttri:JutesToRender(System.


fт--т-т-;;:-c~:-:---:-:---,-,--:=-----11 ' ..", AddParsedSubOb]€Ct(ob]€Ct)
I±J'..~ GridViewLpdateEven .... ; .t>.
....,.~ Gеt?оstвасkОрtюnsО
,;,. . '1$ HiddenFffi
......,. LinkButtOll О
ciJ...~ HierarchicalDataBour ,....... LoadV","State(object)
", . '1$ Hotspot ' ,," OnChck(System,EventAгgs)
НJ .. ·~ Hotspotcollecbon ; л
· . ·1~ OnCommand(System,WebUI.
",'1$ HyperLink ~
, i.... " .., OnPreRender(System.EvenUl.r
ri,J . ·~ HyperLinkColumn
i "'-';~ RaisE9ostБackEvent(sUilg)
I±J".~ HyperLinkConu oIEIuil :"'--i~ RenderCOIltents(System.Web.U
rn··'1$ HyperLinkField :.... ~ CausesValidation
~.' ..~ Image
:.... ~ Сот mandArgument
I±J"'~ ImageButtOll '
:... ~ Сот mandName
НJ .. ·~ ImageField ;
. . . . m ' OnСliепtcliсk
';''1$ ImageMap ,... ~ Росtвзdkll"l
~ ...~ ImageMapEvenUl.rrк
""" 't'j' Text
", . '1$ Label 'm' VaIкJa"onGгoop
rn··'1$ LabelConuolBuilder
$. '1$ '1 СН
!} Соттаnd
"' '1$ LinkЕluttОПСOIl"'ОПЗU

Эти соб ыт ия мы и будем п ерехва тывать в н ашем элеме н те управления .

• ~ зме н ите тип элемента в шабло н е <ItemTemplate>


дескр иптор н ого п редставле н ия файла LiпkТаblеЕхt .аsсх и новое
имя атрибуга Co mmandA rgu ment , п осле ч его файл долже н бы ть
та ки м

<%@ C ontrol Language="C#" AutoEventWireup =''true'' CodeFile="LinkTabIe E:


Inherits=''LinkTable '' % >

<table bord er="l " cellpadding=''2'' ce llspacing=''O '' width="lOO%''>


<tr>
<td >
<asp:Label ID =' '1ЬГПtle'' runat="selVer"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

ForeColor= ''#COOOOO'' F ont- Bokl=''true''


Fопt-Nаmes = 'Vе mаdа " Fо пt-Size="Sma ll" >
< !--Здесь будет за головок- ->
</asp:Label>
</td>
</tr>
<tr>
<td >
<asp:DataList ID="listCo ntent" runat="server">
<ItemTemplate>
<img width=''25'' hеight="lЗ" src=''Yes.gif' alt="MapKep''>
<asp:LinkButton ID=''НурегLinkl '' runat="server"
СО П1П1апdАгgumе пt= '< %# DаtaВindег.ЕvаЧСопtаinег.DаtаItеm
Text='<%# DаtaВindег.ЕvаЧСопtаinег.DаtаItещ 'Text') %>'>
</asp:LinkButton>
< lItеmТеmр1зtе >
</asp:DataList>
</td>
</tr>
</tab)e>

Листинг
LinkTableExt.ascx
Смена типа элемента
• шаблоне файла

Мы хотим создать событие с именем L inkCl i c k ed . Для


распознавания выбранного п ункта списка нам вместе с будущим
событи ем L i n k Cl i ked н ужно будет п ередавать инqюрмацию о
знач ени ях свойств Te x t и Ur l , которые мы о пр еделили р анее во
вспомо гательном классе L i nkTableltem . сз . Затем в обработчике
событи я Li n k Cl i c k ed мы р аспознаем эту инqюрма ци ю и выведем ее
на экран .

Напрямую эюемпляр класса LinkTableltem . сз в аргументах


событи я п ередавать н ельзя - не тот тип, п оэтому упакуем е го в класс
L i nkTable EventArgs , который обяза н быть наследни ком
библиоте ч ного класса
Sys t em . E ventArg з . Объявим также делегата
событи я в глобальной области видимости .

• ~Откройте файл LinkTab Ie Ext.ascx. cs подцержки

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

пользовательского элеме н та управления и добавьте в него


объявление ново го масса и делегата, п осле чего общий код
долже н бы ть таким

usiпg System;
usiпg System.Data;
usiпg Systеm. Со пfigша tiоп;
usiпg System. Collections;
usiпg System. Web;
usiпg System. Web.Security;
usiпg System.Web.UI;
usiпg System. Web.UI. WebControls;
usiпg System.Web.UI.WebControls.WebParts;
usiпg System. Web.UI.HtmlControls;

public partia l class LinkTable : System.Web.UI.UserContro l


(
public string Tlt1e
(
get { геtшп Ibmde .Text; }
set { lbmtle.Text = value; }
}

private LinkTab leItem{] кешs;


public LinkTableItem[] Items
(
get { геtшп items; }
set
(
кешs = value;

11 Обновляем сетку
listСопtе пt.DаtaSошсе = кешs;
listCo ntent.DataBindO;
)
}
}

11 Объявляем деле гат события LinkClicked


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

11 в гл обальной области видимости,


11 который определит си гнатур у события и обработчика
public de!egate void LinkClickedEventНand!er(object sender, LinkTabIeEve ntAr:

11 Класс-ynаковка экземпляра LinkTableItem для


11 передач и с событием в качестве аргумента
public class LinkTableEventArgs : ЕvепtAгgs
(
11 Конструктор
public LinkТаЬ!еЕvепtAгgs(LiпkТаЬ!еItеm item)
(
se!ected Item = кет;
)

11 Внугреннее поле БУдет хр анить объект гиперссылки


11 и контролируется свойством 'только для чт ения"
private LiпkТаЬ!еItеm se!ected Item;
public LinkTab!eItem Se!ectedItem
(
get { геtшп se!ected Item; }
}

11 Внугренне поле хран ит флаг отм ены , переданный с генериро вавши


11 событие массом- источ нико м для обработчика ЮJасса-приемника
private Ьоо! сапсе! = false;11 Инициализируется при создании
public Ьоо! Carк:e!
(
get { геtшп сапсе~ }
set { са псе! = va!ue; }
}
}

Листинг

LinkTableExt.ascx.cs
Добавление нового хласса - упаховхи
• файл

Таким образом, мы объявили масс для ynаковки п ередаваемой в


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

ш
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

распознает эту 2 ипер ссылку и через событие L ink Cl i c k ed отправи т


эту информацию в канал сообщений Windows. Конеч н о же , этим должен
заниматься масс Li n k Ta bl e подц ержки пользовательского элемен та

управления.

• ~Откройте на редактирование файл LinkTableExt.ascx в режи ме


Dеsigп
• ~ы делите пользовательский элемен т управления и в панели
Prop erties создай те об р аботч и к для события I t e mComma n d
(Проследите , чтобы в дескрипторе п ользовательского элеме н та на
тестовой стран ице не появился атрибуг Wi d t h )

LinkTabIeExt.ascx Properties .... -j:::] Х

IistContent System.Web.UIwet·
~:' l1]lJ I [;] [2J I ~
CancelCommand
DаtaВlгЮlr>;J
DeleteCommand
Disposed
ЕditCоmmaгЮ
Inlt
ItemCommand
ItemJeated
-
• IJ$Добавьте в масс Li n k Table и созданны й обработчик
стан дартн ого собы тия следующий код

us iпg System;
us iпg System.Data;
us iпg Systеm.С опfigша tiоп;
us iпg System.Collections;
us iпg System. Web;
us iпg System. Web.Security;
us iпg System. Web.UI;
us iпg System.Web. UI. WebCo ntrols;
us iпg System. Web. UI. WebCo ntrols.WebParts;
us iпg System.Web. UI. HtmlControls;
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

public partial class LinkTable : System.Web.UI.UserControl


(
public string TJtle
(
get { геtшп Ibmde.Text; }
set { lbmtle.Text :::: value; }
}

private LinkтаыlItеmпп кешs;


public LinkTableItem[J Items
(
get { геtшп items; }
set
(
кешs = value;

11 Обновляем сетку
listСопtе пt.DаtaSошсе = кешs ;
listContent.DataBindO;
)
}

11 Объявляем в классе наше событие LinkClicked


11 с помо~ю ранее созданного глобального дел егата
public event Link C lickedEventНandler LinkClicked;

protected void listContent_ItemCommand(object so urce, DataListCommandE


(
if(LinkClicked != null)
(
11 Выделяем объект ссылки , на которой был выполнен щелчок
LinkButton link = (LinkButton)e.Item.Controls[l];

11 Выделяем нужные свойства Text и Url через атрибугы


11 дескр ип тора элемента LinkButton и сохраняем их
11 в эюемп л яре вспомогательного класса
LinkTableItem кет :::: new LinkTabIeItem(link.Text, link.CommandArgun

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

11 Передаем ссылку на сохраненные свойства в класс упаковки Щ


LinkTableEventArgs args == пеw Linkтаыevеп tAгgs(itеm);;

11 Генерируем событие
LinkClicked(this, aгgs);

11 Пускаем клиента к закромам по ссылке, если класс-получатель


if (args.Cancel !== иие)
(
Respo пsе .Red irect( item. Url);
}
}
}
}

11 Объявляем делегат события LinkClicked


11 в глобальной области видимости,
11 который определит си гнатур у события и обработчика
public delegate void LinkClickedEventНandler(object sе пdег, Linkтаыevеп tAг::

11 Класс-упаковка зкземпляра LinkTabIeItem для


11 передач и с событием в качестве аргумента
public class LinkтаыeveпtAгgs : EventArgs
(
11 Конструктор
public LinkTableEventArgs(LinkTableItem item)
(
se lected Item == item;
)

11 Внугреннее поле БУдет хранить объект гиперссылки


11 и контролируется свойством 'только для чт ения"
private LinkTableItem selectedItem;
public LinkTableItem SelectedItem
(
get { геtшп selected Item; }
}

11 Внугренне поле хран и т флаг отм ены , переданный с генерировавши

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

11 событие массом- источ ником дл я обработчика ЮJасса-приемника


private Ьооl сапсеl := false;11 Инициализируется при создани и
public Ьооl Carк:e l
(
get { rеtшп cancet }
set { са псеl := value; }
}
}

Листинг Добавленный ход в !Сласс LinkTable файла


LinkTableExt.ascx.cs

Теперь событие L inkClicked БУдет воз ни кать всякий раз , когда


п ользователь щелкнет на гиперссылке пользовательского элемента

управления. Классом-получателем этого события определим нашу


тестовую страницу. Именно в ней мы создадим функцию-обработчик,
которая распакует переда нные событием аргументы и выведет
п олученную инqюрмацию на экра н . Проверку существования события
мы выполняем на всякий случай, чтобы наверняка предотвратить
ге н е рацию систем н ого ИСЮJючения.

Учитывая, что в режиме проектирова ни я оболочка поддерживает


автоматическое создание обработчиков через панель Properties только
для событий библиотечных массов , создадим за готовку обработчика
вручную. При этом нужно соблюсти сигнатуру, заданную объявленным
ранее деле гатом . Но и в этом случае подсказчик IntelliSense оболочки н ам
п омогает .

• ~Откройте на редактирование файл LinkTableExtTest.aspx.cs и в


конце обработчика события Page Load () ЮJасса
L i n kT able Test начните набирать имя объекта L i n kT able l,
под которым на тестовой странице у нас числится эюемпляр
зарегистрированного на ней пользовательского элемента
управления. Вы сразу увидите реакцию п одсказчика кода
IntelliS ense
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

_ pUbJlC: p.o.rt:bl. l cJ~~~ L;nkТ ~ ЬJ~'JI-~ t gY"t: = _ I! ",b . UI. ~ ~ g~

(
protected void paQe_ LOadl object sende r, !:',entA'QS е)

!! OOF"""PV""" ~~ ~al!O " O~ с ун.с""


L шkТ"bl",l . тi t J~ = "Сп ~<:;ок """Н"ННО ~ <fi:H>< X ~ хпе рсс"",ок ";

!! Co"д~ "" слис'ж ~1!~"~"TO~ - Г1fЛ"РССWIO~


LшkТ"ЬJ"Н = 1 1 ;t",.. _ """'" Lшkт"ыl,н, ,,,1 3 j ::
it",, ~ [ OI = n ~W LinkTdbl"'Il" [I ("CCNJ]" ~ lI'l ~ ЕО 1!НО "У Виллу" ,
"ЬПр' ((www lI icro ,o tt соо") ;

i t:=~ [l ] - n ~'" ,inkT~bj"T t:"" I "C=M Jl'2 ~ ~ ИОI~О 1!" \ " ДIIЫIOГ -С",р~ис\"" ,
' http ' ((WWW d i e 1Qg ,~ п к ... n ... t ' );
i tens [2) nЕ'" LinkTdblelte,, ('CCWJ ~a lI'З ~ 9а'ЫЧ~8 J ачаsсriрt',
'j"y,ycr;pt ' voi iJ !О )" );
L in kТ~bl"l.It ~,, ~ - i t ~ ,.~ ;

Нажав два раза клавишу ТаЬ мы получим и реrnстрацию собы тия в


классе - п риемнике ч е ре з глобально го делегата, и заготовку обработчика.
После генерации оболочкой таким способом заготовки обработчика
далее мож н о п оступить одни м из следУЮЩИХ способов:

1. Либо оставить все как есть и начать за полнять обработчик


2. Либо остав ить заготовку обработч ика, а код ре ги ст р ации собы тия
уничтожить

LinkTable1 .LinkC licked += пеw LinkсliсkеdЕvепtнапdlег(Linkтаыl1_LL

Если выбрать второй способ, тогда нужно в дескрипторном


представлении пользовательского элемен та добавить ат р ибуг
On Link Cl i cked= "Li nkTablel LinkC li cked ", чтобы
привязать к событию созданны й обработч ик (обратите внимание , чт о
имя атрибуга qюрмируется из им ен и событи я и nрефuкса ОП ). Но и в
этом случае Большой Билл нам тоже ч угь-чугь п омогает
В.М. Сн"",,,в Про,раммupoвtJNШ' 110 ASP.NET
,.~ W~bS;t~"I - r-11<rosoft Visual Studio

r ablerestExt.aspx* lrtT~Xt.=X ,CS LrtТз.:еЕxt , asсх

~ Clent Objects g, Events . . Iс'ю ЕуentБ)


9" ~age
Сo::iеЕ' i
Language =' C#" Au t oEventW~reup= "true"
l e = "LiJltTableTestExt . aspx .cs" Inhe[it5 = 'Li nkTab l eTest " %>

EJ <htrr.l xralns = "htt D' ! !\ОWoЧ . wЗ • org/H 9 9 !xht;nl '>


- <head [ШJa t = " sе[v е r" >
..;titlе> тестовая страница сл ожно го элемеНТа у лравления </titlе>­
</h .,,,d>-
- <bo dy>
..; for;n ~d = "foLI0 1 " runat=" s erver'>
<d ~ v>

<ucl : Lin kTable Ш=" LinkТаЫеl '


</div>-
..; / forlO>-
</body>
</htm l >

Давайте выберем вто рой с по соб ...

• ~ничтожте реги страци ю соб ы тия в ЮJассе LinkTableTes t ,


ско пир уй те имя сгенериров а нного обработчи ка и доба вьте его в
атри буг OnLinkC 1 i c ked= " LinkTablel Lin k Cl i c ked"
дескриптора <ис l: Link Table ID= " Link Tablel "
run at= " server " /> фай ла т естовой страницы
LinkTableExtTest.aspx
• ~ режиме Design т естовой страницы р азмест и те текстовую
метку asp : Label из ВЮJа.цки Standard, задай те е й имя lbl I n fo
и очистите п оле ее свойства T ext (л ибо у,цал и те одноиме нны й
атри буг в дескрипторе). В н е й мы будем отоб ражать информацию
о на жатой гиперссылке
• ~ер ни тесь в файл LinkTableExtTest.aspx.cs и за п ол ните

об р аботчи к та к

using System;
using System.Data;
using Systеm. Со пfigша tiоп;
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

usiпg System. Collections;


usiпg System. Web;
usiпg System.Web .Security;
usiпg System.Web.UI;
usiпg System. Web.UI.WebControls;
usiпg System.Web.UI.WebControls. WebParts;
usiпg System. Web.UI.HtmlControls;

public partial class LinkTableTest : System.Web.UI.Page


(
protected void Page_Load(object sender, EventArgs е)
(
// Формируем заголовок с писка
LinkTab lel .Тide = "С писок жизненно важных гиперссылок";

// С оздаем с пи сок элементов - гип е р ссылок


LinkTableItem[] items = new LinkТаЬ)е Itеm[ З];
items[O] = new LinkТаblеItеm("Ссылка N91 к Бол ьшом у Биллу",
•.http ://www.mk:roso ft. со т');
items[ l] = new LinkТаblеItеm("Ссылка N92 к автошколе \''Диало г-Се РЕ
· .httр ://www.diaЮg-sеrviсе.пеt·) ;
items[2] = new LinkТаblеItеm("Ссылка N9З к затыч ке JavaScript",
'1 а vascript:vo ю(О) '');
LinkTablel.Items = items;
}

public void LinkTablel_LinkClicked(object sender, LinkTableEventArgs е)


(
// Ищем подстроку в вызывающей строке
if(е.SеleсtеdItеm.Техt.lпdехОf("Диалог-Сервис") > О)
(
е.Сапсеl = fu lse;// Пропус тить
)
e~e
(
е.Сапсеl = tпJе ; // Н е п ускаем дальше
IblInfo.Text = ''Вы щелкнули " +
'\'11' + e.SelectedItem Text + '\". ";
IblInfo.Text += " И зв ини те, но Вам н е р азрешено и дти на "+
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

e.Se)ectedItem.Ur! + "!! !";


}
}
}

Листинг Обработчих добавленного события LinkClicked

• ~Запусти те тестовую страницу LiпkТаЫеЕхtТеs t .аsрх и


полюбуйтесь н а свою работу

..j-o Back ..,.. .... ..,.. ~ M ea a


дddг е s;s

Список жизненно важных гиперссылок

...- Ccьmкa .N"" 1 к Большому Биллу


r;.;s- Ccьmкa 1'{о2 к авТОПIКоле "Диалог-Сервис"

ii$ Ccьmкa Х23 к затычке J avaScript

Вы щелкнули "Ccьmкa Х21 к Большому Бшшу".


Извюпгге. ио Вам ие разрешеио иДП! иа
http://www.rnicrosoft.coт!!!

1. Donе iпtr.леt

Доступ из кода Web-страницы к состав ным

ко м п о н ен там п ользовательского эле м е н та уп р авления

Web-стран иц а, которая содерж ит интегрированный в нее

п ользовательский элемен т ynравле н ия, н е может без до п ол н и т ель н ых


п риемов п олучать достyn к компо н ен там этого элеме н та: к их методам ,

событи ям , свойствам. Такое п оложе н ие являет ся обос н ова н н ы м, чтобы


случайно в Web-страни це не в н ести н ежелательные изме н е ни я в ее

ш
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

дочерний элемент.

Но учитывая, что сам пользовательский элемент имеет достyn к своим


компонентам , а страница имеет достyn к пользовательскому элементу,

это правило можно обойти. Для это го существует два способа:

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


свойства и функции достyn а к нужным членам индивидуально
для каждого компонента

2. Ввести в масс пользовательского элемента ynравления для


каждо го компонента по одному дополни тельном у свойству,
возвращающему ссылку на соответствующий компонент

Первый способ

в пользовательский элемент вводят промежугочные свойства и ли


методы доступа, через которые из Web-страницы обращаются к его
компонентам. ЭТО напоминает прием, который применяется в С ++ для
п оддержания инкапсуляции (закрытости) да нны х: п ереме нны е-члены
масса с людuфикатором доступа pr i vate ynаковывают в функции
достynа publ i c , которые сами видят эти переменные , а их, в свою

очередь, видят миен ты этого масса .

Пусть, например , пользовательский элемен т управления MyCo n t r oll


как объект порождается массом MyCont r o l и в качестве одного из
компонентов содержит в себе объект L abell библиотечно го масса
System . Web . UI . WebCont r ols . Labe l . Класс Label наследует
от базовою класса Sys te m. Web . UI . WebCon trol s . WebCon t r o l
свойство BackColo r , которое, в свою очередь, имеет тип
System . Draw i ng . Colo r . Напрямую из Web-страницы н ельзя
установи ть новое значение свойства BackColo r компонента Labell
пользовательско го элемента. Но можно раскрыть это свойство для Web-
страницы , введя про межугочное свойство BackColor (или с другим
и менем) в массе самого пользовательского элемента. Сказанное
схематично изображено на рисунке

'"
в м С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Web - страница

i
BackColor I >~
МyContro l l

I BackColor I
LaЬell

Выполним это на практике.

• ~Создайте за готовку пользовательского элемен та Web User


Co ntrol с име н ем MyControLascx с раздельн ы м кодом (флажок Place
code in separate filе масте р а вютючен)
• ~ ерейдите в режим Design редактора за готовки и поместите на
н ее из вютадки Standard элемен т Label с именем Labell
• ~ п анели So lution Explorer откройте файл подцержки
MyControLascx.cs, удал ите из ютасса MyCont r o l заготовку
об р аботчи ка Page_LoadO за ненадобностью и до п олните класс
свойсmвалш доступа, чт обы он стал таким

using System;
using System.Data;
using Systеm. Со пfigша tiоп;
using System. Collections;
using System. Web;
using System.Web .Security;
using System. Web.UI;
using System. Web.UI.WebControls;
using System.Web.UI.WebControls. WebParts;
using System. Web.UI.HtmlControls;

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

public partial class М уС опtrоl: System.Web .UI .UserContro l


(
public string Text
(
get { геtшп Lab ell.Text; }
set { Label1 .Text = value ; }
}

public SystemDrawing.Color BackColor


(
get { геtшп Lab ell.BackColor; }
set { Label1 .BackColor = value ; }
}

public SystemDrawing.Color F огеС оюг


(
get { геtшп Lab ell.ForeC olor; }
set { Label1 .ForeC olor := value; }
}
}

Листинг Добавление посреднических свойств доступа х классу

MyControl из Web - страницъ!

Здесь мы и с п ользовали имен а посредн и ческих свойств родителя


MyCont r o l l то ч но такие , как у п рямых свойств компонен та Label l .
Но это не обязательн о . Мож н о ис п ользовать любые имена. Просто ,
когда И ванов, П етров, Сидо р ов оз н ачают одн о и то же лицо, но в
разных ин ста нци я числятся по разному, это " хужее Н.

• Г;:;=Создайте пользовательскую тестовую стран ицу с раздельным


кодом п од именем MyCo ntroIГest. aspx и п ереведи те ее в режи м
редактирования
Design
• г;:.=из панели Solution Ехрюгег из дерева файлов п риложения
п еренеси те н а тестовую стран иц у узел МуСопtгоlаsсх . Убеди тесь ,
что эюемпляр пользовательско го элемента уп р авления

заре гистрировался на тестовой стра ниц е п од имен ем

MyControl l
• ~ о п робуйте выделить элемент уп р авления и убедитесь, что он

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

не выделяется и добавленные нами свойства н е видны в панели


Prop erties. ЭТ О з начи т, что декларативно (в режиме
пр оектирова ния) из страницы на страи вать его н елься, н о можно
пр о гра мм но ynравлять (в режиме выполнения) ч е рез введенные
нами общедостynны е свойства, в чем мы и хотим убедиться .
• r;:;nоместите на страни цу под пользовательски м элементом
ynравления компон е нт Rad i oButtonLis t из вкладЮ1 Standard
и убед и тесь, что он имеет ID= " Rad i oButtonLis tl "
• ~ ерез коллекцию Items элем е нта Rad i oBu t tonListl
задайте три радиокнопки с таки ми свойствами
о Va l ue= " Red "
Техt = " красный ";

о Техt = " Зеленый "; Va l ue= " Green "

о Техt = " Синий "; Value= " Blue "


• Г;;:;=Установите свой ство Repea t Direction эл ем ента

RаdiоВuttопL i stl в з н аче ние Ноrоzопtаl

• ~ы делите компонент RadioButtonL i stl и через пан ель


Prop erties создай те обработчик для его события
Selectedlnde x Changed
• ~ oд с пи ском радиокнопок поместите компонент Input
(Submi t) из вкладЮ1 НТМL

Дескри п тор ное пр едставление страницы бу,цет иметь вид

<%@ Page L апguagе="С#" Аutо ЕvепtWirеuр=' 'truе ''


С ode F ile= ''М УС о пtrо rrest. asp х. cs"
Iпhег its=''МуСопtrоrrеs t '' %>

<%@ Register S гс =''МуСо пtго L аsсх'' ТаgNаme= "МуСопtго l " TagPrefix="llcl "

<html xm1пs="httр ://www.wЗ.огgl 19 99/xhtml" >


<head nmat="server">
< title > Uпtitled Page</tide >
<lhead>
<body>
< fопn id ="fо пnl " ruпаt="sеrvег' '>
<div>
< llсl:М уС опtго) ID="MyControl1 " nmat= "server" />
< Ьг />

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

<br 1>
<asp :RadioButtonList ID='RadioButtonList1 " runat= "server"
RереаtDirесtюп=''Ноriwпtаl''
OnSelectedlndexChanged='RadioButtonListl_SelectedlndexChanged '~
<asp :Listltem Value='Red"> Кра с ный </asp:ListItem>
< asp :Listl tem Value= "Gree п"> 3 ел е н ы й </as р :Listl tem>
<asp :Listltem Vа luе =''В luе ' '> С иний </asp:Listltem>
</asp:RadioButtonList></div>
<br 1>
< inр и! id="Submitl" type="submit" value="submit" 1>
</form>
</body>
</html>

Листинг Дескрипторное представление тестовой страницы


МуСопtrоlТеst.аsрх

Мы хотим , чтоб ы на клиенте при щелчке на кнопке Submit выполнялась


обратная отсылка на сервер, где бы код страницы через вв еде нные нами
в класс пользовательского элемента управления допо лни тельные

свойства менял н астройку элемента Labe 1 1. Этот код смены


настройки нужно поместить в созданный н ами обработчик
радиокнопок, чтобы он срабатывал каждый р аз, когда получит обратную
отсылку с требованием пользо вателя выполнить новые настройки. В
результате элемент L abe11 сгенерирует нужный HTML ~кod и отошлет

его юш е нту.

• ~3аполните обработчик
Rad i o Butt on Li st1 Se1ected I nde x Changed( )
страницы в файле MyControrrest.aspx.cs следующим кодом

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebContro ls;

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

using Sуstеm.WеЬ.U I .WеЬСопtrо ls.Wе ЬРаrts ;


using Sуstеm.WеЬ.U I . НtmJСопtгоls ;

риыic рапial class МуСопtгоfТеst: System.Web.UI.Page


{
protected vo id RаdioВuttоnList1_sеleсtеdIпdехСhaпgеd(ОЬjесt send el
{
int index = RadioВuttonList1.SеlесtеdIпdех;

switch (index)
{
case О:
МуСопtгоl1.FогеСоlог = System.Drawing.Color.White;
МуСопtгоl1.ВасkСоlor = System. Drawing.Co lor.Red;
break;
case 1:
МуСопtгоl1.FогеСоlог = System.Drawing.Color.Aqua;
МуСопtгоl1.ВасkСоlor = Sys tеm. Dгаwing. Со lor. Gгее п;
break;
case 2:
МуСопtгоl1.FогеСоlог = Systеm.Dгаwing.Соlог.УеПоw;
МуСопtгоl1.ВасkСоlor = System. Drawing.Co lor.Blue;
break;
}

if(index!= -1)
М уСо пtго l1 .Теxt = RadioButtonList1.1tems[index]. Value;
}
}

Листинг. Код обработчика в файле MyControlTest.aspx.cs


• ~Откомпилируйте страницу и проверьте ее работос пособность.
При щелчке на кнопке код страницы ме н яет свойства компонен та
Labe 1 1 , хотя он входи т в состав п ользовательско го элемен та

уп р авления МуСо пиоl1 . Вза и модействие стра ницы с Labell


пр оисходит через добавленные на ми в пользовательский элемен т
уп р авления до п ол ни тель ны е глобаль ны е свойства.
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Второй способ

Есть еще один способ обеспечить доступ к компонентам ,


интегрированным в поль зовательский элемент управления , это
до бавить в пользовательский элемент по дополнительному свойству,
возвращающее ссылку на каждый компонент. При этом н ужно
использовать только get -аксессоры, поскольку адреса компонентов

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


страницы , можно обратиться к любым членам раскрытого таким
образом компонента, входящего в состав поль зовательского элемента.

Поясним сказанное на пр едыдущем прим ере .

• г;.:.=СкопирУЙте через панель Solutlon Explorer, как это мы делали


р анее, фай л тестовой ст р аницы MyControrrest.aspx и файл
пользовательского элемен та управления MyControLascx
• Г;;:;nрисвойте копиям новые имена МуСопtгоlEхtТеst.аsрх и
MyControlExt.ascx соответственно (файлы сопровождающего
скрытого кода оболо ч ка переимен ует автоматически)
• г;;;?Сделайте страни цу МуСопtrоlEхtТеst.аsрх стартовой, выполнив
на ее узле в панели So lution Explorer командУ Set As Start Page
• ~ змените парам етр S r c директивы регистрации в файле
М yControlExtTest.aspx

<%@ Register Src="MyControlExt.ascx" TagName='MyControl" TagPr€

• г;;;?Откройте файл скрытого кода MyControlExt.ascx.cs и измените


в н ем масс МуСоп trol , чтобы он выглядел так

using System;
using System.Data;
using Sуstеm.Сопfigurаtiоп;
using Sуstеm.Соllесtiо пs;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using Sуstеm.WеЬ.U I .WеЬСопtrоls;
using System.Web.UI.WebControls.WebParts;
,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

using System.Web.UI.HtmlControls;

риыic рапia l class MyControlExt: System Web.uI.UserControl


{
// Раскрываем весь компонент Label1
// Имя свойства IrmerLabell выбрали произвольно
// Используется только get-аксессор

риыic Label Iпne гLаЬ е l1


{
get { return Label1 ; }
}
}

Листинг . Добавление в класс пользовательского элемента


управления свойства-ссылки на его внутренний компонент
Labell в файле MyControlExt.ascx.cs
• Г;;:;=Скорр е ктируйте в файле MyControlExt.ascx атрибyr директивы
СОП t rol так Inhe r i t s= " MyControl Ex t "

• Г;;:;=Откройте файл MyControlExtTest.aspx.cs скрытого кода тестовой


страницы и отредактируйте его дл я достynа к прямым свойствам
компонента Label l с использованием созданного адреса

InnerLabe l l

using System;
using System.Data;
using Sуstеm.Сопfigurаtiоп;
using System.Collectio ns;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using Sуstеm.WеЬ.U I .WеЬСопtrо ls;
using Sуstеm.WеЬ.U I .WеЬСопtrо ls.Wе ЬРаrts ;
using System.Web.UI.HtmlControls;

риыic рапial class MyControlExtTest: System.Web.uI .Page


{
protected void RаdioВuttоnListl_sеJeсtеdIпdехСhaпgеd(ОЬjесt send el
{
in! index = RadioButtonListl.SelectedIndex;

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

// Достyn к прям ым свойствам Ю)мпонента Lab el1 выполняеr.­


// ч ерез ссылку на этот Ю)мпонент в родителе М уСо пtго l1
switch (index)
{
case О:
М уСо пtго l1.lnnегL а Ь е l1. F oreColor = 5 ystem Drawing. Color.'
М уСо пtго l1.lnnегL а Ь е l1.Вас kСоlо г = System.Drawing.Colo r.
break;
case 1:
М уСо пtго l1.lnnегL а Ь е l1. F oreCo lor = 5 ystem Drawing. Color.J
М уСо пtго l1.lnnегL а Ь е l1.Вас kСоlо г = System.Drawing.Colo r.
break;
case 2:
М уСо пtго l1.lnnегL а Ь е l1. F oreColor == 5 ystem Drawing. Color.'
М уСо пtго l1.lnnегL а Ь е l1.Васk Соlо г = System.Drawing.Colo r.
break;
}

if(iпdех!= -1)
М уСо пtго l1 . lnnегL а Ь е l1 . Text = RadioButtonList1.Items[index]. V
}
}

Листинг Доступ к прямым свойствам Labell через адрес

IпnеrLаЬеll на странице MyControlExtTest.aspx


• ~ыполните стран ицу и убедитесь, что п олучился тот же
самый результат, что и в предьщущем при мере при реализации
п е рвого способа

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

11 Untitled Page - Мicrоsоft Internet Е.


File Edit Vi€.... Favoгites Tools Help
*' Back ~ .. ~ 10 @I Gl I <t\Search
Address ebSite4 !МуСоп1т OIТestExt, asp х

r Красный r Зеленый r. Синий

I submi t

ГlГlГ Im! Local intra",t

Какой cn особ выбрать - решать Вам.

Дин амич еское создани е п ользовшельского элемента


уп р авления

На протяже ни и этой темы мы рассматр и вал и во п рос создания


пользовательско го элемен та уп р авления в режиме п роектирован и я и

последУЮщее уп р авление им в п ро грамм н ом режиме. Но может


потребоваться н а стра н ице подгружать и настраивать пользовательский
элемен т управления динам и чески (''на лету') . Мы уже пр о граммно
создавал и и з библиотечно го элемен та управлен и я Ht ml Table объект­
таблицу на стра н ице DynamicTab)e.aspx. Те п ер ь п осмотрим, как это
делается для пользовательского элемен та уп р авления.

Требуется выполнить следУЮ щи е шаги:

1. Создават ь при каждой загрузке стран иц ы в обработчике ее


соб ы тия Page . Load экземпляр класса п ользовательского
элеме н та управления, заран ее под готовленно го в фай лах * .ascx и
* .ascx.cs. Создание и регистрация экзем п ляра п ользовательского
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

элемента в коде страницы осуществляется статическим методом


Page . LoadCon t r ol() .
2. Р езер вирова ть с помощью э лемента PlaceHolde r место
р азме щения для точ ного позиционирования на странице

по льзовател ьс кого элеме нта ynравления.

з. Обязательно присваивать посл е дина м ич еского создания значение


свойства 1О пользовательского элемента ynравления, особенно ,
когда создается несколько экзем п ляров одного и того же элемента.

Это может п онадоби ться для однозначной ид е н т ификации


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

выпол ня емом с помощью статического метода

Page . F in dCont r ol () , который как раз иcnользует значение


идентификатора 1 D.

Есть н екотор ая с п е цифика динамического создания пользовател ьского


элемента ynравления. Н ел ьзя создать пользовательский элемен т
напря мую , как это делается с библиоте чным элементом ynравления
че р ез конструктор кл а сса. Пользо в ател ьский элеме нт ynравления
состоит н е только из подцерживающего масса в файле >1< .ascx.cs, но и
дескрипторной части фай ла >I<.ascx. Поэт ому на эт апе праектuравания
он н е пр едставле н общим массом, экзем п л яр которого можно было-бы
создать с помощью конструктора. Экзем пляр пользовател ьского
элемента ynравления создается самой ASP.NET объединением эт и х двух
частей на эта п е выполнения.

• ~Скопируй те чер ез панель Solutlon Explorer, как это мы делали


р анее, файл те сто вой страницы МуСопtгоlEхtТеst.аsрх и фай л
по льзовател ьс кого элеме нта ynравления MyControlExt.ascx
• ~ рисвойте копи ям новые и ме на MyControlDynamicTest.aspx и
MyContro!Dynamic.ascx соответственно (файлы сопровождающего
скрытого кода оболо ч ка переимен ует автоматически)
• ~Сделайте стр аницу MyContro!DynamicTest.aspx стартовой ,
выпол нив на ее узле в пан ел и Solution Explo rer команду Set As Start
Page
• ~Закройте все пр едыдущие редактируемые документы командой
меню Wirкlow/Close All Dосuшепts
• ~Откройте на редактирование страницу
MyContro!DynamicTest.aspx в режиме Design, у,цал и те наш

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

пользов ател ьский элемент управления Labe 1 1 и пом естите на


е го место и з ВКlIадки Standard стандартный элемент управления
PlaceHolder
• r;:;n ерейдите в файле MyControlDynamicTest.aspx в режим Sошсе
редактор а страницы и у,цалите полностью старый код директивы
регистрации

<%@ Register Src="MyControlExt.ascx" TagName='M yC ontrol" TagPr€

На дан н ом этапе страница в дескрипторном представл е нии БУдет такой

<%@ Page Language="C#" AutoEventWireup=''true''


С ode F ile= ''М УС о пио lDynamicTest.aspx. cs "
Inherits='MyControrrest" % >

<html xmlns =' 'httр ://www.wЗ.огgl 19 99/xhtml'' >


<head nmat="server">
<title>Untitled Page</tide >
<lhead>
<body>
< fопn id ="fо пnl " runat= "server''>
<div>
<asp:PlaceHolder ID="PlaceHolderl " runat="server" 1>
< Ь г 1>
< Ьг 1>
<asp:RadioButtonList ID='RadioButtonList1 " nmat= "server"
RереаtDirесtюп= 'Horiw ntal''>
<asp :Listltem Value='Red"> Кра с ный </asp:ListItem>
< asp :Listl tem Value= "Gree п"> 3 ел е н ы й </as р :Listl tem>
<asp :Listltem Vа luе=''В luе' '> С иний </asp:Listltem>
</asp:RadioButtonList>
< Ьг 1>
<input id= "Submitl " type="submit" value="submit" 1>
</div>
</foпn>
<!body>
<lhtml>

Листинг Страница MyControlDynamicTest. aspx после удалеНИА


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

пользовательского элемента

Все, теперь пользовательский элемен т управления на странице не


существует! Вместо не го существует пустое место P l aceHolde rl .
Далее мы программно должны создать этот элеме н т, доба вить ссылку
на н его к ст р анице, а потом и управлять свойствами е го компо н ен тов.

• ~Откройте на редактировани е файл скрытого ю)Да

MyContro!DynamicTest.aspx.cs, выполнив команду контекстного


меню viJeW Cd
о е редактора

.!! Cut

lt1I Сору

if!, Paste
Paste Alteгnate

'х D€lete

V~Code
I I
1!1 View Rl Browseг

Synchroniz:e Document OutJine

Foгmat selec:tion
Foгma1jjng аnd Valid.aoon ...

• ~ змените код об р аботчика Page Load ( ) , чтобы он стал


таким

using System;
using System.Data;
using Systеm. Со пfigша tiоп;
using System. Collections;
using System.Web ;
using System. Web.Security;
using System. Web.UI;
using System. Web.UI.WebControls;
using System. Web. UI. WebControls. WebParts;
using System. Web. UI. HtmlContro ls;

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

public partial class MyControrrest: System.Web .UI.Page


(
protected void Page_Load(object sender, EventArgs е)
(
11 Создаем экземпляр масса поддержки
11 пользовательского элеме н та управления
МуСопиоl MyControll := (MyControl)Page.LoadControl('MyControlDyn
11 Добавляем объект в зарезе рвир ованное место страницы
Р !асе Н о k:ler 1. С о пио 15. Add(M УС о ntro 11 );

int index:= RadioButtonListl.SelectedIndex;

11 Доступ к прямы м свойствам компо н е нта Label1 выполняем


11 чер ез ссылку на этот компонент в родителе MyControll
switch (index)
(
case О:
М yControll . InnerLabel1 .ForeColor := SystemDrawing.Color. White ;
М yControll . IппегLаЬ е l1 .ВасkСоЮг := 5 ystem.Drawing.Color. Red ;
break;
case 1:
М yControll . InnerLabel1 .ForeColor := SystemDrawing.Color.Aq ua;
М yControll . IппегLаЬ е l1 .ВасkСоЮг := 5 ys tеm. Dга w ing.СоЮг.Gгееп;
break;
case 2 :
М yControll . InnerLabel1 .ForeColor := SystemDrawing. Color. Yellow;
М yControll. IппегLаЬ е l1 .ВасkСо Юг := 5 ys tеm. D гаw ing.СоЮг.В luе;
break;
)

if(index ,=
- 1)
М yControll. InnerLabel1 .Text := RadioButtonListl. Items[ind ex]. Value;
}
}

Листинг Код обработчиха Paqe_Load() для создания

пользовательсхого элемента

Обратите внимание , что при на боре кода создания пользовательского

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

элемента в редакторе кода механизм Intel1 i Sense нам не


помогает, потому что страница не знает, что где-то в файле
MyControlDynamic.ascx существует класс МуСоп t rol .

Преобразование страницы в пользовательский элемент


управления

Чаще пользовательсЮ1Й элемент ynравления проще сделать из обычной


страницы .aspx, чем мы и воспользуемся ниже. ЭТО делается так:

1. С начала нужно разработать обычную страницу, отладить ее и


проверить в де йствии.
2. Переименовать расширение файла из aspx в ascx
з. Директиву @Page вместе с ее атрибугами следует удалить и
заменить директивой @Control с требуемыми атрибугами.
4. Удалить из кода все дескрипторы <h tm l> , <body> , <fo r m> ,
<head> .
s. В коде файла подцержЮ1 заменить базовый кл асс Page на
Use r Cont r ol .
б. Если мы используем модель совмещенного кода , то нужно в

директиву Cont r o 1 обязательно доб авить атрибуг


ClassName= " ИМЯ _ Фа й ла _ и л и _ л юбое _ и мя ". Он извещает
ASP.NET, что код , который нужно компилировать, находится в том
же файле в дескр иптора х <scr i pt> . Без этой июlюрмации файл
компилироваться не будет.

Управление динамической загрузкой многих


пользовательских элементов управления (портальные
каркасы)

Итак, мы разработали несколько пользовательсЮ1Х элементов


управления:

1. Header.ascx - верхний колонтитул


2. ТпnеDisрlaу.аsсх кнопка-ссылка, возвращающая
н еформатированную и форматированную дату-время

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

з. LinkTable.ascx - список гиперссылок


4. LinkTableExt.ascx - список гиперссылок с предварительным
анализом выбора пользователя (для этого создали свое событие)
S. MyControLascx - с применением промежугочных средств доступа к
настройкам внугренних компонентов
б. MyContro!Ext.ascx - с созданием общего свойства-ссылки на
встроенный компонент для доступа к любым его членам
7. MyControlDynamic.ascx - то же самое, что и MyContro!Ext.ascx,
только применяли способ динамической загрузки
пользовательского элемен та на тестовую страницу

Для каждого из этих элементов управления разрабатывалась своя


тестовая страница, на которую элемент управления помещался

декларативно. Только в последнем случае мы сам пользовательский


элемент не изменяли, но на тестовой странице создавали его
динамически (программно). Теперь давай те на примере р ассмотрим
вопрос, когда на страницу н ужно поместить программно сразу

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

• ~Создайте новую страни ц у DynamicUserControls.aspx с


р аздельны м кодом и сделайте ее стартовой
• ~ раскрывающемся списке панели Properties выберите элемен т
DOCU ME NT и задайте его свойству T i tle значение
Порталь ны е к ар к асы

• ~ режиме Design пом естите с вкладки S tапdагd элемент Рапеl


и присвойте ему имя Panel1 (оно генерируется автоматически).
Этот элемент БУдет служить контейнером для других элементов
управления, в том числе и для пользовательского

• ~ оместите внугрь контейнера Panel 1 друг за другом по


вертикали стандартные элементы

о Dr op DownList с автоматически сгенерированным

именем Dr opDown Li st1 - для выбора загружаемого в


контейнер пользовательского элемента управления
о PlaceHolder с автоматически сгенерированным именем

PlaceHolder1 - для позиционирования в контейнере


пользовательского элемента управления

о Labe l с автоматически сгенерированным именем Labell


- для отображения имени файла, И 3 которого в контейнер

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

загружен пользовательский элемент ynравления

По большому счету нам в данном примере безразлично, какие имена


будуг иметь зкземпляры до черних элементов. Однозначно различать их
в коде мы можем по най де нным ссылкам. Сс ылки , в свою очередь ,
будем искать в именованном контейнере по типу до чернего элемента ,
поскольку пом е щенные нами элементы имеют разный тип. Но сама
оболочка Visua! Studio 2005 требует, чтобы на странице не было
декларативно объявляемых дескрипторов с одинаковыми значениями
1О .

• ~ роследите в дескр ипторном представлении страницы, чтобы


ни один из элементов, включая контейнер , не имел атрибугов
Wi dth и Height , ограничивающих свободную рQсширяемость
до черних элементов

Заметим , что контейнер Рапе 1 1, как родитель, по умолчанию будет


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

Ранее мы перечислили пользовательские элементы ynравления ,


которые создали в да нной работе. Выберем несколько из них дл я
динамического размещения. Имена этих элементов нужно занести в
список DгорDоwпList1. Пусть это БУдУГ элементы:

1. Header.ascx - Верхний колонтитул


2. ТпnеDisрlaу.аsсх - Кнопка ' время -дата '
З. Liпkтаыeаs схx - С писок гиперссылок
4. Liпkтаыeхt.аsсхx - Контролируемый список гиперссылок
5. MyControLascx - С настройкой внугренних компонентов

• r;.:.=выделите объект DropDownL i st l в контейнере Р1асе l и


заполните декларативно е го свойство I tems так
Декларативные настройки объекта DгорDоwпList1

Items[i] Text Va!ue


I tems [ О ] (None) None
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Items[ l ] Верхний колонтитул HeaderTest . asc x


Items[2] Кнопка 'в ремя -дата ' T i meDisplayTest . asc x
Items[3] С пи сок гип ерссылок L i nkTableTest . ascx
Контроли р уем ый
Items[4] L i nkTableExtTes t. ascx
сп исок гиперссылок

С настройкой
Items[5] внугр е нних MyCon t rolTest . ascx
компонентов

• ~ скрытом поле Value мы указал и имена файлов , которые в


БУдущем должны будем создать
• ~становит е для элемента DropDownList1 его свойство
AutoPostBack в значение True , чтобы обес п еч и т ь постин г
страницы при выборе польз о вателем нужной опции

Будем с чи тать, что один из трех ста н дар тны х элеме нт ов управления
кон тейнера, а именно с пи сок, мы заполнили деюыративно. Два других
элеме нта кон тейнера будем за полнять прorра мм но.

Таким образом, оди н ко н тей н ер мы по чт и н астроили . Но мы .хоти м


размести ть на странице три таких контейнера, чтобы иметь
возможность в каждый ИЗ ни х програ мм но загружать выбранны е через
список DropDownList l пользовательские элемен ты управле ни я. При
этом мы хотим убеди ться , что о ни ра ботают н еза ви симо д руг от друга и
каждый делает то, что долже н пугем реагирования на свои собственные
события .

• ~ режиме Design тестовой страниц ы разместите по


верти кал и друг за другом три копии контейне р а Place l вм есте с
е го до ч ер ними элементами . Про следи т е, чтобы ко нте йн еры
имели имена Panel1 , Panel2 , Panel3
• ~ ерез р аскрываю щийся список панели Properties выд ел яйте
п оследо в ател ьно каждый кон тейнер Panel1 , Panel2, Panel3
и н астро йт е и х свойства та к
о BackColor=Web/Gainsboro
о BorderWidth=lpx
о HorizontalAlign=Center
о BorderStyle=Ridge
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

о EnableViewState= " False "

Мы з акончи л и эта п про екmUРО6анuя страницы дл я да нн ого п ри м е ра .


Д е скрипторное п редс та в л ение с траницы должно б ыть таким

<%@ Page AutoEventWireup= ''true '' CodeFile=''DynamicUseгControls . aspx . cs'


Language="C#" % >

<html xmlns="httр ://www.wЗ.огgl 1 999/xhtml">


<head id= 'Head l " nmat= "server">
< title > Портальные кapKacbI </title >
<lhead >
<body>
< fопn kl ="fопnl " runat="server''>
<div>
<asp:Panel ID="Panel1 " runat="server" BackCo lor= "Gainsboro " Border:
Horiw ntalAlign= "С enter" ЕnaЬ Ie ViewS tate= "F alse ''>
<asp:DropDownList ID= ''DropDownList1 '' ruпа t="sеrvег" AutoPostB
<asp :ListItem Value= ''N o ne">(N опе )</asp:ListItem>
<asp :ListItem Value= 'HeaderTest.ascx''> Верхний колон ти тул </а
<asp :ListItem Value= 'TnneDisplayTest. ascx''> Кнопка ' время- дат,
<asp :ListItem Value= ''LinkTableTest.ascx''>C писок гиперссылок
< asp :ListItem Value= ''LinkTab lе ExtTest.ascx"> Ко нтроли р уемы й
<asp:ListItem Value= 'MyControrrest.ascx">C настройкой внугр
</asp:DropDownList><br />
< Ьг />
<asp:P laceHolder ID= ''P IaceHolderl " runat= "server''></asp РвсеНоl
< Ьг />
<asp:Label ID= ''Label1 '' ruпаt="sеrvег" Text="Label"> </asp:Label><!
< Ь г />
<asp:Panel ID="Panel2 " runat="server" BackCo lor= "Gainsboro " Border:
ЕnaЬ lе ViewS tate= ''F а Ise" Н о riw ntalAlign= "С enter''>
<asp:DropDownList ID= ''DropDownList2 '' ruпа t="sеrvег" AutoPostB
<asp :ListItem Value= ''N o ne">(N опе )</asp:ListItem>
<asp :ListItem Value='HeaderTest.ascx"> Верхний колон ти тул </а
<asp :ListItem Value= 'TnneDisplayTest. ascx"> Кнопка ' время- дат,
<asp :ListItem Value=''LinkTableTest.ascx''>C писок гиперссылок
< asp :ListItem Value= ''LinkTab lе ExtTest.ascx"> Контроли р уемы й
<asp:ListItem Value= 'MyControrrest.ascx">C настройкой внугр

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</asp:DropDownList><br 1>
< Ьг 1>
<asp:P laceHo!der ID=''P IaceHo!der2 " runat= "server''></asp РвсеНо!
< Ьг 1>
<asp :Labe! ID=''Label2 '' runat= "server" Text=''Labe!''></asp:Labe!><!
< Ьг 1>
<asp:Pane! ID=' 'РапеLЗ'' runat="server" BackCo!or="Gamsboro " Border:
ЕnaЬ!е ViewS tate= ''F а Ise" Н о rizo ntalAlign= "С enter''>
<asp:DropDownList ID =''Dгор DоwnListЗ'' runat="server" A utoPostB
<asp :ListItem Value=''N o ne">(N опе )</asp:ListItem>
<asp :ListItem Value='HeaderTest.ascx''> Верхний колон титул </a
<asp :ListItem Value='TnneDisp layTest. ascx''> Кнопка ' время- дат,
<asp :ListItem Value=''LinkTab!eTest.ascx''>C писок гиперссылок
< asp :ListItem Value= ''LinkTab!e ExtTest.ascx"> Контроли р уем ы й
<asp:ListItem Value='MyControrrest.ascx''> C настр ойко й внугр
</asp:Drop DownList><br 1>
< Ьг 1>
<asp :PlaceHo!der ID=''P IaсеНо!dегЗ " runat= "server''></asp РвсеНо!
< Ьг 1>
<asp :Labe! ID =''LаЬеlЗ '' runat= "server" Text=''Labe!''></asp:Labe!><!
< Ьг 1>
</div>
</form>
<!body>
<lhtml>

Листинг ДеСlCрипторное представление страницы

DупаmiсUsеrСоntrоls.аsрх

• ~ыполните сф:J р мирован н ую страницу

DynamicUserCo ntrols.aspx, чтобы убедиться в работоспособности


настро ек режима пр оектирования. Результат на дан н ом этапе
долже н бы ть таким
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

11 Портальные каркасы - Мicrоsоft Internet Ех ..


Fie Edit V"VI F аvопtes To~o Нф

т .. т liiII @J GI ~ se"ch tжJ Favorites

I (NOne) 3

I (NOne) 3

I (None)

31
- - ..:J
Lосзl in1J" anet

Таким об р азом, мы выполнили ин терфейсн ую заготовку портальных


каркасов на тестовой странице. Теперь пришла пора наполнить их
функц и ональностью, которая бы обес п ечила ко н тей н ерную загрузку
выбранных пользовательских элеме н тов ynравления. Э ту
функц и ональность мы обеспечим, кодируя файл
DynamiсUsеrСопtrоls.аsрх.сs скрытого кода ст р аницы. Ниже мы убедимся ,
что программно загруженные в по ртальн ые каркасы пользовательские

элемен ты ynравления обрабатывают свои события точ н о также , как


будто бы каждый из н их находится н а отдельной тестовой стран ице .

• IJ$Откройте н а редакти рование файл DynаmicUsеrСо пtrоls.аsрх.сs


• ~Добавьте в масс Dynam i cUse r Co ntr ols следУЮЩИЙ код

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

usiпg System;
usiпg System.Data;
usiпg Systеm. С опfigша tiоп;
usiпg System. Collections;
usiпg System. Web;
usiпg System. Web.Security;
usiпg System. Web.UI;
usiпg System. Web. UI. WebControls;
usiпg System. Web. UI. WebControls. WebParts;
usiпg System. Web. UI. HtmlControls;

public partial class Dynamk:UserControls : System.Web.uI.Page


(
protected void Page_Load(object sender, EventArgs е)
(
11 Загружаем портальные каркасы
М yLoadControls(Panel1);
м yLoadControls(Panel2);
М yLoadControls(P апеlЗ);
}

11 Вспомогательная функция
private void MyLoadControls(Control сопtaшегРапеl)
(
11 Объявляем вспомогательные ссылки на ин терфе йсны е
11 элем ен ты текуще го контейнера
DropDownList list = null;
PlaceHok:ler ph = null;
Labellbl = null;

11 П е ребир аем все дочерние э леме нты текущего


11 контейнера и ищем ссылки на объекты дочер ни х
11 интерфейсных элементов п о их типа м
foreach (сопtгоl си! iп сопtашегРаneL Со пtrоls)
(
if (ctrl is DropDownList)
list = (DгорDоwпList)сtr~
else if (си! is PlaceHolder)
ph = (PlaceHolder)ctrl;
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

e~e if(ctrl ~ Label)


Ibl = (Label)ctr~
)

// Берем инqюрмацию из выделенного


// элемента списка текущего контейнера
strmg IstValue := list.Se!ectedItem Va!ue;
strmg IstText := list.Se!ectedItem.Text;
lbL Text = '"';

// Заполняем текущий контейнер.


// Проверяем наличие нужного расширения
if (~tVаlllе.Епdswith(".аsсх '))
(
р h. С о ntro 15. Add(P age. Load С о ntro ~Ist Value ));
lbLText = "З агрузили: " + IstVa!ue + "- "+ IstText;
}
}
}

Листинг Код файла DynamicUserControls.aspx.cs

Создадим пользовательские элеме нты управления, которые реализуют


пользовательский интерфейс и функциональность, использованную
нами при выполнении прим еров в тестовых страницах. Из этих
тестовых страниц мы их и п еределаем.

• ~ пан ели So!ution Explore выделите при нажатой ЮIaвише Ctr!


следУЮщие файлы
о HeaderTest.aspx
о TuneDisplayTest.aspx
о LinkTabIeTest.aspx
о LinkTabIeExtTest.aspx
о MyControIГest.aspx
• ~ыполните команду Сору затем Paste (на верхнем узле
пр оекта) контекстного меню
• ~ рисвойте копиям те же самые имена , только с расширением
.ascx
о HeaderTest.ascx
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

о TuneDisplayTest.ascx
о LiпkТаЫеТеst. аsсх
о Liпkтаы Ехtтеst.аsсхx
о M yC ontro IГe st. ascx
• ~Откройте новые файлы в дескрипторном режиме и замените
директиву @Page н а @Control , все остал ьны е атрибугы
директивы @Page оставьте пр еж ни м и . Теперь это будуг не
страницы, а польз о в ател ьские э леме нты управления. Директиву
@Reg i ste r с ее атрибугами остав ьте в покое
• ~дали ть и з кода все дескрипторы <html> , <body> ,
< f o r m> , <head> и за крыв аю щие их дескрипторы.
• г;.:.='Для н ов ых файлов >I< .ascx откройте файлы скрытого кода
>1< .ascx.cs и замените в объявлении масса и м я наследую щего
масса с" Sys t em . Web . UI . Page " на "
Sys t em . Web . UI . Use r Cont r ol " Остальной код массов
оста нется пр еж ни м.

Мы зако нчи ли выпол н е ни е примера. Код т естовой страницы пр и


очередной за гр узке БУдет пр огр амм но создавать сво и польз овател ьские
э л емен ты управления для каждого контейнера Рапеl и р азме щать и х в

э л емен тах PlaceHo l der .

• ~ыполните страницу Dynamk:UserControls.aspx и испытайте ее .


Р езул ьтат будет прим ер но таким
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

11 ПОртальные KapKaCbl - Мicrоsоft Internet Explorer


---------------------------- -

I Ве рхн ий кол о нтит ул

: HeaderT est. ascx -

I Список гип е рссыл о к

Список жизненно важных гиперссылок

..: Ссылка N<> 1 К Большому Биллу


..: СсылкаNо2 к автошколе "Диалог-Сервис"
r;.: СсылкаNQ3 к затычке JavaScript

з зишr: LinkTableTest.ascx - СШIСОК пше сс ьшок

I Кн о пка ' b p eMR-д ата'

19:02:44

Сегодня пятшща, 23 марта 2007


Текущее время 19:02:44

з зишr: TimeDis lа Test.ascx - Кнопка 'в емя- дата'

1111 ГГГ ~ Local htr~t

Ин огда при отладке приложения оболочка начинает сбоить, выдавая


н епонятные ошибки. Может помочь п ерезапуск VlSua! Studio 2005 и ли
удален ие файла web.co nfig, все равно оболочка создаст его

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

автоматичесЮ1 при очередной компиляции. Пока нам этот файл не


жалко, потому что его настройками мы все-равно еще н е занимались.
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

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

Элеме н т управления MuhMew. Ynравление отображением


пр едставлений. Элемен т управления Wizard. События элемента Wizard.
Стили элемен та Wizard. Ша блоны элемен та Wizard.

Файлы к лекции Вы можете скачать здесь скачать:

httр :l/оkl.iпtuit.ruldераrtmeпtJiпtеmеtJрrаsрпеtJ7 /07 _ WebSiteS.zip

Два высокоразвитых элемента управления Ми1 t i V i ew и Wi zard


по зволяют организовать для пользователя имитацию сложного

мно гостранично го пр осмотра. Они содержат встроенные средства


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

Элемент управления MultiView

Элеме н т уп р авления Ми] t i V iew по зволяет организовать ст р аницу в


виде множества вюыдок. Каждая вкладка может содержать свой
пользовательский интерфейс и обеспечивать свою форму
пр едставления одной и той же информации пользователя .

• ~Создайте новый проект с именем WebSi t e5 , выполнив


командУ меню FilelNewMebSite и определив пар аметры масте р а
так
в.м. СН"",,,В Про,раммupoвtJNШ' NQ ASP. N ET

.1J ~
T...-rpl ..,... Гf! ;:;:

~ ~ ~ ~
АЧ' r.ET \', 00 ASP J-ET W3!J ж-sma l Vleb ЕrrjЖ)l Web
Sib SOfYEO Si'" stoc"" K~ Sib

I~ Ь:ОП A5P, rEТ Vieb s.te


Loc<Otoo : "IFi~>~~=,"О"::---::J:ll mtm-.,."",iЦ'i!I'"Ш;;;-М!§iI 3 [:'-0"'''' .. ,

I v ~"'" CI

• r;:;nереименуйте, для тренировЮ1 смелости в отношении


модификации кода, сгенерированную страницу Default.aspx в
MultiViewControLaspx, в ее демарации @P a ge введите новое
значение параметра Inhe ri ts= " Mu l t i ViewCont r o l", а в
файле скрыто го кода переименуй те масс в Mul t i Vi ewCon t rol
(или не п ереиме н овывайте ни масс и Inhe ri ts , ни страницу,
но я будУ говори ть об этих име н ах и код при водить С их
использованием)
• ~ оместите на страницу в режиме редактора Design из вмадЮ1
Standard ком п онент-кон тейнер Ми1 t i Vi ew
• ~ оместите на ст р аницу в режи ме редактора Design внугрь
созданного объекта Ми 1 t i V i ew 1 из той же вмадки Standard три
экзем п ляра компонен та Vi ew. Компонент Vi ew н азывают
предсmавленuем данных

в результате оболочка сге н ерирует следующий дескрипторный код

<%@ Page AutoEventWireup =''true''


Со d е Filе =' 'МultiViewС опtrоLа s р х. с s''
Inhеrпs=' 'МultМеwС опtrо l'' Language="C#" % >

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

<html xmlns=''httр ://www.wЗ.огgl1999/xhtml'' >


<head nmat="server">
<title>Untitled Page</tide>
<lhead>
<body>
< fопn ю="fоrml" runat="server''>
<div>
<aspMulttView ID =''М ukМе w l '' nmat="server''>
<asp:View ID=''Viewl '' nmat="server">
</asp:View>
<asp:View ID=''View2'' nmat="server">
</asp:View>
<asp:View ID=''ViеwЗ'' nmat="server">
</asp:View>
</asp:MuluView></div>
</form>
<!body>
<lhtml>

Листинг Дескрипторный код файла MultiViewControl.aspx

• Г;;:;=Запустите приложение и вы получите чистый экран броуэерй ,


п оскольку созданные вкладки - пр едставле ния еще н е были
заполнены интерфейсными элементами и показать им нечего

Заме чани е. Пр едстав ле ния V i ew можно добавлять и программно п о


мере необходимости (как и любой другой элемент управления). Для
этого нужно создать экзем п ляр (например, V i ew l ) нового
представле ния и добави ть ссылку на него в коллекцию Vi ews
экземпляра (например, Mul t i Vi ewl ) элемента Миl t i V i ew с
помощью Mult i V i ewl . V i ews . Add(Viewl) и ли

Mult i Viewl . V i ews . AddAt ( i nde x, V i ew l ) . Свойство Vi ews


определено в классе

Sys tem . Web . U1 . WebCon t r ols . ViewCollec tion , который и


имеет указанные методы Add () и AddA t ( ) . Но мы БУдем для
простаты использовать декларативный способ этапа проектирования.

Web-форма в оболочке после наших действий БУдет и меть вид

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

/ MultiViewControl,aspx l ,., х

,.- MultiViewl
, ~

i" Viewl

View2
-
.- View3

,
Visual Studio 2005 во время проектирования показывает все
представления View в раскрытом виде , но на этапе вы п ол н ени я на

странице может отображаться только одно ИЗ них, которое раскроет


пользователь . Кажд ое представление можно редактировать в оболочке
точно также , как любую часть обычной страницы .

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


или нет, определяется свойством MultiView . ActiveViewlndex,
доступном и на этапе проекmUРО6анuя и про граммно. Если значение
это го свойства равно "-1 ", то п ри начальной загрузке страницы ни одна
из ВЮJaДОК н е БУдет раскрыта. Если свой ство установлено в н оль , то
будет раскрыта первая вклад ка и т. д .

Давайт е прод олжим выполнение нашего примера и н а п ол ни м


представления каким-ниБУдЬ содержимым .

• r;:;n оместите в корневую папку сайта какой-н и будь рисунок


щадящего Web-qюрмата ( >1< .gif, .... jpg, >1< .рпg ). Один из вариантов
ри с унка, файл MyPhoto.jpg, пр ила гается ...
• Г;:;=П оместите в пред ставле ни е V i ew l из вкладки Staпdагd
компонент Image (контейнер для рисунка) и декларативно
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

настройте его так:


о I mаgеU r l~ " -/МуРhо t о . jрg " . Символ (тил ьда)
обозначает корень виртуального каталога сайта
• ~ оместите в пред ставление V i ew2 какой - нибу,ць текст
• ~ оместите в представление View3 элемент Calenda r из
ВЮJaДКИ Standard и настройте е го внеlШlИЙ ви д
• ~ы делите объект Mult i V i ew l и установите его свой ство
ActiveViewlnde x в значение ноль, чтобы при начальной
загрузке страницы было открыто п е рвое пр едставление

Управление отображением представлений

Вариант 1

Как один из вариантов ynравления вкладками можно дать


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

• ~ оместите на qюрму страницы вперед и эл ем ента


Mul t i V i ew l компонент Dr opDownLi s t из вкладки Standard
• ~становите для с пи ска свойство AutoPostBack в значение
True , чт обы при выборе нового пункта автоматически
выполнялась обратная отсылка
• ~ы делите эюемпляр DropDownL i s tl и ч ерез панель
Prop erties в режиме Even ts создайте обработчик события
Selectedlnde x Changed

Дескрипторное пр едставление страницы бу,цет таким

<%@ Page АutоЕvе пtWirе uр=''truе''

СоdеF ilе="МuhМеwСо пtго L аsрх.сs"


Inhег its= ' М ultiViеwСопtrоl" Lапguаgе="С#" %>

<html xmlns="httр ://www.wЗ.огgl 1 999/xhtml" >


<head nmat="server">
< title >Элеме н т ynравле ни я м ножеством п редстав ле ний </tit1е>
<lhead>
'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<body>
< fопn kl="fопnl" runat="server''>
<div>
<asp:DropDownList ID= ''DropDownList1 '' runat="server"
AutoPostBack='True"
О пS е lected IndexC hапgеd = ''Drop DownListl_S е lected IпdехС hanged I

</asp:DropDownList><br 1>
<aspMuluView ID='MuhMewl " nmat="server" ActiveViewIndex="O">
<asp:View ID::::''Viewl '' runat= "server''>
< Ы > Мое qюто < lhl >
<asp:Image ID='1magel " runat= "server" lmagеUгl= "~lМуРhоtо.jр:
</asp:View>

<asp:View ID::::''View2'' runat= "server''>


< h1 > Мои стихи < lhl>
<р>

У Лукоморья дуб зеленый < Ьг 1>


Златая цепь на дУбе том < Ьг 1>
И д нем и ночью кот ученый<Ьг 1>
Все ходит по цепи кругом
</p>
</asp:View>

<asp:VJew ID= ''ViеwЗ'' runat= "server''>


< h1 > Мой календарь < lhl >
< аsр:Саlепdаг ID =''С аlепdагl ''
runat="server" BackColor=''#C OFI
BorderColor= 'Red " BorderStyle=''Ridge''>
</asp:Calendar>
</asp:View>
</asp:MuluView>
</div>
< /foпn>
<!body>
<lhtml>

Листинг Дескрипторный код файла MultiViewControl.aspx

• r;.:;=поместите в файл МuhiViеwСопtrоLаsрх.сs следУЮЩИЙ код


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

usiпg System;
usiпg System.Data;
usiпg Systеm.Сопfigшаtiоп;
usiпg System. Web;
usiпg System. Web.Security;
usiпg System.Web.UI;
usiпg System. Web.UI.WebControls;
usiпg System.Web.UI.WebControls.WebParts;
usiпg System. Web.UI.HtmlControls;

public partial class MultiViewControl: System.Web.UI.Page


(
protected void Page_Load(object sender, EventArgs е)
{
11 Заполняем список только при первом запросе страницы,
11 а потом все бу,цет сохраняться в состоянии вида.
11 Иначе список всегда будет переустанавливаться в начало
if (!lsPostBack)
{
11 Подсоединяем коллекцию с ВЮJaДками к списку
DгорDоwnListl.DаtаSошсе == MuluViewl.Views;
11 Назначаем идентификатор , значениями которого
11будуг заполнены поля 'Text" списка
DropDownListl.DataTextField == "ID";
11 Заполняем список подсоединенными данными
DгорDоwnListl.DаtаВiпdО;

11 Отображаем первое представление


MultiViewl.ActiveViewlndex == О;
11 Синхронизируем список
DropDownListl.Selectedlndex:= О;

11 Выделяем текущую дату


Calendarl.SelectedDate := DаtеТпnе.N ow.Date;
Calendarl.SelectedDayStyle.BorderStyle:= BorderStyle.Solid;
}
}

11 Обработчик события выбора в списке

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

protected void DropDownList1_SelectedlndexChanged(object serкler, Event


{
MultiViewl.ActiveViewlndex:= DropDownList1.Selectedlndex;
}
}

Листинг Код файла MultiViewControl.aspx.cs управления

представлениями

• ~ыполните страницу, результат долже н быть не менее


лучезар н ым, чем этот...

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

11 Элемент управления множеством представл ..


FM
e Edlt y~w Favorites ТОols Help
t2t search @] Favorites
: 1041ANеЬSitе5МultiViеwСоп-о-, .....

Мое фото

Local in-o-.:net

Вариа н т 2

В обработчике события Page Load () мы , для тренировки , встав и ли


КОД, чтобы пр и п ервом за п росе страницы список п ро граммно
заполнялся значе ни ями атрибугов ID представлений. Это го можно и не

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

делать, если вручную на этапе праектuраванuя заполнить свойство


1 te ms списка более осмысленными именами.

Мы, также , назначили для списка Аи toPos tBack= " True ", чтобы он
индивидуально осуществлял обратн ую отсылку Ну; а если на странице
будет мно го интерфейсных элементов с возможностью постинга ,
которые долже н БУдет нас трои ть пользователь. В этом случае будет
расточительно, что каждый элемент интерфейса при настр ойке
индивидуально посылает страницу на сервер для обновления. Лучше
предусмотреть отдельную кнопку; которая отдаст команду браузеру на
обратную отсылку после настройки всех интерфейсных элементов .
Выполним эти модификации на новой странице.

• Г;;:;=Через панель Solution Explorer выполните копию страницы


MultiViewControLaspx и присвойте копии новое и мя
Mul t i Vi ewCont r oll . asp x .

Обратите внимание , что файл кода .cs автомат и чески копируется и


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

связан со страницей . Правда, его можно ско пировать отдельно, то гда он


переименовывается.

• г;.:.=выполните команду меню Window/Close АН Documents, чтобы


закрыт ь все прежние окна редактирования рабочей области
оболочки
• Г;;:;=Откройте новую страницу MuluViewControl1.aspx на
редактирование и выполните команду меню Website/Set А5 Start
Page, чтобы сделать теперь ее стартовой при запуске и з оболочки
• ~ыделите список через панель Properties и сбросьте его
свойство AutoPostBac k в False
• r;:Fчерез раскрывающийся список в верхней части панели
Properties выделите объект Mul ti Viewl и задай те
ActiveViewInde x =- l, чтобы ни одно представление при
первой за гр узке стра ницы у пользователя не было раскрыто
• r;;:;=в файле MultiViewControll.aspx.cs полностью очистите
об р аботчи к события Page Load () , код которого в предыдущем
прим ере прогр амм но заполнял список (можно полностью Удали ть

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

этот обработчик, н ам он здесь не понадобится)

Сейчас мы должн ы заполн и ть список декларати вно (на этапе


проекmuрованuя) .

• u;.;rвыделите список и за п олните его свойство 1 tems так


Декла р ативные настройЮ1 объекта DropDownList1

Items[iJ Text Value


1 te ms [О] Моя ф:нографи я не имеет значения .. .
1 te ms [ 1 ] Мои стихи не имеет значения .. .
1 te ms [2] Встроенный кале н дарь не имеет значения .. .
• ~Добавьте на новую стра н ицу сп рава от с п иска кно п ку Input
(Submi t) из вкладЮ1 НТМL п анели Toolbox (вос п ользуемся
п ростой кнопкой) и задайте ей Value=Show i
T itle= PacKp blTb вкладку
• ~3апустите приложе ни е и неизменяя сп исок п он ажи майте
кнопку Show.

Ни чего не п ро и сходи т, пока в списке мы не выбирем новый п ункт.


Только после этого свойство Mul ti Viewl . Acti veV i ewIndex
п римет отл и чное от -1 значение и п редставления при обратн ой отсылке
н ачнуг работать. Чтобы и с п рав и ть это , нужно код п рисвое ни я значения
свойству ActiveViewIndex п ереместить в обработчик нажатия
кнопЮ1.

• IJ$Создайте обр аботчик для кн оп Ю1 1 D=Sub mi t 1 двойным


щелчком на ней мышью

Мы видим, что оболочка создала код заготовЮ1 JavaScript -с ц е н ария ,


который мы должны зап ол н ит ь и который ст р аница готова п осылать на
клиентсЮ1Й броузер. Чтобы не в н икать в JavaScript приведем в свое
оправдание аргумен т, что поддержка сценариев JavaScript - дело
н енадежное, поскольку пользователь может в своем броузере ее
отключ и ть.

• ~дали те созданный оболо ч кой предыдущим действием код


JavaScript -сценария. Для это го в режи ме Source помести те
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

те кстовый курсор редактора внугрь блока кода < зе r i pt


lang uage= " javaser i pt "
t ype= " te x t/ j avascript " > .. I .. </ scr i pt> и в нижней
ча сти р амки окна редактора щел кните на кнопке <script>. Весь
выделенный код можно Удалять
• ~далите из дескриптора <i nput> кнопки Submit1
one li e k =" retu r n Subm i tlonel i c k( ) ",
сгенерированный оболочкой
• Г;:;=Щел кните на Submit l правой кнопкой мыши и выполните
командУ RШl As Server ControL Этим действи ем в дескриптор
<i np ut > будет добавлен атри буг runat= " se rv e r", который
заставит AS P. NET за п ус кать обработчик кнопки (если мы его
предУСМОТРИМ) , если с броуэерй с обратной отсылкой будет
прислан о событие , что кли ент щелкал на этой кнопке
• ~ы делите список Dr opDownL i st l и чере з п а нель Properties
в режим е Events очистите пол е события
Selec t edlnde x Cha n ged
• ~Двойным щелчком на , теперь уже серв ерной , кнопке Submit1
создайте дл я нее обработчик в файле MultiViewC ontroll. aspx.cs
• r;:;nеренесите код обработчика события
Selec t edlnde x Cha n ged в КОД нового о бработчика , а старый
обработчи к удал ите

в результате код файла будет таким

using System;
using System.Data;
using Systеm. Со пfigшаtiоп;
using System.Web ;
using System. Web.Security;
using System. Web.UI;
using System. Web.UI. WebControls;
using System. Web. UI. WebControls.WebParts;
using System. Web. UI. HtmlControls;

public partial class MultiViewControl: System.Web.UI.Page


(
11 Обработч ик события на кнопке Submitl

m
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

protected void SubmitCServerClick(object send er, EventArgs е)


{
MultiViewl.ActiveViewlndex:= Dro pDownList1 .SelectedIndex;
}
}

Листинг НОВЫЙ КОД файла MultiViewControll.aspx.cs

• ~ыполните страницу

Теперь по прибытию на сервер обратной отсылки система ASP.NET


распознает присланное событие щелчка на кнопке. Свойству
Mul t i Viewl . Acti veV i ew l nde x в обработчике события кнопки
присваивается значение выбранной поль зователем опции списка.
Клиенту страница отправляет СQЦержимое вклil,цки , соответствующей
его выбору.

Добавление в представления функций навигации

в предыдущих при мерах мы знакомились с механизмом р аботы


элемента МИl t i Vi ew. Мы использов али для смены ВЮJaДОК внешний
по отношению к Ми1 t i Vi ew элемент списка. Но Ми1 t i Vi ew имеет

собственные средства для перехода по своим ВЮJaДками. Рассмотрим


эти возможности.

Серверные элементы Виttоn , IтageButton , LinkBu t ton


реализуют интерфейс
Sys tem . Web . U1 . WebCon t r ols . IB u t t onCont r o l, от которого

наследуют способность генерировать не только событие Сl i c k, но и


событие Coтmand . Такие элементы управления называются
кнопочными. Они реали зуют ряд полезных свойств интерфейса, таких
как CommandArgu ment , Co mmandName и д р.

m
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

ObJect Browser .... ~ Х

Вrowse: AI Components •

.~ CommandAгgument
; .~ СоттandNате
i""b Base Types I.. ·~ PostвackUrl
~"1b Derived Types i-~ Text
riJ···4$ Вutton I.. ·~ ValidatJonGroup
$. .4$ ImageВutton ,_о , Cl,ck
r4J ...4$ LinkВutton
!.... '1 соттаnd

в свою очередь, элемент управле ни я М иl t i Vi ew содержи т


об щедо ступные пер еме нные (поля) , которые ожидают поступления
определенных команд, чтобы Миl t i V i ew соответствующим образом
и х исполнил .

Ob)eCt Brow$et" ...... -!;::; х

BrOW$e: ,1. 1Component:3 .. .. Ъ f::jJ .

createCoo1yo ~c:fec1j oo О

~ GetActiveVlew O
.~ МJ I1jV~W O

CflAc1jveV~wCh.:n;led (Sy:;te m ,EverltAr gз)


CflБLkЫеЕVerlt(cbje ct, Syste m,EVerltArgs)
SetActiYeView(Sy~tem, Web.UI. W ebCootrd ~, V~w)

ActiVeVieW!гdex
Enatk1Пеm h;)
V..ews
{J Nextv~wCommard\Jame
~ FТeVio..lsVi€wComma l"d Name
OQO SWitchViewByIOComm zrd.j ame
{J SW itchViewBy Irde xComm cп:f.Ja me
' AcbYeY~

Ниже приведены команды , которы е ожидает Миl t i Vi ew.

Имена кома н д , которые может распознать MultiView


аЛ.
Поле Ждет команду

Пере:

ш
В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

слею

пред(

Ne x tViewCo mmandName Ne x tView Кома


з н аче

Co ml1
КНО П I

Пере:
пред]

пред(

PreviousViewCommandName Pr evView Кома


з н аче

Co ml1
КНО П I

Пере:
пред(

з н аче

и д ен '

Sw i tchV i ewByIDCommandNa me SwitchViewByID пере)

свой(

Co ml1
КНО П I

упра l

Пере:
пред(

о п ре/

ин д еl

Sw i tсhV i еwВуlпdе х Соm m апdNаmеSwitсhViеwВуlпdе х пер ~

свой(

Co ml1
КНО П I

упра l

Вос п ользуемся опис а нным механизмом в нашем примере. Развитие


п рим е ра выпо л ним на копии .

• ~ панели Solution Explorer с копируйте страницу


MultiViewControll .aspx, п рисвойте копии имя

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Mul t i ViewCont r ol 2 . asp x и сделайте эту страницу


стартовой
• ~ з вклil,ЦЮ1 Standard п ан ели Toolbox поместите в первое и
последнее представления по одной сервер ной кнопке Button , а
в среднее - д ве кнопЮ1

• ~ астройте кнопки как показано в таблице

Настройка кнопок навигации на


пред ставлениях

Представление Свойство Значение

IO b t nNe xt O
Views[O ] Te x t Ne x t >
Co mmandNameNe x tV i ew
IO b t nPrev l
Te x t < Pre v
Co mmandNameP rev V i ew
Views[l ]
IO b t nNe xtl
Te x t Ne x t >
Co mmandNameNe x tV i ew
IO b t nPrev2
Views[2 ] Te x t < Pre v
Co mmandNameP rev V i ew

у нас в обработчике кнопки Submi t 1 выполняется синхронизация


выбранного пункта списка и активного пред ставления. Если те перь
осуществлять переход по пр едставлениям введе нными кно п ками

навигации , то об р атной синхронизаци и представлений со списком не


будет. Исправим это ...

• ~становит е редактор страницы в режим Dе s igп


• r;:;=в пан ели Properties в
верхнем раскрывающемся списке
выберите объект Mul t i Viewl , п еревед ите пан ель в режим
Events (кнопка с пиктограммой мол ни и) и двойным щелчком на
поле события ActiveV i ewChanged создайте обработчик,
который запол ни те кодом си н хронизации с пи ска
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

в результате файл п одце р жки страни ц ы должен быть таким

using System;
using System.Data;
using Systеm. Со пfigша tiоп;
using System.Web ;
using System. Web.Security;
using System. Web.UI;
using System. Web.UI.WebControls;
using System. Web. UI. WebControls. WebParts;
using System. Web. UI. HtmlControls;

public partial class MultiViewControl: System.Web .UI.Page


(
// Обработчик соб ытия на кнопке Submitl
// С ин хро ни зация представлений со списком
protected void SubmitCServerClick(object sender, EventArgs е)
(
MultiViewl.Active ViewIndex = DropDownList1.SelectedIndex;
)

// С ин хро ни зация списка с представ ле ниям и


protected void Muh.iViewl_ActiveViewChanged(object sender, EventArgs е)
(
DropDownListl.SelectedIndex = MultiViewl.ActiveViewIndex;
)
}

Листинг Файл скрытого кода MultiViewContro12.aspx.cs

Фай л дескр ип то р но го пр едставле ни я БУдет та ки м

<%@ Page AutoEventWireup=''true''


CodeFile='MuhMewCo ntrol2.aspx.cs"
Inhег its=''М ultiViеwСопtrоl'' Language="C#" % >

<html xmlns=''httр://www.wЗ.огgl1999/xhtml'' >


<head nmat="server">
< title >Элеме нт управления м ножеством представлений< /title >
<lhead>
п,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<body>
< fопn kl="fопnl" runat="server''>
<div>
<asp:DropDownList ID=''DropDownList1'' runat="server''>
<asp :Listltem> Моя фотография < /аsр:Listltеm>
< аsр:Listltеm>Мои стихи </asp:Listltem>
<asp :Listltem> Встроенный календарь < /аsр:ListItеm>
</asp:DropDownList>

< inр и! id ="Submitl " type="submit" vаше="Shоw"


title=''PacKpbITb ВЮlадку" nшаt="sеrvег"
onserverclick="S ubmit C ServerClick " /><br />

<aspMultNiew ID='MuhMewl " nmat="server"


ОпАсtivеViewСhапgеd=''МultiViewl _АсtivеViеwСhaпgеd' '>
<asp :View ID=''Viewl '' nшat= "sеrve г ''>
<Ы >
Мое фото < lhl >
<asp:lmage ID='1mage l " runat="server"
l mageUrl="~lМyPho to.jpg" />< Ьг />
< Ьг />
< аsр:Вuttоп ID='Ъ tnNехtО " runat="server"
CommandName= 'NextView" Text='Next >" />
</asp:View>

<asp :View ID=''View2'' nшat= "sеrve г ''>

<Ы >
Мои стихи<lhl>
<р>

У Лукоморья дуб зеленый < Ьг />


Златая цепь на дУбе том < Ьг />
И д нем и ночью кот ученый<Ьг />
Все ходит п о цепи кругом
< /р >
< аsр:Вuttо п I D='ЪtnP геvl " nшat= "sеrveг"
Со пunaпdN ame=''PrevView''Text="< Ргеу" />
< аsр:Вuttо п I D='ЪtnNехt1" runat= "server"
Со пuпапdNаmе ="NехtViеw" Text='Next >" />
</asp:View>
m
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<asp:View ID =''ViеwЗ'' runat="server''>


<Ы >
Мой календарь<lhl >
< аsр:Саlепdаг ID ="Саlепdагl "
nmat="server"
BackColor=''#COFFFF'' BorderColor='Red"
BorderStyle='Ridge" />
< Ьг />
< аsр:Вuttоп ID= 'ЪtnPгеv2"
runat="server"
СОП1J1la пdN ame=''PrevView'' Text="< Ргеу" />
</asp:View>
</asp:MuluView>
</div>
</form>
</body>
<lhtml>

Листинг ДеСlCрипторное представление страницы

MultiViewContro12.aspx

• ~ыполните страницу и у6едитес ь, что все работает как н ужно


В.М. СН"",,,В Про,рйммupoвtJNШ' Na ASP.NET

11 Элемент управления множест ..


FMe Edlt y~.". Fаvопtеs Tools
Bxk т .. т ~ @) G'! ~ se"ch
hl:ljo:!~ocalhost:

I мои стихи iJ ShO\N

Мои стихи
у Лукоморья дуб зеленый
Златая цепь на дубе том
И днем и ночью кот ученый
Все ХОДИТ ПО цепи крутом

< Р г еу Next >

Loca in1J"anet

ХОРОШИЙ элемент, что и говорить . Но есть оди н существенный


недостаток. Поскольку хранится несколько представле н ий, то мы
должны быть готовы вер н угься к любому представлен ию, если его
повторно вызовет пользователь. Это значит, что мы должны сохранять
состояние вида всех п редставлен и й, в том числе и нев и димых в
данный момен т. Из-за этого элемен т п осылает на клиен тскую машину
большой объем кода состояния вида. О т этой не п риятности можно
избавиться, отключив свойство EnableV i ewState .

Еще одна особенность, о КОТОрОЙ стои т помнить. Элемент Ми1 ti V i ew


не является контейнером для имен элемен тов управления на вкладках .
Это значи т, что в пределах стра ниц ы все элементы управления должны
иметь ун и кальные значен ия иден тификаторов ID, и н аче компилятор
заблУдИТСЯ.
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Элемент управления Wizard

Элеме н т управления Wiz ard (масте р) является более развитым, ч ем


элемент MultiView. Он имеет богатую настраиваемую
функц и ональность, ВЮlючающую в себя

• Возможн ость п оследовательного отобр аже ния од н ого и ли


н ес колью1Х пр едставле ний
• Встроенные ююпЮ1 на в и гац и и
• Встроенное боковое меню со ссылками на выполняемые шаrn ­
вЮJ 3ДЮ1

• Ст и л и и шаблоны

Содержи м ы м шагов - ВЮJ 3Док мастера являются Web- и НТМL-элеме н ты


управления, обычно используемые при п остр ое нии страниц .
Ра ссмотри м п оследовател ьно свойства элемента управле ни я Wi zard
на пр имерах.

• Г;;:;-Добавьте новую страницу с именем Wi zardCon tr ol . азр х


и файлом отделенного кода. Н аз н ачьте ее ста рто вой
• ~ режиме Design редактора пом ест ите на страницу элемен т
управления Wi zard из ВЮJадЮ1 Standard пан ел и Too lbox

Б удет сгенерирова на така я загот овка

/ WizardControl,a5px* ~ J
ЕЕ го'

SteD
Steo 2
INext I
Дескри п торное п редставление за готовЮ1 БУдет таЮ1м

<%@ Page L апgua gе="С#" Аutо ЕvепtWirеuр =' 'truе''

С оd еF ilе='WizaгdС опtrоLа s р х. с s" lпhе гits='WizaгdС опtrоl" %>


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<html xmlns =' 'httр ://www. w З .огgl 1999/xhtml'' >


<head nmat="server">
< title >Эле мен т управ ле ния Wizard</tit1e>
</head>
<body>
< fо пn ю ="fо rml " runat="server''>
<div>
<asp:Wizard ID='Wizardl " runat="server" ActiveStepInd ex="O">
<WizardSteps>
<asp:WizardStep nmat="server" 1it1e="S tep 1 ">
</asp:Wizard Step >
<asp:WizardStep nmat="server" 1it1e="S tep 2">
</asp:Wizard Step>
<lWizardSteps>
</asp:Wizard>
</div>
</form>
<!body>
</html>

Листинг Дес~рипторное представление страницы

WizаrdСопtrоl.аsрх с заготов~ой Wizard

Д альнейшей задач е й программиста БУдет настройка этой заготовки в


полноценный элемент управления. Оболочка предоставляет llШрокие
возможности для р азработч ика на этйпе проекmUРО6ЙНUЯ. Кр оме
традиционной панели свойств Properties элемент Wi z а r d имеет
дополнительную локаль ную панел ь задач для оперативных действий п о
на стройке. Чтобы вызвать локальную панель задач элемента Wiz a r d .
нужно щелкнугь мышью на пиктограмме в виде треугольника в его

прав ом верхнем углу

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

WiZ8rdControl.8SPX*
,.ЕН . Wizard Ta5k5
ilstep 1 Auto Foгmat ...
IIStep 2 Step IStep 1 ElI
!I~~~~~. ~_ .~.~~N~e~xt~l~ AddjRemove W~ardSteps ...
Convert to StartNalkJationTem~te

Convert to StepNalkJationTem~te

Convert to F,nshNa"gatiooTerrplate
Convert to S,deBarTem~te

Ecit т em~tes

в элементе управления Миl ti Vi ew все п редставления на этапе


проектuрованuя р аскрыты для р азработчика. Для элемента Wi zard
оболочка VJsua! Studio 2005 п оказывает разработчику п редставление
только одного текущего ша га.

Чтобы создать н овые шаги мастера, нужно :

• п росто добавлять в его контейнер дескри п торы

<asp : Wiz ardStep>


• или через локальную панель задач выполни ть опцию Аd dlRепюvе
WizardS teps
• или в п анел и Properties вызвать на редактирова н ие свойство
Wi z ardSteps

'"
в.м. С""",,,в

WizardStep CoNection Editor ===-......;..; Про,раммupoвtJNШ' 110 ASP. N ET

Мembers: Step 1 properties:

~
о

1 Яер 2

~ AIowRеtllЛ
EnaЫеThе пg
T,~

Тс",

EnaЫeVIe'f)'State T, ~

ЯерТуре Auto
Title Step 1

dd'---_.J-I _-,ес:,,,mo:::.,:.:,,---,
_---"A::
еж Са гсel

Обратите в ни ма ние , что по умолчанию дескр ип торы

<asp : Wi z a r dS t ep> шагов -вкладок не им еют значения

иде н т ификатора ID. Здесь подразумевается , что для тако го сложного


элемен та управления р аз р аботч ику достаточно декла р ат ивной
настройки. Если же в дальне йше м разработчик пр ед полагает
программ н о управлять шага м и мастера, то без атрибугов ID не
обойтись.

в прив еденном окне редактирования коллекции ша гов-вкладок


наиболее существенными являются следУЮщие свойства дескрип то р а
<asp : Wi z a r dS t ep>

Н екоторые свойства дескри п тора <asp:WizardSteI


С войство О пи са ни е

T i tle Имя шага, видимое пользователю в ссылках н а боковой

Э то свойство о пр еделяет тип кнопок нави га ции , кото р ь


поль зо в ателю данным шагом, и рав н о одн ому и з з начен

Sуs t еm . WеЬ . UI . WеЬСолt r оls . Wi z аrdStерТу


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• Auto - определяется по умолчанию и устанаВЛИЕ

зависимости от местонахождения шага в Ю)ллеКЦl

S t epType п ервом месте , то бу,цет кнопка Start, во в с ех пром€


кнопка Step, если на последнем месте - будет кног
• Complete - не показыва ет никаких кнопок и CKr

• F i n i sh - показывает кнопки Finishи Previous


• S t ar t - показыва ет кнопку Next
• S tep - показывает кнопки Next и Previous

Показывает, может ли пользователь возвращаться к это]

его прой дет. Если это свойство имеет значение fa l se ,


Al l o wR eturn ~
пользователь прои дет этот шаг, он н е сможет вернугься

ссылки, ведущие к этому прой денному шагу; немедленн

Наполним шаги маст е р а конкретным содержимым элем ента ми

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


Ю)торых ра зместим :

• Wiz ardStepl - раскрывающийся списо к Dr opDown Li st


• Wi z ardStep 2 - список ра.циокнопок Rad i oBu t ton Li s t
• Wiz ardStep3 - текстово е пол е Te xt Bo x
• Wiz ardStep 4 - обычный текст

Оболочка VJsual Studio 2005 все отличные от значений по умолчан ию


свойства элементов сохраняет в дескрипторах текстового файла .aspx
как дополнительные атрибугы. Бол ее того , при уст ановке значений
отдельным свойствам оболочка сама генерирует новые дескрипторы и
даже ц елые блоки Ю)да. Поэтом у все декларативны е настройки сл ожных
элемен тов управл е ния нужно выполнять через пан ель Properties, но дл я
краткости излож ения прив едем уже готовый код настройки страницы
наше го прим е р а .

<%@ Page Lапguagе="С#" Аutо ЕvепtWirеuр=' 'truе ''

СоdеF ilе='WizaгdСопtrоLаsрх.сs" lпhегits='WizaгdСопtrоl" %>

<html xm1пs="httр ://www.wЗ.огgl1999/xhtml" >


<head nmat="server">
< title>Элемент управления Wizard</tit1e>

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<lhead>
<body>
< fо пn id="form1 " runat= "server''>
<div>
<asp:Wizard ID=''Wizard1 '' runat="server" Васk С оlог= "# ЕFF З FВ"
BorderColor= ''#B5C7DE''
BorderWidth="1px" Width="100%" ActiveStep lnd ex=''O''
StartN еxtВ uttопТеxt="Далее >"
StерNехtВuttопТехt="Далее >" StepPreviousButtonText="< Назад"
FinishCompleteButtonText='ToTOBO " FinishPreviousButtonText="< Н.
Н еаdегТехt='Жи з н е нно важная ан кета!">
<WizardSteps >
<asp:WizardStep ID=''WizardS tep1 '' nшat= "sе rvег " Тitle ="Д рузья "
< hЗ >
Какой пр ез и де н т самый лучший? <lhЗ>
<asp:DropDownList ID=''DropDownList1'' runat="server">
<asp :Listltem> Наш П угин </asp :Listltem>
<asp :Listltem> Их Клинтон </asp:Listltem>
<asp:Listltem> Похожи й на Чингиз -Хана </а s р :ListItеm>
<asp :Listltem> Вы сам и </asp:Listltem>
<asp :Listltem> Ваша соседка </аsр:Listltеm>
</asp:DropDownList>
</asp:Wizard Step >
<asp:WizardStep ID=''WizardStep2'' nшat= "sе rvег" Тitle =' Туризм '
<h2 >
Где Вы были с 19 по 21 августа 1991 года?<lh2 >
<asp :RadioButtonList ID='RadioButtonList1 " runat= "server''>
<asp:Listltem> На Красной п ло щади </а sр:Listltе m>
<asp:Listltem> На Луне </аsр:Listltеm>
<asp:Listltem> В ч ужом огороде </аsр:L istltеm>
<asp :Listltem> У тетеньки </asp:Listl tem>
<asp:Listltem>B ayre</asp:Listltem>
</asp:RadioButtonList>
</asp:WizardStep >
<asp:WizardStep ID =''WizaгdS tе р З'' nшat= "sе rvег " Тitle =' 'ВстреЧI
< hЗ >
Кайтесь! Место встречи изменить нельзя! < IhЗ >
Ваш ИНН :
<asp:TextBox ID='TextBox1 " runat= "server" 1>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

</asp:WizardStep >
<asp:WizardStep ID='WizardStep4" nmat="server" Тitle="Досуг">
<h2 >
Мера ПООI.l.lpения < lh2 >
Ус и ленная диета + кrlИзьма ззз перцем!
</asp:Wizard Step >
<lWizardS teps>
<HeaderStyle ВасkСоloг=''Вluе'' Fопt-Воk:l='Тruе" Fопt-Size="Х-L~
</asp:Wizard>
</div>
</form>
<!body>
</html>
Листинг Дес~рипторное представление страницы

WizаrdСопtrоl.аsрх с элементом Wizard

Несколько замечаний:

1. Такой дураштlИВЫЙ текст Вы долж ны изменить (Технари MOryr


себе позволить, пока Органы отдыхают, а ''Утомленные Солнцем"
до ц е нты - т ем более)
2. Боковую панель навигационных ссылок можно отключать
свойством Wi z ard . Di sp l ayS ideBa r = " Fal se "
з. Оболочка в режиме проектирования автоматически изменяет
значение свойства Wiz a r d . Act i veStep I nde x при
редактировании текущего шага. Поэтому, чтобы страница при
запуске показала первый шаг, небходимо в конце редактирования

либо на него перейти , либо установить


Wiz a r d . Act i veStep I nde x = " 0 "
4. Мы еще ничего не программировали , а уже успели добиться такой
мощной функциональности страницы
s. Последни й дескр иптор кода <HeaderStyle> определяет стиль
заголовочного блока элемента Wiz a r d , о чем мы е ще поговорим
ниже

• ~3апустите страницу с настроенным элементом Wi z а r d и


' 'подывитесь '', какой же все-таки Большой Билл умный, да еще так
вовремя - какие масuпабы и горизонты открывают для нас эти его

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

инструм е нты (н у, прямо , Э льдорадо!)

~ Элемент уnpавления Wlzard - Мicr050ft Internet Explorer .=J.gJ~


FIe Ed t Vfew Favcrites TooIs н.ф ~C-~-----_•
.... Back ... .....10 a'J ~ ' ~ Seif"ch [ij Favcrites '9 ~ () ' ~ ... .3 G! IВ .,. О ~
Addess Ji1 http://ocahJst: 104 1/INеЬstе5/INiиdCооtr,j .,,+,х :::J~

Жизненно важная анкета!


Где Вы бьJJШ с 19 по 21 августа 1991 года?
Друзья v

Т уризм
r На Краснои IШощади
Встречи r На Луне
l.I2.m r В чужом огороде
r. у тетеньЮI
r B ауте
I < Назад Далее>

ГГГ ~ Lосз пtrюеt


cJl

События элемента Wizard

До сих пор мы занимались настройками Wiz a r d в режиме


про ектирования, ПРИlШlа пора при ступить к программированию его

времени выполн е ния. Мы уже говорили , что для раз р аботчика задача
управления объ е ктами страницы во время выполнения сводится к
с озданию и программированию обработчиков событий , на которые
MOryг реаrnровать эти объ е кты. Ниже перечислены события , на которы е
может реагировать э кземпляр класса Wi z a r d .
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

ObJect Browser ...- --J;:I Х

Бrowse: All components

System.Web.UI.WebCOIltJols.\ ". ,.~ StepPrevirusButtonStyIe


.~ StepPreviQ/SButtOllText
.~ StepPreviQ/SButtOllType
5' StepS1yle
. 'ff: T.ag<ey
.~ WizEf"dSteps
C.arк:elButtOllID
.. Q C.aIYelCom mand\J.ame
СustоmF п isГВuttOllID
Custo mr-.JeхtвuttопID
CustomPreviousВuttonID
Data..istID
FinisГВuttOllID
FinisГPreviQ/SButtOllID
.. Qo rvIOveCompleteComm.ardN.ame
.. Q rvIOVeI\JextcommandName
.. " rvIOvePreVirusCommandName
.. " rvbveToComm.amName
SideBarButtOllID
StartNextвuttonID
Step\JextвuttonID

.. ., Carк:elButtOnCliCk
.. ., FinisГВuttOllClick
..'1 NextвuttonO:: k

.. " Ргеviru,вuttоnCick
..'1 SideBarButtOnClick

Собы тия , подцерживаемые элементом WiZQ j


Событ ие Описание

Ага! Пользоват ель переключился на новый


ActiveStepChanged
СВОЙСТВО АсtivеStерlпdех

Ага! Пользоват ель щелкнул на кнопке Сапсе


умолча нию н е отображается, од н ако ее мож

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

5 tep сразу, если установип


представления

Wizard . DisplayCancelButton= " Tr


инициирует обратную отсылку, и если не Щ
CancelButtonClick соответствующе го обработчика , то ничего н
одновременно определено свойство

Wizard . Cance l Des ti nationPageUr


СапсеlDеstiпаtiопРаgеUrl= " -/Мu
то п о щелчку пользователя на этой кнопке е
ст р аница

FinishButtonClick Ага! Пользователь дошел до последнего шаг

Эти события возникают при щелчке на кнOl


любом шаге. Но сменить шаг пользователь ~
Ne x tBu t tonClick , ~
Prev iousBu t t onC l ick панель. Чтобы такои момен т н е упустить и (
сме н у LIJara, лучше вместо этих событий обр
ActiveSteplndex
S ideBarBut tonCl i c k Ага! Пользователь щелкнул на ссылке в оБЛi

Чувствуете?!!! Мы сидим СО своим кодом на другом конце провода и


ждем очередных пожеланий ненасытного пользователя. При по лучении
от него очередного запроса мы анализируем выбор по присланным
событиям и пакуем для н его новую п осылку, в которую закладываем и
тр ебуемый текущий ответ, и интерфейсные элемен ты для ввода новых
пожеланий. Да все это еще должн о быть красивым, блестящим и
пyuntстым. Вот Большой Билл нам здесь и помогает - осталось только
руки приложить.

Используем событие FinishButtonClick , чтобы


усовершенствовать наш пример. Когда пользователь щелкнет в
последнем шаге на кнопке Finish (Готово), соберем его выбор с каждого
шага и вернем в раскрытом представлении это го по следне го шага .

• IJ$Откройте страницу WizardControLaspx в режиме Design и


перейдите на последний шаг WizardStep4 для его редактирования
• ~ оместите в середину контекста текстовую метку Label из
вкrJaДКИ Standard пан ели Toolbox, присвойте ей имя lblSummary
и очистите свойство Text

'"
В.М. СН"""'f~'•~~~~~~:~~~~=:~~~~~~П~"'~'~'"~~~"~-~"~",~"~"~"'~'~.N~П
/ Wizif"dCmtтd ,aspx,cs* WizaгdContгol.aspx* т Х

Жнзненно важная анкета!


lII>Ylli! Мера поощрения
ТУРИЗМ

Встречи lri~($~~~
~ Усиленная днета + клизьма ззз перцем!

< Наз ад ГОТ О В О

• ~ы дел ите объ е кт Wiza r dl и через п а н ель свойств в р е жи ме


Even ts со здайте обработч ик дл я собы тия
FinishBu t tonClick
• ~3а пол ните обработчик следующим кодом

using System;
using System.Data;
using Sуstеm.Сопfigurаtiоп;
using Sуstеm.Соllесtiо пs;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using Sуstеm.WеЬ.U I .WеЬСопtrоls;
using Sуstеm.WеЬ.U I .WеЬСопtrоls.Wе Ь Раrts;
using Sуstеm.WеЬ.U I .НtmlСопtгоls;

риыic рапia l class WizardControl: System.Web.UI.Page


(
protected void Page_Load(object sепdег, ЕvепtAгgs е)
{

protected void Wizard l_FinishButtonClick(object serкler, Wiza rdNa~


(
// Библиотека Framework 2.0 в на шем распо р яжен ии
System Теxt . S tr iпg8uildег sb:= пеw System Text.String8uilderO;
sb.Append("< h3> ');
sЬ.А р ре пd(''Вы выб р али : < Ьг /> '');
,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

string tide ;

title = WizardStepl.1ide;
sb.App end(tit1e + ":" + DropDownListl.Text + "< Ьг />");

title = WizardStep2.1ide;
in! index = RadioButtonList1.Selectedlndex;
if(index! = - 1) // Есл и что-то выбрал
sb.App end(tit1e + ":" + RadioButtonListl.Items[index]Text + "<Ь

/* !! !!!!!!!!! !!!!! !!!!! !!!!! !!!! !!! !!!! !!!!! !!!!! !!!!! !!!!
// Для элеме н та класса C heckBoxList н ужн о пров е рять коллею
C heckBoxList C hec kBoxListl ;
foreac h (ListItem item in C hec kBoxListl .Items)
(
if (item.Selected)
sb.Append(item.Text + "; '');
}
!!!! !! !!!! !!!!! !!! !!!!! !! !!!!! !!!!! !! !!! !! !!!! !!!!! !!!!! */

title = WizaгdStерЗ . 1idе ;


if (ТеxtВох 1 . Теxt.Lепgth > 0)// Есл и что-то ввел
sb.App end(tit1e + ":" + TextBox1.Text + "< Ьг />< /ьг /> '');

sЬ.А рр е nd( "<IhЗ> ');

sЬ.А рр е пd(''В ам рекомен дуется:'');

// Отображаем собра нны е данные


IblSlll1lIrnry.Text = sbToString();
}
}

Листинг . ОбработчиlC событии FinishButtonClick в файле

WizardC ontrol.aspx.cs
• ~ ерейдите в режиме Design на первый шаг WizardStep1, чтобы
автоматич ески уста новил ось в НОЛЬ з нач е ние свойства
ActiveSteplndex объекта Wi z ardl и пользователю вначале
отображался первый ша г

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• ~ыполните страницу, заполни те анкету и на последнем ша ге


щелкните н а кно п ке Готово. Обработчик отобразит пользователю
пр имер н о такой результат
~ Элемент уnpавления Wlzard - Мicr050ft Internet Explorer ~~_="ID I~
FIe Ed t Vfew Favcrites TooIs НеР
----
=-__ _
.... Back ... ..... ($) ffi ~ : ~ Seз:сh [ij Favcrites 1;' Мес1а (J 1 ~ "' .3 G! IВ r О -..--J
Addess Ji:I http://ocahJst :104 1/1.11 еЬSitе 5/1.11izз:dCооlrU ,aspх :::J~

Жизненно важная анкета!


Мера поощреЮlЯ

Друзья Вы выбрали:
Туризм Друзья: Их Клинтон
Встречи Туризм: В чужом огороде
i!<>m Встречи: 0123456789

Вам рекомендуется:
у сrшеЮlая диета + КШlЗьма ззз перцем!
< На зад ГОТОВО

1;.i1'"Dte=:-------------ггг ~ LОС3 Illrюеt

Стили элемента Wizard

Элеме н т Wi z a r d содержит средства, позволяющие легко менять его


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

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

ObJect Вrowser ..... ~ х

Вrowse: AlI COmp:xelts

System, wro,LЛ. WebCon1YoIs, 1,. ..- --~ DispаУСЗIYelвutton


,,-~ DispауSideВзГ
, -~ F h ishCompleteВuttonImageijl
,,-~ FhishCompleteВuttonstyle
, -~ F h~ hCompleteВuttonText
,,-~ Fh~hCompleteВuttonTyp€
, -~ F h~ hDestinationPageLtI
" -~ Fh~hr-.JavigationТеmplatе
--~ F h~ hPreYiaJSButton]mageIJrl
--~ Fh~hPreYiaJSButtonStyle
--~ F h~ hPreYiaJSButtonText
--~ FhishPreYiaJSButtmType
..ts' C*""rSМe
--~ l-\e.ю:гТеmрlаtе
--~ l-\e.ю:гТехt
--~ r-.Javigationвuttonstyle
..I:'!i' Nav>]a''''Stylo
--~ SideBarButtOnStyle
, -~ SideBarStyle
,,-~ SideBarTemplate
, -~ SkipLriText
,,-~ Starl:f.JavigationTempate
-!'j' StarlJ.JextвuttonI mageUrl
,,-~ StartNextвuttonStyle
, -~ StartNextвuttonText
--!5I StartNextвuttonType
--~ Stepr-.JavigationТеmplatе
--~ Stepr-.Jeхt8uttonImagelJгl
--~ Stepr-.Jeхt8uttonStyIe
--~ Stepr-.Jeхt8uttmТехt
--~ Stepr-.Jeхt8uttmТуре
--~ StepPreYiaJSButtmImageIJrl
--~ StepPreYiaJSButtmStyle
--~ StepPreYiaJSButtOnText
--~ StepPreYiaJSButtOnType
I:'!i' StepSМe

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


в.м. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

Некоторые свойства для настройки кнопок

Свойство Описание

Задает изображение для


S t a r tNe x tBu t ton I mageU r l б
и зо р ажения-кнопки

Использует стили внешней каскадной


S t a r tNe x tBu t tonS t yle
таблицы стилей CSS
Настраивает текст кнопки и л и
S t a r tNe x tBu t ton Te x t
ссылки

Определяет кнопку; ссылку и л и


S t a r tNe x tBu t ton Type
выбираемое изображение-кнопку

Среди свойств компонента Wiz ard есть общие сти ли, затра rnв ающие
на стро йки всех элементов, а есть ИН Д ИВИдУальные для каждой группы
элемен тов . Следует по м нить , что если одновременно определены те И
д р уги е стили , то конфrlИкта не БУдет, прос то ИН Д ИВИдУальные
пара метры нас тройки п ерео пр ед елят (отме нят) общие стили. В языках
прогр амм иров а ни я используется тот же принцип , переменная

локальной обл асти видиЛ1Ости п ерео пр ед еляет (делает н едоступной) в


текущем блоке кода одноиме нн ую переменную внешней обл асти
видиЛ1Ости.

Ниже при веде ны свойства мастера Wi zard, опред еляющие общие И


ин див и дуал ьны е сти ли его отдельных областей.

С войства Wizard , определяющие ст и л и е го элементов


Ст иль Описание

Наследуется
Wi z ard от класса
ControlSty l e WebControl И применяется ко
всем е го р азделам

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


колонтитула , который будет
отображаться тол ько в то м случае,
Heade r Style
есл и бу,цет задан какой-нибудь
текст в свойстве
Wiz ard . Heade r Te x t
Прим е ня ется к области боковой

'"
В.М. СН"",,,В Про,рйммupoвtJNШ' Na ASP.NET

пан ели с кнопками

Определяет стиль кнопок боковой


SideBarButtonS t yle
пан ели

Применяется к компонентам
S t epSty l e представления, ВЮJюченным в

текущий шаг

Применяется к нижней области


Naviga ti onS t yle шагов , в которых расположены

навигационные кнопки

Применяется ТОЛЬКО к кнопкам


Naviga ti onButtonStyle
навигации в области навигации

Применяется к кнопке Next в


п ервом шаге, если ее ВИДИМОСТЬ
S t artNe x tBu t tonS t yle
задана свойством
StepType=S t art
Применяется к кнопке Next в
пр омежyrочных шагах, если ее
S t epNextBut t onStyle
ВИДИМОСТЬ зада на свойством
StepType=Step
Применяется к кнопке Previous в
пр омежyrочных и последнем
S t epPreviousBu t tonS t yle
шагах, если ее ВИДИМОСТЬ задана

свойством S t epType=Step
Применяется к кнопкам РinisЬ и
. . h. 1 Previous в последнем шаге, если их
FlnlS Prev l ousBu t tonSty е ~
ВИДИМОСТЬ зада на сваиством

StepType=Fin i sh
Применяется к кнопке Са псе! во
всех шагах, если ее видимость
CancelButtonSty l e
задана свойством
Di splayCancelBu t ton=True

Оболочка VlSua! Studio 2005 по зволяет существенно облегчить жизнь


разработчика наличием сред ств автоматизации по настройке типовых
стилей, которых в больши нс тве случаев бу,цет достаточно. Вернемся к
локальной панели задач элемента Wizard, чтобы ОДним махом
ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

локальной панели задач элемента Wizard. чтобы одним махом


присвоить типовой стиль н ашей тестовой стра ниц е.

• ~Откройте страни цу WizardСопtrоLаsрх в режиме Design и


выделите объект Wi zardl
• ~Откройте локальн ую панель задач объекта Wizardl , щелкнув
на пиктограмме треугольника в его правом верхнем углу

Wizard Т asks
Auto Foгmat, ,.

Step IДрузья
Add/Remove WizardSteps,
COГNert to StartNavigationT errplate
Convert to StepNa~gatiooTerrplate

Convert to FlrishNavlgationTem~te

Convert to SId=BarTemplate
Ecit т em~tes

• ~ыполните о пци ю Auto Fоппаt и в появившемся диало говом


окне выберите нужный стиль
дuto rormat

SeO"c!a >o:::heme' Previe",


====---.1 .><1
Жизненно важная анкета!

~;'::~:,~~~езиде,нтсамый

Дaneе > I

Окно Auto Fопnat можн о вызвать и через контекстное меню элемен та


Wizard. выполнив одн оимен ную опцию

'"
в м С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

,j!; Cut

i:tI Сору

I~ Paste

Paste Alternate

Х D€l€te

Stye ...

View Code

Vi€w Component Designer

I!), View il Browser

Edit Iтag€

Show Smart Tag

I Auto Format".
I
AddjRemove WizardSteps ...
COIlvert to Starb\JavigatjOllTemplate

COIlvert to StepNavigatjonTemplate

COIlvert to Finsf"Ii\JavigatiOllTemplate

COIlveгt to SideBatTemplate
-

EditTemplate ~

End Template Editing

liJ Re~esh

Ia Propeгties

• ~ы п ол н и те страни цу и убедитесь, что она приобрела


пр офесс и онал ьны й дизай н
В.М. СН"",,,В

§ Эл~менr УnPdВ~Я WlUrd ~i<rosoft Int~~ [хрlor~т


-....;..;

--1.
Про,раммupoвtJNШ' ,ю ASP.NET
..:..IgJ~

Жизненно важная анкета!

поощрения

выбрали:
Д~IУЭ'ЬЯ Похожий на Чингиэ-Хана

~~,:=,~:Ha
6
Луне
0123456769

ре ко мен дуется :

Ус ил енн ая диета + клизьма ззз пер ц ем l

[ < Назад J [ ГОТО80

• ~ роа н ал и зи р уй те дескри пт ор н ое п редставлени е страницы ,


чтоб ы выясни ть, каки е свойст ва дескр ип то р ов стилей позвол и ли
добави ть такую красоту (у ме н я бы такое ни ко гда вручную не
п олучилось!! !)

П роа н ал и зируй т е дескр ип тор н ое п редставле ни е стра н и ц ы, чтобы


в ы яс ни ть, ка ки е свойст ва дескр ип торов стилей п озволили добави ть
такую красоту (у ме н я бы такое ни ко гда вручную не п олуч и лось!! ! )

<HeaderStyle BackColor=''#FFCC66'' Fопt-Воkl='Тruе" Fопt-Size=''O.9еm'' FI


BorderColor=''#FFFBD6'' BorderStyle="Solid" BorderWidth=''2px'' Horiwnt
<SideBarStyle BackColor=''#990000'' Fопt-Size=''O.9еm'' VerticalAlign='Top" 1
<N avigatlonВuttonStyle BackColor='White" BorderColor=''#CC9966'' Border~
BorderWidth="lpx" Font- N ames=''Verdana'' Fопt-Size=''O.8еm'' ForeColor= '
<SideBarButtonStyle ForeColor='White" 1>

Листинг Дескрипторы стиля I добавившие красоту в элемент


Wizard страницы WizаrdСопtrоl.аsрх

в приведе н ном коде каждый дескри п тор настра ив ает свою область
элемен та Wi z a r d . Обрат и те в ни мание, что приведе нны й блок кода
настройки ст илей оболо ч ка доба в ляет в самый конец ко нт ей н е р а
<asp : Wiz a r d></asp : Wiz a r d> , чтобы легче было искать . Если

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

этот блок кода удалить, то мы вер н емся к почти п режнему вариан ту


стилей по умолча ни ю (почти , потому, что может потребоваться
корректировка атрибугов еще в некоторых других местах, например, в
дескрип торе <asp : Wizard> - п осмотр и те сами!).

• u;.;rн алюбовавшись сей красотой, вызови те кон текстное меню для


элемента Wiz ard и выполните кома н ду Auto FопnatlRепюvе
Formatlng, чтобы вернугься на грешную Землю к сти лям по
умолчанию

Шабло ны элемента Wizard

Если с помощью свойств-стилей н ам н е Удается доб и ться желаемого


эфректа , то можн о воспользоват ь ся свойствами-шаблонами. Ниже
п риведен полный список шабло н ов элемента управле ни я Wiz ard,
выбранный как свойства из п анели Object Browser

ObJect Browser .... ~ х

Browse : АI CompOllents •
System.Web.UI.WebCono-о •. \ • , ~ HeaderSty1e

'" ~ System.Web.uJ.WebConO-О •. Wiшd


'G!i' HeaderTemplate
i.",~ HeaderText

Шаблоны элеме н та управления Wizard


Шабло н или дескриптор О п исание

Определяет содержимое области


HeaderTemplate
верхнего колонтитула

Определяет боковую панель,


SideBarTemplate которая обыч н о включ ает ссылки
навигации для каждого шага

Определяет кно п ку навигации для


перво го ша га , если ее видимость
StartNavigationTemplate
задана свойством
StepType=Start
Определяет кно п ки навигации в

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

промеЖУГОЧНblХ и последнем
S t epNav i gationTemplate
шагах, если их видимость задана

СВОЙСТВОМ StepType=Step
Определяет кнопку навигации Firllsh
. . h .. 1 для последнего шага , если ее
FlnlS NavlgatlonTemp ate ~
ВИДИМОСТЬ задана СВОИСТВОМ

StepType=Fini sh

Формирование шаблона <HeaderTemplate>

ДеСКРИПТОРНblЙ блок первого шаблона добавляется опцией Edit


Templates через локальную панель задач , либо опцией Edit Template через
контекстное меню элемента Wizard (одна и та же команда в раЗНblХ
местах по разному наЗblвается - Большой Билл тоже человек!).

Wizard Tasks
Auto Format ...

Step I Друзья ~I
Add/Rermve Wizck-dStерs ...

Convert to Staгtt'Jav~аt:ioп Т emplate

Сопvегt to StepNavlgabonTemp~te

Сопvегt to Fil~hNalkJаtioпТеm~аtе
Сопvегt to SideВErTerrplate

Edit Те rmlates
в м СН"",,,В Про,раммupoвtJNШ' NQ ASP.NET
~, ш W"u .... JcoпIrol.m.p х.. • Х

.. "'"
~

~ Pacte
~,

повокшага:

нт самый лучший?
""
Pacte !.Jf<м:e

Х
\3
Do!I;\i'

st'y4o" ,
у~",с ш Д"'"'~O>
I
Y~"'C~tc..~

l!I Y~",,, [\'"о",,"г

r' • Ie "'7"

Sho1o' Smdlt Tag


Auto FCfma!",
Md ,~ e", o ye \\.\ZordStEp" "
CC<"Nert \0 S Ш1:J'.lavlg01КIlТ€ rrра::е

~! \0 s t<pNa"9ЖOl1Т~ tе

CC<"Ner! to F ~уqжaтrещ::t;te

Coпv ег t to Sde!!<>"Te rrph


E (]IТ ' ,"

Е'J~"гг~ч_еЫJ"
• ~T" ~
SIJ~~ te

[i] Рйс:h St.Yt!-1J"9->"'tonТ" " "to


l.iiII Рщ::..r~, s tе;:N,,1;рЖ<l1 отр ет

Fn$m"'1]aXn re", DOCe

• ~ режиме Dеsigп выполните командУ Edit TemplatelНeader


Template контекстного ме н ю для элемента управления Wi z a r d
страницы WizardControlaspx
• ~ появившемся окне введ ите текст верхнего колонтитуЛ Q "
Эт о заголовок шага: " (или л юбую другую Абру- Кадабру; лишь-бы
заготовка шаблона созд алась , все равно потом руками
редакти ровать) , после че го щелкните н а опции End Template Editing
локальной п ан ели задач, чтобы завершит ь созда ние шаблона
заголовка и вернугься в редактор Design

V\f\zaroXontrol.aspx,cs WlzardControl.aspx*
""""""""""""""""""Ш
г Wizard Tasks
izard 1 - HeaderTemplate
Template EditJng fVIode
Г\ead€rTemplate
Dsplay
Это заголовок шага:
Еnd Т enWte Ediln;i

т.
--------------------------------------------

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Если ни чего в п оле т екста не ввести, то после выхода п о опции End


Template Editing дескр иптор <Heade rTe mpla t e> создан не будет.

• ~ ерейдите на страни це в режим Sошсе, найдите в конце блока


кода созданный оболочкой дескри п тор <Heade r Temp l ate> и
отредактируйте е го так

<HeaderTemplate >
<Ы >
Э то заголовок шага:
<%= Wizard1.ActiveStep.1ide %>
</h1>
< lНеаdеrТеmрlatе >

Листинг Код десхриптора шаблона заголовха элемента Wizard

Получается , что мы шаблон заголовка должны за п ол н ять вручную как


обычный НТМL -текст. Эта возможн ость оставлена в силу ее простоты
(" уж НТМL-то они должны з на ть!", опрометчиво п одумал Большой
Билл). И для тренировки мы сами вставили в этот НТМL -код
опе р аторный исполнимый блок
<%= имя переменной ИЛ И вы ра ж ение%> . Это обычный пр ием ,
п риме н яемый, например , в РНР. При исполнени и страницы вместо
это го блока в статический текст БУдет подставле н о значение указа нн ой
п еременной и ли выражения. Таких блоков в статическом НТМL -коде
страницы мы можем наставить, сколько угодн о . В нашем примере в
указа нн ом месте БУдет подставляться значение атрибуга Тi t 1е
текущего шага , которые мы деЮJa р ативно определили ра н ее пр и

формирова нии шагов элеме н та Wi z а rd .

• г;.:.=и сполните страницу и вы увидите работу шаблона заголовка в


действии

Обратите внимание , что хоть ранее мы и задали в панел и Properties


з н ач ен ие за головка в свойстве Неаdе r Те х t= " Жи зненно важная
ан ке та! " элемен та Wizard (этот атрибуг и сейчас там
п рисугствует), но как только мы добавили дескриптор шаблона
за головка, оболочка сразу же скрыла это свойство в панели Properties.
Отображаться тепер ь БУдет именно заголовок шаблона.
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Формирование остальных шаблонов

Все оставшиеся шаблоны областей элемента Wiz a r d разрешают


пользоваться Удобствами среды в силу их сложности. Чтобы создать
тр ебуемый дескр иптор шаблона, нужно выполнить соответствующую
команду Convert to ... (в контекстном меню элемента Wiz a r d или его
локальной панели). После этого можно приступать к редактированию
созданного шаблона, выполнив опцию Edit Template (опять вставлю те
же самые снимки. Физически они занима ют на дис ке одно место , а
отображаться броузером MOryr хоть в ста местах)

Wizard Tasks
Auto Format ...
Step I Друзья

Add/Remove WIZE<dSteps ..
Convert to StartNav'9аtюпТеmрзtе

Сопvегt to StepNavigationTemplate
Сопvегt to Fi1ishNavigаtioпТеmраtе

Convert to 5ЮеВагТеmplаtе

Edit Те rmlates
в м
, _". СН"",,,В

Ш W"u .... JcoпIrol.m.p х·


Про,раммupoвtJNШ' NQ ASP.NET
• Х

.. "'"
~

~ Pacte
~,

повокшага:

нт самый лучший?
""
Pacte !.Jf<м:e

Х
\3
Do!I;\i'

st'y4o" ,

У~"'С Ш
Д"'"'~O>
I
y~", Ce>rrpmmt c..~

l!I y~",,, [\'"о",,"г

r' • Ie "'7"

Sho1o' Smdlt Tag

Auto FCfma!",

Aad ,~ e"' O ye \\.\ZordStEp" "


CC<"Nert \0 S Ш1:f\lavlg01КIlТ€ rrра::е

~! \0 s t<pNa"9ЖOl1Тeщ:>ii; tе

CC<"Ner! to F ~уqжaтrещ::t;te

Coпv ег t to Sde!!<>"Te rrph


E (]IТ ' ,"

Е'J~"гг~ч_е Ы J"
• ~T" ~
SIJ~~ te

[i] Рйс:h S ty1N'J ~"t OnТoo-p:gto

l.iiII Рщ::..r~, s tе;:N,,1;рЖ<l1 отр ет

Fn$m"'1]aXn re", DOCe

Команда Edit Template вызывает окно редактора шаблонов , в рабочей


области которого находи тся прямоугольн ый индикатор настройки со
своей локальной п а н елью. Стои т только выделить этот и н дикатор ,
сразу в панели Properties появляются достyn н ые для настройки шаблона
свой ства.

у Wiz"dCono-u,asрх,сs / WizardControl,a5px* I I
~jzard 1 - SideB-аrТеmрlаtе

SideBarTemplate
i
ISldeВarTemplate - Cl,ck to s!art eciting, I

Завершение редактирования осуществляется командой End Template


Editing ко н текстно го меню и ли локальн ой панели
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Wiza-dСonUоl,asрх.сS WizardControl.aspx*
~~~~~~~~~~~Ш
izardl- SideBarTemplate Wizard Т asks
ТеЩ)lаtе Eclmg Mode
SideBarTemplate

• End Т еЩ)Lзtе Edibr>;)

~ Cut

Сору

Paste

Paste Altегn.зtе

Х Delete

Style ...
View Code

VI€W Component De3igner

~ View in Browser

Edit Image

0 Show Smaгt Tag

EditTemplate ~

I End Tempate Ecimg

[i] Re~esh

~ Properoes

Обратите в ни мание , что как только какой-то И З шабло н ов создан , то в


меню соответствующая коман да ме н яется с Co nver to .. ., на Reset.. .
Выполнение команды Reset. .. начисто удаляет дескр ипторы
соответствующего шаблона. Дескр ипторы любо го шаблона можно
удалить и вруч н ую в режиме Source, но для шаблон а заголовка это
можно сделать только вручную.
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Wizard Tasks
Auto Format ...

Step I Друзья ElI


Add/Rermve Wizз-dStерs ...
COГNert to StartNav~at:ionTemplate

Сопvегt to StepNavlgabonTemp~te

Сопvегt to Fil~hNa~аtЮпТеm~аtе

Reset SЮеВаг Те roolate


Edit Те rтplates

• г;.:.='Добавьте к элемен ту Wi zard шаблон


<SideBarTemp l ate> и через п анель Properties задай те ему
свойство ItemSty l eIBorderStyle="Outset "
• ~ернитесь в режим Design и убедитесь, что кно п ки боковой
панели стали выпуклые

WI:lз- dContrd.aspx.cs WizardControi.aspx* ~ Х

о, ~
I!p Это заголовок шага:
l' Друзья
I , Тm изм Какой президент самый лучший?
I ' Встыечи
rн аш Пути н :.:J
I , .!illY!:
Дал е е> ]
I !
• ~ыполните ст р аницу, все должно работат ь

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

и все же , давайте вернемся к той красоте , которую мы получали для


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

этой страницы применением стандартных стилей .

• ~далите шаблон <S i deBar Templa t e> , выполнив в режи ме


Dе sigп коман ду Reset SideBarTemplat контекстного меню элемен та
Wi z а r d , и выберите красивый стандартный стиль через опцию
Auto Fопnat того же меню

~ Элемент управления Wlzard MICrosoft Internet Explorer _ --"-,,,10 I~


FIe Б1t Vfew Favcrites TooIs НеР ;;;'0 - " '- - - _ _ _ _ _
.... Back ... ..... 10 ffJ ~ ' ~ Seif"ch !lJ Favcrites 'G' Мeda () ' ~ ... t.J G! ЪJ .,. О
Addess 11) htlpJ!ocahJst: lZ-З8/WеЬSitе5/W~юХооtпiaspх

кой президент самый лучший?

I Далее>

ГГГ ~ LОС3 Iltrюеt

т
(

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Программирование уровня приложения ASP.NET


Файл приложения GlobaLasax. Заготовки методов масса пр иложения с
пр едо пр еделенными именами. Демонстрация собы ти й приложения.
Демо нстрация перехвата необработанного события .

Файлы к лекции Вы можете скачать здесь скачать:

httр :l/оkl.iпtШ. ruld ераrtmeпtJiпtеmеtJр rasp netJ8/08 _ We bS ке Sx.zip

Виртуальный каталог, который мы создаем в самом начале разработки


сай та, при исполнении страниц ассоциируется с отдельным
при ложением. Приложение является отдельной пр о грамм н ой
единицей , изолированной при исполнении от страниц других
виртуальных каталогов. Все, что находится в виртуальном катало ге ,
относится к при ложению .

Исполняемое средой ASP.NET приложение на зывается доменом (по


аналогии с процессом при исполнении при ложения локально го стола) .
В отличие от локальных приложений, конечный пользователь никогда
н е запускает приложение ASP.NET напрямую. Он за п ускает броузер на
своем локальном ком пьютере и за пр ашивает определенный URL . Этот
запрос получет Web-сервер и передает е го среде исполнения ASP.NET
(рабочему процессу) , которая выделяет в па мяти доме н для
виртуального каталога и загружает в него код адресуемой стр ан ицы .
Таким об р азом, домен прuложенuя создается рабочим процессом пр и
п ервом за пр осе любой ст р аницы или Web-службы виртуального
каталога.

Web-страницы и Web-службы одно го в иртуально го катало га


выполняются в одн ом и том же домене . Содержимое другого
виртуального каталога выполняется в своем домене . Выполнение
при ложений из разных виртуальны х каталогов в отдельных
изолированных доменах гарантирует, что одн о приложение не сможет

оказывать влияние на работу другого, в том числе видеть его данные ,


хранящиеся в операти вной памяти. За этим строго следит общеязыковая
среда выполнения CLR.

Все Web-ст р аницы или Web-службы совместн о используют одни и те


же ресурсы, которые недоступны другим пр иложениям .
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Конфигурационные настройки среды исполнения, п омещенные в файл


Web.config виртуального каталога приложения , действуют только в
пр еделах этого приложения. Ст р аницы, требующие еще более
индивидуальных настроек, MOryr быть помещены в подкатало ги со
своими файлами Web.config.

Приложение может состоять из следующих компонентов:

1. Web-страницы (файлы .aspx) - основные рабочие еди ницы любого


приложе ния

2. Web-службы (файлы .asmx) - выполняют полезную работу для


сторонних при ложений
з. Файлы отделенного кода (.cs) - содержат исполнимый код для
пр о гра ммно го управления объектами, определяемыми в
интерфейсной части страницы
4. Конфигурационные файлы (Web.config) - содержат настройки
среды исполнения (рабочею процесса) как для всего при ложения
в целом, так и для групп страниц, расположенных в подкаталогах
виртуального катало га

s. Файл событий приложения (G/oba/.asax) - содержит обработчики


событий , которые реагируют на глобальные события самого
приложе ния

б. ДрYJl1е компоненты: базы данных, п ользовательски е элементы


управления, отдельные сборки, каскадные таблицы стилей ,
ри сунки, ХМL-файлы и т.д.

ASP.NET периодически п ерезапускает при ложение в другом домене для


освобождения неиспользуемых ресурсов (говорят, что при ложение
п ереходи т в новый доме н ). При этом старый доме н будет работать до
тех пор , пока не будуг обработаны все запросы клиен тов, стоящие в
очереди. То же самое пр оисходит и при заме н е разработчиком
содержимого страниц и конфигурационных файлов. Среда
обнаруживает новы е изменения , создает для модифицированного
при ложения новую сборку и запускает ее в нов ом домене , выполняя его
од новрем е нно со старым немодифицированным. И з-за того, что CLR
всегда блокирует файлы сборок при выполнении при ложения, перед
созданием нового домена она автоматически создает для него копии

файлов сборок в каталоге


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

с :\[Каталог_ Windоws]\Мk:rosоft.NЕ1\[Версия]\Теmрогагу ASP.N ЕТ Files

При создании домена приложение может создавать в нем не один


эюемпляр объектов приложения , а целый пул , содержащий от 1 до 100
эюемпляров , в зависимости от масштабируеЛ1Ости (количества)
запросов. Каждый новый запрос от одного и того же клиента может
адресоваться к разным эюемплярам п ул а домена.

Файл приложения Global.asax

Файл GlobaLasax является необязательным для приложения. Но если он


присугствует, то долже н быть единственным и находи ться в корне
виртуального каталога приложения. Э тот файл включает в себя
обработчики событий уровня приложения , которые выполняются
автоматически в ответ на происходящие с приложением события. Код
обработчиков пишется точно также , как и исполняемый С #- код
обычной страницы .aspx и не должен содержать никаких дескрипторов.

Любое приложение является экземпляром класса , на следую щего класс


HttpAppl i cation . Код файла GlobaLasax является неявным
расширением этого базового класса и будет иметь доступ ко всем его
свойствам и методам. В этом файле мы можем заполнить заготовки
методов с предопределенными именами , а также создать обработчики
на интересующие нас события уровня приложения. Все они долж ны
иметь одинаковую си гнатуру, определенную делегатом

public delegate void Sys tem.Eve ntНa nd ler(objec t sender, System.EventArgs е)

Заготовки методов класса приложения с

предопределенными именами

Объект приложения создается автоматически, поэтому мы не можем


сами регистрировать некоторые обработчики , присваивая им
прои зв ольные имена. Как и в случае с эюемпляром класса Page, мы
можем использовать только предопр еделе нны е имена обработчиков
приложения.
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Базовый масс HttpAppl i cation имеет ряд собы тий, которые


срабаты вают при определенных условиях и в определе нн ой
последовательности. Большая часть этих событий связан а с запросом .
На любое И3 них мы можем подписаться в методе
App l lcat l on Start () и создать обработчик с пр оизвольным
именем , либо воспользоваться именами по умолчан ию

App l lcat l on ИмяСобытия . В таблице приведе ны при меры


обработчиков событий приложения и сеанса, а также обработчики
событий , связанны х с за пр осами:

Некоторые обработчики уровня прилож ения

Об р аботч ик Описание

Обработчики событий приложения и сеанса

Э тот метод
вызывается то

когда впервые

за п ускается

приложение и

создается ДOM€

Appllcatlon Star t () этом обработч

m обно
инициализира

такие данны е,

де ревья навuгG

общие счетчш<
д р.

Вызывается ср

после завершеJ

работы
приложения.

Приложение

может завер l.Ш

работу вслеДСl
Appllcatlon End()
перезапуска т
или перехода Е

новый домен I
обновления
ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

файлов
виртуального

каталога

Вызывается

всякий раз, кш
приложении
Appllcatlon Error()
возникает

необработанн(

событие

Вызывается
всякий раз, кш
приложении

начинается но]

сеанс. Удобен ,
Session Start()
инициализаци

инqюрмации ,
специфичной ,
юшечного

пользователя

Вызывается
всякий раз пру
завершении

сеанса. Сеанс

завершается, КI

мы явно

освобождаем €
коде , или если

Session End() сеанс простоЯJ

заданное врем

(обычно 20
ми нуг), не
получив ни од

запроса.

Используется )

очистки любы
связанных дан

ш
в.м. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

Обработчики событий , связанных с запросами

Вызывается в
начале каждоп

запроса, ВЮlЮL

запросы на фаi
Appllcatlon Beg l nRequest()
не являющиеCJ

Web-ф:Jрмами

(например , We
службы)

Вызывается дс
начала

аугентификацу
(распознавани
пользователя).
Appllcatlon Au t hentlcateRequest()
Сюда можно
поместить

собственную
логику

аугентификацу

Вызывается nc
выполнения

Appllcatlon Au t horlzeRequest() аугентификацу


для назначен и :

специальных r
Используется
вместе с
Appllcatlon ResolveRequestCache()
кэшированием

выходных даю

Срабатывает
после извлечеJ

из запроса

инф:Jрмации о
Appllcatlon AcqulreRequestSta t e()
пользователе

перед

сохранением е

ю)ллекции сеа!

ш
В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

Вызывается ш
тем , как БУдет
выполнен защ

Appllcatlon Pr eRequestHandlerE x ecu t e () и сгенерируеп

HTML-КОа

обработчикаМI
страницы

Вызывается пс
Appllcatlon PostRequestHandle r Ex ecute()
обработки зап]

Вызывается то
Ю)гда информа

сеанса

сериализуется

Appllcatlon ReleaseRequestSta t e() ю)ллекции Ses~

чтобы стать
доступной в
следующем

запросе

Вызывается ш

добавле ни ем
информации в
Appllcatlon Upda t eReques t Cache()
выходных дйю
если он был
разрешен

Вызывается в
Ю)нце запроса

Appllcatlon EndRequest() используется /J


размещен ия кq

очистки

Демонстрация событий приложения

Приведем пример, иллюстрирующий работу рассмотренных методов


уровня при л ожен ия.

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• IJ$Создайте новый п устой проект с помощью кома нды


FilelNewlWeb SitelEmpty Web Site
• Г;;:;-Добавьте к проекту командой Website/Add New ItemIWeb Form
новую стра ни цу Default.aspx без файла отделенного кода и
модифицируйте ее так

<%@ Page Language="C#" %>

Листинг. Модифицированная страница Default.aspx


• IJ$Добавьте к про екту файл Web.config командой Website/Add New
ItemIWeb Сопfigшаtiоп РПе с ВЮlюченной о пци ей отладки, чтобы
е го код был таким

<?xml version="l .O'?>


< сопfigшаtiоп>
<system.web >
<compilation debug="true"l>
</system. web>
</соnfigшаtiоп>

Листинг Конфигурационный файл с включенной опцией

отладки

• Г;;:;-Добавьте к проекту файл GюЬаLаsах, выполнив команду


Website/Add New ItеmlGюЬа! Application Class, и за полните его
следУЮЩИМ кодом

<%@ Application Language="C#" %>

<script runat= "server''>

11**************************************************** ...
11******************** Обработч ики событий приложения *'
11**************************************************** ...

void Applk:ation_Start(obj ect se nder, EventArgs е)


(
IlНttpApplication Ap plication = new HttpApplicationO;

System DiagnostKs.Debug. WriteLine(


"** ** ******** Ap pocation_S tart********* '');
ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

void Аррlk:а tiоп_Епd( оЬjесt sender, EventArgs е)


(
System DiagnostKs. Debug. Write Line(
"** ** ******** Ар рlk:аtioп_Епd * ** ** ** ** ');
}

void Аррlk:а tiоп_Епо г(оЬjесt sепdе г, ЕvепtAгgs е)


(
System DiagnostKs. Debug. Write Line(
"** ** ******** Ар рlk:аtioп_Епог** ** ** ** *');
}

void Session_Start(object se nder, EventArgs е)


(
System DiagnostKs. Debug. Write Line(
"******* *****Sе ss iоп_Stагt********* ' );

void Session_End(object sender, EventArgs е)


(
System DiagnostKs.Debug. Write Line(
"** ** ********Sеssiоп_Епd* ** ** ** ** ');
}

//**************************************************** ...
//******************** Обработчики событий за про са *****.
//**************************************************** ...

void Аррlk:а tiоп_В еginRе q uеst( оЬjес t sender, EventArgs е)


(
Resp о nse. Write("< о 1> \n'');
Respo nse. Write("< li>Арр Ik:atio n_ BeginReq uest\n'');
}

void Аррlicа tiоп_А uthе пtiсаtеRе q uеst( оЬjес t sender, EventArgs е)


(
Resp о nse. Write("< li>Ар Р Ik:atio n_ A uthentk:ate Req uest\n'');
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

void Аррlk:аtiоп_АuthогizeRеquеst(оЬjесt sender, EventArgs е)


(
Resp о nse. Write("< li>Ар Р lk:atio n_ А utlю rize Req uest\n'');
}

void Аррlk:аtiоп_RеsоlvеRеquеstСасhe(оЬjесt sender, EventArgs е)


(
Resp о nse. Write("< li>Ар Р lk:atio n_ Reso lve RequestC ache \n'');
}

void Аррlk:а tiоп_АсquirеRеquеstS tаtе(оЬjесt sепdег, ЕvепtAгgs е)


(
Resp о nse. Write("< li>Арр lk:atio n_ Acq Шге RequestS ta te\n'');
}

void Аррlk:а tiоп_РгеRеq uе stНапdlегЕхесutе(о Ьj ес t sender, EventArgs


(
Resp о nse. Write("< li>Арр lk:atio n_ Рге RеquеstНапdlегЕхеcutе\n '');
}

void Аррlk:а tiоп_Ро stRеq uеstН а пdlегЕхесutе(оЬjес t sender, EventArg


(
Respo nse. Write("< li>Арр lk:atio n_ PostReq ues tНand ler Execute\n'');
}

void Аррlk:а tiоп_Rеleаsе Rеq uеs tStаtе(о Ьj есt sender, EventArgs е)


(
Respo nse. Write("< li>Арр lk:atio n_ Re lease Req uestS tate\n'');
}

void Аррlk:а tiоп_U рdаtе Rеquеs tСасhе(оЬjе с t sender, EventArgs е)


(
Respo nse. Write("< li>Арр lk:atio n_ U pd ate Req uestC ache\n'');
}

void Аррlk:а tiоп_ЕпdRеquеst(оЬjесt sепdе г, ЕvепtAгgs е)


{
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Resp о nsе. Write("< li>Арр lk:atio n_ EndReq uest\n '');


Respo nsе. Write("</o 1>\n'');
}

</script>

Листинг. Код файла Global.asax


• ~ыполните при ложе ние и в окне броуэера должен п оявиться
следУЮЩИЙ резул ьтат
1. Аррlicаtioп_ ВеginRеquеst
2. Аррlicаtioп_А uthе пtiсаtеRеquеst
з. Аррlicаtioп_А uthогizeRеquеst
4. Аррlicаtioп_ RеsоlvеRеquеstСасhе
5. Аррlicаtioп_АсquirеRе quеstS tаtе
б. Аррlicаtioп_Р геRеq uеstНа пdlегЕхесutе
7. Аррlicаtioп_Р оstRеquеstНапdlегЕхесutе
8. Аррlicаtioп_ RеleаsеRеquеs t Stаtе
9. Аррlicаtioп_Uрdаtе Rеquе s tСасhе
10. Аррlicаtioп_ ЕпdRеquеst
• ~ панели задач щелкните дважд ы на иконке тестового сервера

1003

• Г;::=Осmановиmе тестовый сервер щелчком н а кнопке Stop


~ ASP.NET Development Server - Port 1085
----- ~
ASP.NET De ....elopment Server
Run ASP.N ET a,pplicetions locelly. fu
Physic~1 P~th: IC:\VVI NN1\М iero s oft.N E1\Fra.rn ework\v2, 0,5 О 727\
Yirtu~1 P~th: l i~sp.netweb~dminfiles

Роп:

Root URL: httР"/ЛQCа.lhQS110В5/а.sр netweba.dminfiles

Stop
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• IJ$Откро й те (если его н е в и дн о) о кн о O utput оболоч ки кома ндой


View/O utput и об р ати те вни мани е, что в нем присугствует, в том
ч исле , и н фо р ма ц ия , выдаваемая обработч иками пр и ложе н ия и
сеан са , кот орая будет пр имер н о такой

************ Applicatio n_S tart** ** ** ** *


'WebDev. WebServer.EXE' (Managed):
Loaded 'С :\W IN NThIssembIy\GAC_M S IL \System. Web.Mobile\2.0.0.0_bO:
No symbols Ioaded.
'WebDev. WebServer.EXE' (Managed):
Loaded 'С:\W I NNТ\Мiсгоsо ft.N Е1\Fгаmеwо гk\v2.0.50727\Теmpогаry ASP.
App_Web_ayudlfun.dll', Symbo~ Ioaded .
************Sessio n_Start*********
'WebDev. WebServer.EXE' (Managed):
Loaded 'С :\W IN NThtssembIy\GAC_M S IL \System. Web. RegularExpressions\2
N о symbols Ioaded.
************Session_End*********
************Applicatio n_End *********
Тhe program '[1 800] WebDev. WebServer.EXE: Managed' has exited with code
Тhe program '[820] IEXPLORE.EXE: Script program' has exited with code О (О

Демонстрация п ерехв ата нео браб о танного со б ытия

• ~Добав ьте к п рое кту н овую страниц у Default2.aspx с фай лом


отделе н но го кода и н аз н ач ьте ее стар товой кома н дой Set As Start
Page
• ~3аполните в застр ани чн ом файле обработчик Page L oad ()
кодом деления н а ноль

protected void Page_Load(object sender, EventArgs е)


(
int а=О , Ь = l ;
int х = Ь / а;
)

• ~Откро й те фай л Globalasax, о ч исти те его и ско ррект ир уйте так

<%@ Аррliсаtюп Language="C#" % >


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<script runat= "server''>

void Аррlk:а tiоп_Епо г(оЬjесt sender, EventArgs е)


(
Response. Write("<h1 > ');
Rеsроnsе.Wгitе("Произошла какая- то ошибка < lhl >< hr /> ');
Resp о nse. Write( 5 erver. Gе tLа stEпо ГО. М essa ge .То 5 tringO);
Response.Write("<hr /> " + Sеrvег.GеtLа stЕ пог() .ТоS tгingО);
Server.C lеагЕпогО;
}

</script>

Листинг. Содержимое файла Global.asax


• г;.:.=установите в редакторе оболочки стран ицу Default2.aspx
текуще й и через контекстн ое меню вы п ол ните для нее команду
View in Browser

Html-ВbI Вод страницы будет таким

ОШl1бка

в таком объеме информации ТРУдно р азобраться и п оэтому обработчик


App l l ca tl on Er r or() программи сты используют только в

крайнем случае.
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Средства форматирования страниц

Каскад ные таблицы стилеk Добавление стилей в НТМL -дескри птор.


Добавлен и е стилей на Web-страницу ВнеlШlие стили. Применение
внеlШlИХ стилей в VlSua! Studio 2005. Темы. Приори теты оф:Jрмлени й и
стилевых нас троек. Оформления слож ных элементов управления.
Использова ни е внеlШlИХ CSS в теме. Прим енение общей темы в
конфигурационном файле. Применение тем по выбору пользователя .
Мастер-страницы. Генерация заготовки мастер-ст р аницы. Компоновка
содержимого мастер-страницы. Создание страниц содержимого для
масте р -страни цы. Программное управление мастер-страницей из
страницы содержимого. Многослойное подключение мастер-страниц.
Подключение мастер-страницы ч ерез конфигурационный файл.

Файлы к лекции Вы можете скачать здесь скачать:

httр :J/оkl.iпtШ. ruld е р аrtmeпtliпtеmеtlр rasp netl919.пp

Единообразие в оф:Jрмлении множества отдельных страниц сайта


является важной е го характеристикой. VlSua! Studio 2005 имеет три
возможности для подце ржки форматирования сайта:

1. Каскадные таблицы стилей ( CSS - Cascading Style Sheet) -


традиционное средство р асшире ния языка НТМL для управления
стилями тегов

2. Темы ( thеше ) - специфическое средство, позволяю щее определить


детали форматирования отдельных элеме н тов управления и
воспроизводить их на множестве страниц. Можно создать
несколько разных тем и при выборе одной из них автоматически
меняется оформление всех страниц , использующих эту тему
з. Этало нны е страницы ( master page ) - пр едставляют собой
м ного кр атн о используемые шаблоны страниц. Их еще на зывают
мастер -ст р ани цами. В шаблоне можно определить необходимые
детали оформления, такие как заголовки, п анели меню , банеры и
связать их с обычными страницами. После этого все
использующие шаблон страни цы буА.УГ иметь одинаковый дизайн.

Каскадные таблицы стилей

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Применение стандартиза ции требует пр ежде все го выработать


единообразный визуальный стиль оформле ния для каждого элемен та
ynравления. Начнем со знакомства с каскадны ми таблицалш стилей .
Каскад ны ми табли цы н азывают потому, что каждая и з них реализует
принцип : сти л ь в нугр е нн е го каска.ца перекрывает действие стилей всех
внешни х ка скадов.

ЭТО старое средство 4юрматирования , которое входи т в НТМL4 и


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

1. Внугре н няя (in/ine) - когда отдельные тет НТМ L имеют свои


и н дивидуаль ны е настр ойки стилей , областью действия которых
является только этот тег

2. Встроенная (embedded) - когда таблица стилей наход ится на


ст р анице внугри блока <head> и имеет описание стилей об щее
для тех дескрипторов ст р аницы, на которые она должна
действовать . Это и н дивидуальная настройка стилей для стра ницы
и областью их действия являются тет только одно го документа
з. Вн ешняя (liпkеd) - ко гда о пи са ние стилей находится в отдельном
файле и действуют они на те ст р аницы сайта, к которым
ПОДЮlючен этот файл

По отноше ни ю к эти м трем ти па м CSS также соблюдается свойство


каскадн ости , т.е . стиль внугренн е го каскада имеет более высокий
при оритет и перекрывает действие внешнего стиля. Поскольку за.цачеЙ
наше го курса является н е только и зучение возможностей Visual Studio
2005 в Web-программирован ии, рассмотрим кратко все п е речисленные
типы CSS .

Добавление стилей в НТМL-дескриптор

Хотя CSS обычно не пр име н яется для изменения вида каждого те га в


отдель н ости , но п ринци пи ально мож но это делать , особ е нно , когда
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

нужно перекрыть де йствие bhellD-lегО каскада стиля для конкретного


дескриптора. Син таксис прим енения внугреннего стиля на прим ере
дескриптора <h 1 > бу,цет таЮ1М

Сenектс р Списо к определен и й


HmL СТИЛ А

<h1 style="color:red; text·align:center"> ... </h 1>


1 11 ILJ 1 11 1 U
ATP l-1 бут Имя Знзч еl-lие Имя З",з ч ение Ко ",текст
Сiи.пя СВО ЙСiва СВО ЙСi в а сво ЙCi ва сво йства (сод ержа", ие)

Определенный в дескрипторе внугренний стиль бу,цет действовать


только на содержание этого дескриптора и перекрывать все
определ ения bhellD-lИХ стилей.

Пример

Пусть отдельный за головочный дескриптор будет определ ен в данном


докуме нт е так

<Ы style="color:red; text-аlign:сепtег">Э тот за головочный


текст будет ц е нтрирован в текущем докуме нт е и иметь красный
цв ет (бледный вид)! < /h l >

Ли стинг Заголовочный дескрипт ор этого док умента

Отклик броузера вы дел ен в рамочку и будет таЮ1М

Этот :saГОЛО80ЧНЫЙ 1еКС1 будет цеНТРИРО8ан 8 Тl!I(ущем документе И иметь краСНЫЙ цвет (бледный
8ИД) !

Добавление стилей на Web-страницу

Определение внугренних стилей отдельны х дескрипторов используется


редко. Чаще применяются встроенные сти л и , которые де йствуют в
пр еделах все й страницы. Встроенные стили размещаются внугри
ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

дескрип торно го блока <head> . .. </ head> в сво ем дескрипторном


блоке <style> ... </ style> . Си н такси с встрое нн ых стилей
следую щий

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

ДеCJ:рiolnТOр
СiИЛЯ

I I I I
<style type="textlcss ">
Селектор
HTML -теГcl
[ body
{
background : white url(MyWeb.jpg);
[ font-family: Arial, Helvetica, sans-serif;
}
Селектор
HTML -ПJГcI
[ h1
{
[ color: red ;
text-align: center;
}
Cnисо'
,.",=p ID [ #id1 , #id2, #id3
Н ТМL-обwпое {

[ font-size: 1 . 5ет;
font: bold italic;
}
Селе~iOР
r.ла сса
[ .myClass1
{
OnJ)eAMeH.,e
[ color: #9999FF;
"'"""
Селектор
}
для кК~~С~orо [ h2.myClass2
лt п а lOJГOB (h2) {

O"peд~e"" [ color: #OOOOFF


СП'\JII'I .

}
</style>
Атр и буг type= " te x t/ css " дескриптора ст и ля указы в ает броузеру,
ч то в се п оследую щи е сти л и бу,цуг С 55 - стилями. В п р иведенном пр име р е
селекторы body и h1 сов падаю т с и менами де скрипторов НТМ L.
ш
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

С писок селекторов НТМL·объектов содержит значения


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

Имена массов ". и мя кл асса 11 выбираются пр оизвольно В то м


дескрипторе докуме н та, где необходимо при мени ть определ енный в
массе стиль, используется атрибуг с 1 а s s = " и мя кла сс а ". Кла сс ы
для конкретного вида те гов " тег . им я класса " используются

только в те гах задан ного ти па по той же самой схеме


сlаss= " и мя класса ".

Прим е р

Пусть страница имеет код , приведе нный ниже (файл embedded.htm в


каталоге css рассматрива емо й темы)
<html>
<head >
< title > Документ со встроенной CSS </tide >
<meta сопtепt=''tехt/html; charset=windows·1251" httр·еquiv="сопtепt·Туре
<style type=''text/css''>
body
(
background:white ш~М уWеЬ.jрg);
fопt·fumilу:АгiaL
Helvetk:a, sапs·sе гif;
}

h1
(
co lor:#FFOOOO;
text· а ligп :сепtег;
)
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

#TextBoxl
(
font- family:"Courier N ew", СОШЕ Г, mоrю;
font-size:24px;
font:bold italic;
backgrourkl-соloг :# ООООFF;
co lor:yellow;
width:400;
)

.ЬtпRеsuh
(
backgrourкl- ima ge :url(Ba с k grОШld lmage. Ьmр );
co lor:white;
}
</style>
<lhead >
<body>
<Ы >
Заполните аикету! < lhl >
< fопn>
<р>

Введите Ф ИО:
<input id= 'TextBoxl " name= 'TextBoxl " type="text">
</p>
<р>

Введите ИНН:
<input id= 'TextBox2 " naше =' ТеxtВох2 " type="text">
</p>
<center>
<input id =' 'Вuttопl '' сla ss='Ъ tnRеsult " name= "Buttonl"
tуре =' Ъuttоп " vаluе="О тослать' '>
</center>
</foпn>
<!body>
< lhtшl>

Листинг Страница CSS\emЬedded.htm со встроенной CSS

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Чтобы получить оригинальн ый результат, щелкните на кнопке ,


расположенной в н изу приведенного примера кода. Если на Вашем
броуэере включена п одцержка JavaScript, то он запустит новую страницу
в отдельном окне, где можно п осмотреть результат с использова ни ем

встроенной CSS. "С тильный " снимок моего результата будет таким

--;1 Документ (:0 впроенной CSS - Мicrоsоft Internet Explorer

Заполните анкету!

Введите ФИО: Снетков Владимир МИхайлович'

Введите ИНН: IДоцент 007

Внешние стили

Внешними считаются стили, которые хранятся в отдельн ом файле


текстовою формата (чаще с расширением .css, но бу,цет работать
любое расширение). Содержимое стиля в отдельном файле отличается
от в строенного стиля тем, что во внешнем стиле не должно быть
дескрипторных скобок <style></style> . Кроме этого ,
п одключение стилевого файла к НТМL-докуме нту выполняется
добавлением в блок <head> . .. </ head> дескриптора < l ink> или
директивы @import .

Пусть имеется два файла с внешними стилями и п роизвольными


и менами, например , header . css de f aul t . css .
и Вот варианты их
п одключения в НТМL-документ MyPage . h tт ( обязательно в
за головочный блок <head> . .. </ head» :

Вариа н ты подключени я CSS к НТМL-документу

Вариант В блоке <head> файла MyPage.hrт


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Подключа ется <link rel="stylesheet" href=''header.css''>


одн а CSS

Подключается <link rel="stylesheet" href=''header.css''>


две CSS <link rel="stylesheet" href="default.css''>

<style type=''text/css''>
П одключа ется Н е П Оi
@imро rtшl(hеаdе г.с ss);
одн а CSS NetscG
</style >

<style type=''text/css''>
Подключается @imро rtшl(hеаdе г.с ss); Н е п D,i
две CSS @imро rtшl(dеfault . сss); NetscG
</style >

8сам(
П одключа ется header
две CSS (в <style type=''text/css''> голая

стран иц у @imро rtшl(hеаdе г.с ss); П ОДЮII

имп ор тир уется </style >


ц е по чка CSS) @iщ

<style type=''text/css''>
П одключа ется @imро rtшl(hеаdе г.с ss); Поряр
две CSS </style > н е ВЮ

<link rel="stylesheet" href="default.css''>

<link rel="stylesheet" href="default.css''>


Под ключается <style type=''text/css''> Поряр
две CSS @imро rtшl(hеаdе г.с ss); н е ВЮ

</style >

<link rel="stylesheet" href="default.css''>


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<style type=''text/css''>

@imроrtшl(hеаdег. сss);

body
Подкл
(
внеШf
background:white шI(МуWеЬ.jрg);
допол
fопt-familу:Агial, Helvetica, sans-serif;
встрОЕ
)

Встра
h1
теор еl
(
им еть
color:#FFOOOO;
приор
text - а Iign:center;
внеШf
)
заВИСI
Под ключается
КОНкрЕ
три CSS #TextВoxl
Поэто
(
изб еж
foпt-familу:"Сошiег New", Сошieг, топо;
недор
font-size:24 px;
однов
font:bok:l italic;
прим€
Ьас kground - со 10 г:#ОООО F F ;
встрОЕ
соlогуеПоw;
стиле
width:400;
) Поряр
н е вт

.btnResult
(
background- image:urI(Background Image .Ьтр);
color:white;
)

</style >

<style type=''text/css''>
body
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

(
backgro und:white urI(MyWeb.jpg);
fопt-familу:Аrial, Helvetica, sans-serif;
)
ПОДЮJ
внеШf
h1
допол
(
встрОЕ
color:#FFOOOO;
text- а lign:center;
Встра
)
теореl

иметь
#TextВoxl
приор
(
внеШf
foпt-familу:"Соuriе r New", Сошier, топо;
заВИСI
По,цЮJючается font-size:24 px;
КО Н крЕ
три CSS font:bok:l ita lic;
Поэто
Ьас kground - со 10 r:#OOOO F F ;
избеж
co lor:yellow;
недор
width:400;
однов
)
прим€

встрОЕ
.btnResult
стиле
(
background- image:urI(Background Image .Ьтр); ПорЯ,ll
co lor:white; н е ВЮ
)

@importurl(header. css);

</style >

<link rel="stylesheet" href="default.css''>

Чтобы проверить сказанное , выпол ните сл едующее (вручную , бе з VlSual


5tudio 2005 !)
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• ~ айдите в прила гаемом катало ге CSS файл embedded.htm и в


этом же каталоге сделайте из него две коп и и с име н ами
Tes t css . htт и ExternalCSS . css
• ~Откройте в текстовом редакторе Блокнот файл Te5tCSS.htm и
замените в за головке <head> встроенный сти ль на строку
ПОДЮJючения внешней CSS

<link rel="5tylesheet" href= ''ExternaICSS .cS5''>

• ~Откройте в текстовом редакторе Блокнот файл


ExternalC S S .С55 и оставьте только чистый код селекторов и

определений стилей
• r;;.;:rОткроЙте страни цу TestCSS.htm в броузере и у6едитесь, что
получился тот же результат, что и при использова н ии встроенных

стилей
~ Документ со встроенной CSS - Мicrоsоft Internet Explorer


Заполните анкету!

Введите ФИО:

Введите ИНН: I

IIIIJ DooC ПГГ [gj му соmр~tff .d

• ~О п робуйте другие вариан ты паДЮJючения внешней CSS ,


п риведенные ранее (есл и хотите!)

Применение в нешних стилей в Visua! Studio 2005

Итак, внешняя CSS, это обыч н ый текстовый файл, которому


традиционно назначают р асширение .С55 дЛЯ лучшей уз н аваемости , хотя
ш
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

может использоваться любое р асшире н ие. Мы убедились, что его


можно создавать отдельно в любом текстовом редакторе, а затем
использовать в Web- п роекте. Но VlSual Studio 2005 имеет свои
встроенные средства создания CSS.

• IJ$Создайте через Проводник Windows новый каталог с имен ем


WebS i te6
• ~Откройте этот каталог через оболочку VlSual Studio 2005
командой File!OpenlWeb Site
• ~ыполните кома н ду Website!Add New Item, выбери те вариан т
Sty1e Sheet и оставьте имя файла по умолчан и ю
StyleSheet . css

Оболочка добав и т в проект новый файл каскадной таблицы стилей и


покажет панель инструментов Style Sheet, помо гающую редактировать
этот файл. Здесь , п равда, возможн остей не так бо гато, как в
специализированных редакторах стилей, но глав н ая линия все- таки
соблюдается .

Наша глав н ая задача, как про граммистов, - п онимать и правильно


приме н ять CSS, а н а чем она подготовлена и ли кем (пусть у дизайнеров
голова бол и т), не очень важно. Но если прис п ичи т, можно
порекомендовать специализированный редактор CSS, который
позволяет кодировать вручную или использовать Удобн ый и н терфейс .
ЭТО редактор StyleMaster, июlюрмацию о котором можно н айти в Internet
по ссылке ссылка: http ://www.westciv.comlstyle_master!

Не будем ис п ользовать созданную оболочкой за готовку


Sty1eS heet.css, а
научимся ПОДЮlючать свою таблицу стилей Externa!CSS .css к тестовому
файлу TestC 5 S.htm, н о уже в проекте WebSite6

• ~Откройте созданн ый н ами ра н ее почти пустой проект


WebSite6 (если не открыт)
• ~ыполните командУ Website!Add Existing Item. В появившемся
диалоговом окне войди те в катало г CSS (мы в нем уже работали)
и отметьте н ужные файлы, у,церживая при этом Юlавишу Ctr!

ш
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Add EXlstNlg Item - C:\Chalf \Book\WEB\ASP.NET 2.0\6) Стандартизация cтpEI-IVrЦ WebSlte6

Look п: ICJ css

f,1y Project5

Ае llJ mе : ::::J
~1";;е:Ь"r
;: ;;-.;')---=======----'з~
; ,
FIes ofty]::e :
L
После щелчка на кнопке Add оболочка физически скопирует
выделенные файлы в файл проекта WеЬSitеб и они появятся в панели
Sоlutiоп Explorer. Если вы н е увидели там этих файлов , то щелкни те на
кнопке Refresh панели Sо lutioп Explorer, чтобы оболочка обновила
п редставляемую п осле ко пи рования информацию

sj ExternalCSS.css
0iI MyWeb.jpg
f! StyleSh€€t.css
~ TestcSS.ht m

• ~ азначьте статическую стра ниц у TestCSS.htm стартовой


(команда Set As Start Page )и зап усти те ее на выполнение , чтобы
убедиться, что и в оболочке о н а работает точно также, как и р анее
в авто н ом н ом режи ме

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Если страница н е содержит иcnолняемого ASP.NET -кода , то сист е ма


AS P.NET ничего с ней не делает, а отсылает в н еизмен н ом ви де
ЮJИ е нту. Если посмотреть на исходный HTML -кo d присланной броузеру
страницы (команда View Sошсе контекстного меню окна броузера) , то
он остался тем же самым , каким мы его пр ежд е сочинили

<html>
<head >
< title>Докуме н т со встрое нн ой CSS </tide>
<meta content=''text!html; charset=windows- 1251" http-еquiv="Со пtепt-Туре
< liпk rel="stylesheet" href=''Externa lCSS.css''>
<lhead>
<body>
<Ы >
Запол ни те aH KeTy! <lhl >
< fо пn>
<р>

Введи те Ф И О :
< inри! id='TextBoxl " naше='ТеxtВох l " type=''text''>
</р>
<р>

Введи те ИН Н:
< inри! id='TextBox2" naше='ТеxtВох2" type=''text''>
</р>
<center>
< inри! id=''В uttо пl '' сlass='Ъ tnRеs ult " паmе::::''Вuttопl''
tуре='Ъuttоп" vаluе="Отослать">
</center>
</foпn>
</body>
<lhtml>

Ли с тинг Исх одный НТМL - к од присланной с траницы TestCSS.htm

• ~Откройте двойным щел чком в So lution Explorer файл


TestCSS .hun на редактирование

Отвлечемся немного от темы стил е й и обратим в ни мание на то , сколько


строк нашего кода подчеркнул редактор оболочки красн ой ли ни ей. ЭТО

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

значит, что его не устраивает синтаксис кода, н а п роверку которо го он

на строен

~~tCSShtm • х

Client OIJjects & Events J iJ'Ю Ev i'flts)


<1J1m..J.>-
- <h" ",d>-
<t itl,, >-До кумеliТ со ~ СТРО " liliОЙ
css <!titl ,, ;.
~ content = "te x t!h tm l; сhаrsе t =wi пdО\olS - 1251" http-equiv= "c ont e nt- Тype">­
<link rеl = " s t'Уlезh ееt" href = "Ex ternalCSS .C 5S">-
<! head;.
- <body>
<h l>-
SаПQЛни~е aHK e~ y ! <! hl>­

'l!ШР
'р'
В ~" ДИТ " ФИО :

<~ id='Text Boxl" na~e=" TextB o xl" t ype = "text'>


<J p>
'р'
В~"ДИТ" ИНН :

<~ id * 'To xtBo x 2" na~o * "Tox tB ox 2" t ypo * "te x t '>
<Jp>
<c e nt er>
<l!:иn!1 id = ·Buttolll ' сlаgg = " Ьt ПRезult " nan e =" BlH tonl "
typ,,- "bu tto n " v ",lu,,- "Отослать">
<Jcente r>
<! fo rrr.>
< !Ьodу>
<! htm l;.

Давайте ус покоим редактор , сообщив ем)'; чтобы о н nроверял синтаки с


чистого НТМL , а не ХНТМL .

• ~ыnолнит е кома н ду Tools/Customize и отметьте флажок НТМL


Sошсе Editing
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Customlze ? х

Toobs5 I Comm ards I


Toc:bJ-5:
г Buld ~W ..
Г dass Des Q:le f
Г Сmtехt~
Г Data Desigl R:ename ..
Г Dаrnз::е D..:"q"am
Г DeOOg Deete
Г Debug Location
Г Devtе Reset ...
Г C:tb;J Editor
Г FormatthJ
Г НС

г Imag€ Edtor
Г Lзуrut
р" мenu Взr

г Use l:f"ge ,=са;

Р" Show ScrOOlTps оп toobars

г ShJw st-utrut keys п ScreenTps

в верхней части каркаса оболочки п оявится пан ел ь инструментов


на стройки НТМL·р едактора, в которой нужно устан ови ть через
раскрывающийся список опцию НТМL4.01

Exple<er 6.0
I ТП'срп~t Explorer 3.02 I N€tscape f\Javigator 3,0

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


синтаксиса документа HTML ·peaaKmop п очти успокаив ается. Остается
п ад черкнугы м открывающий НТМL· де скрuпmор <form> . Чтобы
и збави тьс я и от этого замечания реда ктора , нужно до бавить атрибуг
act i on

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

< fо пn action=TestCSS .htm>

Посмотрите , как и в этом случае нам услужл иво помогает подсказчик


кода IntelliSense, пр едл агающий выбр ать из списка файлов целевую
страниц у на сервере, которая БУдет принимать да нн ые от формы

<fo r m action;:::>
<р> dP ExternalCSS,css
В:в Е iP StyleSheet.css
< ir aJiI TestcSS.htm I
</ р> if' Web.Coofig
<р> О Plck URL

Вообще-то, больши н ство броузеров п ри п ро п уще нн ом атрибyrе


ас ti оп полагают, что ц елевой БУдет та же самая стра ниц а. Но чтобы
успокоить НТМL редакто р окончательн о, укажем эту страницу яв н о .

• ~ызовите контекстное меню щелчком п равой кнопки мыши на


свободном месте верхней ч асти каркаса оболочки и сбросьте
флажок HTML Sошсе Editing, чтобы закрыть одноиме нн ую панель
настройки редактора
• u;.;ryдали те и з заголово чн ого блока страницы код подключения
вне lШl е й таблицы стилей TestCSS.htm, а им е нн о, удал ите строку

<link rel="stylesheet" href= ''ExternalCSS .css''>

• ~ ереведите страницу в режим Design и посмотри те, какая она


с р азу стала блеклая (тусклая , бледная , н евзрачная , некрасивая , ... -
СТУде н т Леша З иборов , продолжай! Только ты можешь дочитать до
этого места!)
• г;:.=Захватите мышью в панели Solutio n Exp lorer файл
ExternalCSS.css и п е ренесите е го на страницу, которая сразу
преобразится уже н а этапе проектирования
• Г;:;=Вер нитесь в режим Sошсе и убедитесь, что оболочка добавила
нужный дескриптор подключения CSS в нужное место
• ~О п ять Удал ите дескриптор подключения CSS
• r;:;nерейдите в режим Design, откройте панель Properties и через
р аскрывающийся с пи сок в ее верхней части выберите объект
DO CUMENT
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• ~ айдите свойство StyleSheet и п одключи те к нему


таблицу ExtemalCSS.css через ди алоговое окно. Оболочка опять
добавит нужный дескриптор подключения CSS в нужн ое место
elect Stylesheet ""iJ~
Ргор::! fo~s : Сопtentз offo lde- :
,:,.~~~---
-~ С:\ ... \WebS iteб \

Fie s oflfl:e : ISlyle9-teets (*.css) :.:J


c ancel I
• г;;;?Очистите поле свойства StyleSheet , оболочка вновь
удали т дескриптор ПОДЮlюче н ия

Таблицы CSS при меняются не только к простым дескрипторам


НТМL , но и к дескрипторам серверных элементов управления .
Давайте это проверим, поместив на стран ицу серверный элемент
управления , н а п ример , Label .

• г;;;?Откройте п ан ель Toolbox

Мы видим, ЧТО доступ н ой является только вкладка НТМL, п отому,


что наша тестовая стран и ца TestCSS .hun имеет расшире ни е .hun.

• г;.:.=переименУЙте в панели Sоlutiоп Explorer тестовую страницу в


TestCSS.aspx и сделайте ее же п ринимающей, исп р авив
дескриптор < f o r m>

<form а с tiоп= Те stСSS . аsр х runat="server''>


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• ~ оместите н а страниц у и з вкrщцки: Standard текстовую метку


Label и в п а нел и Properties о пр еделите
о CssClass=label

о Т е х t=Ст иль к л асса label

• Г;;:;=Откройте ч ерез Solution Ехрюгег фай л ExternalCSS.css и


доб авьте стилевое пр ав и л о для класса label

body
(
background:white ш~МуWеЬ.jрg);
fo nt· fumily:AriaL Helvetk:a, sans-serif;
)

h1
(
co lor:#FFOOOO;
text-align:center;
)

#TextВoxl
(
fо пt-fumilу: "Соuriег New", СОШЕ Г, mоrю;
fo nt-size:24px;
fo nt:bold italic;
Ьа с kgrourкl- сою г:#О 00 О РР;
co lor:yellow;
width:400;
)

.btnResult
(
Ьа с kgrourкl- irrn ge :url(Ba с k grОШld lmage. Ьтр );
co lor:white;
)

.labe!
{
ba ckgrourкl- сою r:G гееп;
co lor:White;
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

font:bo!d ;
fo nt-size:x-Iarge;
fо пt- fumilу:Со шieг New;
}

Листинг . Добавление нового стиля в !Сласс label файла

ExternalCSS.css
• ~ыполните страницу, кото р ая в браузере станет такой
'!I Документ (О BcтpOeHHOf1 свв - Мicrоsоft Internet Explorer D Х

Заполните анкету!
Введите ФИО: Снетков В.М.

В ведите И Н Н: г,1дc:C""
ц'''"H::c
' ."OO''',,-----

Стиль класса label

Краткое знакомство с CSS и их п одцержкой в VlSua! Studio 2005


зако н чили!

Темы

Применение CSS ДЛЯ стилевого оqюрмления стра ни ц ASP.NET имеет


н екоторые ограничения. Дело в том, что CSS являются реше ни ем
стороны браузерй . О н и оqюрмляют уже готовые дескрипторы НТМ L .
п оступившие на броузер. Если их бездумно применять на стороне
сервера к элеме н там управления , которые MOryr генерировать для

отп р авки клие н ту целый пакет НТМL-дескрunторов, то конечное


стилевое оqю р мление может не в полной мере соответствовать

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

желаниям р аз р аботч ика. Для таких ситуа ций существуют другие


средства ф:Jрматирования, которые являются родным решением
элементов управления на стороне сервера и по зволяют полн остью

контролировать их стилевое оф:J рм ление. Одним из таких средств


являются темы.

Как и CSS, темы определяют набор стилей, которые на зывают


оф:Jрмлениями и которые можно применять на многих ст р аницах
ASP.NET Особенности тем состоят в следующем:

1. Стилевые пар аметры тем преобразуются элементами управления


во внугренние стили НТМL-дескрипторов при ген ераци и HTML-
кода и не мо гуг быть реализованы напря мую на стороне броузера
2. Темы MOryr при менять ся вместе с таблицами стилей, тогда
клиен ту отсылается комбинированный стиль, определяемый CSS
и сгенерированным стилем темы

з. CSS можно использовать как часть темы


4. Темы MOryr подключать ся к множеству страниц через
конфигурационные файлы
s. К странице одновременно может применяться только одна тема ,
темы друг с другом не объединяются. Темы для одной и той же
страницы можно менять только про грамм но при каждой новой
загрузке страницы

б. Приоритетом внугреннего стиля элемен та управления и его


стиля, определенного в теме, можно управлять

7. Разработчик долже н создавать свои темы с н уля или может


загружать готовые темы с других Web-сайтов, например, ссылка:
http ://www.asp .net. Но если тема используется, то для обеспечения
гибкос ти и автономности она должна физичесЮ1 находи ться в
своем каталоге прилож е ния .

Все темы помещаются в каталог с зарезервированным именем


Арр Themes , который можно добавить к приложению в панели
Sоlutiоп Explorer, выполнив командУ Add ASP.NET Fokler!Гheme
контекстного меню для узла приложения

'"
В.М. СН"",,,В Про,рйммupoвtJNШ' Na ASP.NET

Soution Explorer - С:\.. \wеЬSltеб\ ...- ~ Х

ffiJ Build Web Site

PubI,sh Web S,te


. Md New Item ...

О Add Exismg Item ...

New FoIder

Add ASP.NEТ FctJer ~I Е<п

Add Reference ... Лрр_Соdе

Add Web Reference ... Арр _ GlobalResources

Щ View Class Diagram Арр _LocalResources

~ Сору Web Site ... Арр _ W ebReferences

Start Орtions ... Лрр_Dаta

~ View in BroVIIser App_Вro\oVsers

Browse With ... lПете

~ ReIТesh Folder

Jt; CUt
Сору

Paste

§I Property Pages

Каждая те ма д олжна храниться в своей одн оим е нной папке и может


состоять из нескольки х файлов текстово г о формата с п роизвольным
именем и обязательным расширением .skin. Э ти файлы называются
файлами оqюрмлений и добавляются коман дой Website/Add New ltem
ч е рез соответствующее диалоговое окно
в.м. С""",,,в

..
Про,раммupoвtJNШ' 110 ASP.NET

.1J~
lIf .-".-

,- •-
Terrp~tes :

~ ~ 1 [\]
~.~ ~ ~
S'ik> Shoot х м.. F ik> Т ох ! F ik> XSL т F ik> Cl:>Go D"'Ч~ m

Seif"ch 011....,
TE"l'~tes".

Па п ку App_Тhemes отдельно можно и не создавать, n отому, что п ри

попытке добавле ни я нового файла тип а Skin Fi 1 е оболочка


предложит автоматически создать папку App_Тhemes

Мicr050ft Vl5ual Studio

You if'e attemptn;J to add а the me fie to ifl ASP . ~ ~aЬ:xl. Fcr а the me fie to ье generaly сc:mu m Юle Il
уc:u site, it Sh::<Jd ье placed Ilside the ' Арр_Тhe т б ' folder . Wc:Ud you lI<e to place the the me fie Il the
' Арр_Тheтб ' folder7

Для темы можно все стилевые настройки элементов ynравления


разместить в одном файле оqюрмлений, а можно и в нескольких. Иногда
просто Удоб нее грynnировать оqюрмления по отдельным категориям
элементов ynравления в соответствующих файлах. ДЛЯ ASP.NET это не
имеет ни како го значения, п оскол ьку она все равно считывает все файлы
оqюрмлений в каталоге темы как неделимое целое определения одн ой
темы.

Проверим сказа нн ое на п рактике:

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• IJ$Добавьте к пр оекту н о вую страницу TestTheme.aspx с


р аздел ьны м кодом

• Г;;:;-Добавьте на страницу из вюыДки Standard следующие


э леме нты управле ни я

о BulletedList
о Label
о CheckBo x
о But t on
• ~ азначьте свойства Te x t этих элеме н тов, чтобы их внешний
ви д н а этапе nроектuрованuя был таким

estтheme.aspx

• Туризм
• Сиорт
• Музык
· т:шцы J Itекстовая метка ~Флажок

• ~ пан ели Sо lutiоп Exp lorer сделайте ко пию файла TestTheme.aspx


и при свой те копии имя F i rstS k i n . азр х . Из н е го мы в
даль н е йше м сделаем файл оформле н ий
• ~дали те файл подцержки FirstSkin.aspx.cs
• ~ астройте деюыративно в пан ел и Properties стилевые
свойства объектов страницы FirstSkin.aspx
о BulletedL i stl :
• BackColor~ " Yel l ow "
• Bo r de r Colo r = " Red "
• Borde r S t yle= " R i dge "
• Borde r Wi dth= " 1 0 p x "
• Bulle t Sty l e= " Numbe r ed "
• Fo r eColor~ " Blue "
о Label l :
• Bac k Color~ " Blue "
• Fo r eColor= " Yel l ow "
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• ТооlТ i р= "Т е к стовая м етка "


о Chec k Bo xl :
• BackColor= " Red "
• Borde r S t yle= " Gr oove "
• Fопt-Воld= " Т r uе "
• Fo r eColor= " Wh i te "
о Button :
• BackColor= " #FFCOC O"
• Bo r de r Colo r = " Blu e"
• Borde r S t yle= " Sol i d "
• Borde r Wi dth= " 2 p x"
• Fопt - Воld= " Т r uе "
• Fo r eColor= " Blue "

Внешний вид элеме н тов ynравления после проведенных стил евых


н астроек до лжен быть таким

FirstSkin.aspx*

1.
2.
з.

4. lliiiiiiiiiil
"1 екстовая метк

III Отправить

• ~ ерейдите в режим S ошсе и Удалите из файла FirstSkm.aspx


весь код, кроме открывающих дескрипторов элемен тов
ynравления , в которых тож е Удал и те атрибуты , не относящиеся к
настройкам стиля. Должн о остаться следующее

<asp:BulletedList runat="server"
ВасkСоюг=''Уеllоw'' BorderColor='Red"
BorderStyle='Ridge" BorderWidth="10px"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

BulletStyle=''N umbered '' FоrеСоlоr= ' 'Вше '' 1>


<asp:Label runat="server"
ВасkСоюr= ' 'Вluе '' F oreColor= ''Yellow''
ТооIПр =' Текстовая метка " 1>
<asp:CheckBox nmat="server"
ВасkСоюr= 'Red" BorderS tyle= "Groove"
Font- Bold='True" ForeColor= 'White" 1>
<asp:Button nmat="server"
ВасkСоюr= ''#FFC ОС О " ВоrdеrСоlоr=' 'Вше ''
BorderStyle="Solid" BorderWidth=''2px''
Font- Bold='True" ForеСоlоr= ' 'Вluе '' 1>

Листинг. ОстаВШИЙСR код в файле FirstSkin.aspx


• ~ рисвойте файлу FirstSkin.aspx новое расширение FirstSkill.skill
• ~Создайте в приложении папку с зарезервированным им ен ем
Арр The mes и определите в ней подпапку с именем MyTheme,
в которой бу;цуг хр аниться файлы оqюрмлений нашего прим е ра
FirstSkill.skin )

• ~ панели Sо шtiоп Explorer захватите мышью файл FirstSkin.skill


и переместите его в папку MyTheme

Тема подключается к странице с помощью атрибуга Theтe директивы


@Page . Так, например , при применении темы с именем каталога
MyTheme к нашей тестовой странице TestTheme.aspx директива будет
выглядеть так

<%@ Page Language="C#" AutoEventWireup=''true''


CodeFile='TestTheme.aspx.cs" Inherits='TestTheme"
Theme='MyTheme" %>

Тему можно подключить к странице и в панели Properties через свойство


Theтe объекта DOCUMENT . В этом случае оболочка автоматически
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

добавит атрибуг Theme к директиве @Page с выбранным значением.

• ~ раскрывающемся с пи ске панели Properties для страницы


TestTheme.aspx выделите объект DOCUMENT и установи те
свойство Theme= " My Th e me "
• r;:;'н азначьте страницу TestTheme.aspx стартовой и выполните ее

Должен получиться такой результат

1. Туризм
2. Спорт
3. узыка
4. Танцы

Текстовая метк

Отправить

in1J"anet

Естественно , что п ерео пр еделяются только те стилевые настройки


элементов управления страницы, которые указаны в ПОДЮlюче нной
теме. Остальные нас тройки н е п ереопределяются.

Приоритеты оформлений и стилевых настроек

Вспомните , что в при ПОД Юlючении CSS стили начинают действовать


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

на отображение элементов немедленно, на этапе проектuрованuя. При


определении же только свойства Theme действие стилей мы увидим
только на этапе выполнения. Механизм тем реализует стилевые
на стройки элементов управления, подключенные к ф:Jрматируемой
странице и з вне .

Но элементы управления страницы MOryr иметь свои ИН ДИВИдУаль ные


стилевые настройки , которые мы им декларативно назначим при
разработке страницы. В этом случае приоритет БУдУГ иметь
одноименные настройки, указанные в подключаемой теме. Проверим
это ...

• r;:;'и змените в странице TestТheme.aspx атрибугы


Bac k Colo r == " Black " и Fo r eCo l or== " Yel l ow " элемента
Check Bo x l , чтобы он имел черный ф:Jн и желтый текст
• r;:;'выполните страницу и убедитесь, что элемент CheckBo x l
БУдет иметь цвет ф:Jна красный, а цвет текста белый ,
определенные в подключенной к странице т еме

Theme= " My T he me "

Объект DOCU MENT страницы им еет еще одно свойство


Sty l eSheetThe me , к которому также можно подключить внешнюю

тему. В этом случае приоритет будуг иметь ИНДИВИдУальные настройки


элементов управления , которые в ни х были явно определены. Но те
на стройки по умолчанию, которые мы не определяли на странице , но
которые содержатся в теме, действуют н а свойства по умолчанию.

'"
в м С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

ОАliои менные стили т е мы


п ерео пределяlOТ СТИЛи

элементов управлен ия страницы

Те ма Тем а
подкл юче на подключена

че реэ че реэ

Theme Slу lеShееПhe mе

Q Q
,sro ,sro
~ ~
'"
:I:
m
а.
t;
о:
s:
:I:
Ф
~
~
>-
о
о

~
/j
- --'>
~
~
о
о

~
о
s
/j
'"
:I:
m
<>
о:
s:
:I:
а.
о-

Ф
.,m
с:;
~ ~ :iim
а. !i !i а.
~
">- .,"u ., ">-
jj
о-
:I:

'"
:;

ci5'"
,

~
о

~
~
т
S
,"
- ,

~
о

~
~
т
S
:I:

'"
:;
'"
ci5
jj
о-

"
z
" "
Любой вариант влияния темы на элемент управления можно
отключить, если установи ть в этом элементе свойство
EnableThem in g= " False " .

• ~Для страницы TestTheme.aspx в панели Properties выдел ите


объект DOCU MENT, очистите п оле его свойства
StyleSheetTheme и п одключите тему MyThe me к свойству
Theme
• r;:;'выделите объект CheckBoxl с индивидуальными

настройками BackColo r = " Blac k ";


Fo r eColor= " Yellow " и установи те ДJlЯ него

EnableThe mi ng= " Fa l se "


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• ~ыполните тестовую страницу и убеди тесь , что красивые


настройки темы для этого элемента н е действуют, а остались
только настройки по умолчанию и индивидуальная н астройка
цвета фона и текста

+-Back •
Address 1161fNebSiteE •

1. Туризм
2. Спорт
3. !музыка
4. Тшщы

C heckBoxl .En
Текстовая метк .Флажо

Отправить

с Ьес kBo х l . Е паЬ leTheming=' 'F alse"

• ~ыделите объект
CheckBox l и верните для него
EnableThe ming= " True "

Именованные оформления элементов управления в


теме

Сти левые настройки , которые мы до сих п ор определяли в файле


оф:Jрмлений темы , являются настройками по умолчанию и
приме н яются для всех элементов управления указанного типа. Но
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

иногда может понадобиться обеспечить в теме для элементов


управления одного и того же типа разные варианты оформления, в
зависимости от контекста их применения на странице. Например ,
текстовые поля MOryr различаться по месту их использования или по

типу содержащихся данных (ввод пароля , прием цифровой информации


и т. д. ).

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


одного и того же элемента управления, то ASP.NET выдаст ошибку об
обнаружении неоднозначности. В этом случае в теме нужно применять
именованные оформления с помощью атрибуга SkinID . Тогда в
странице наряду с общим ПОДЮlючением т емы с помощью свойства
Theme можно БУдет определить значения S kin ID именованных
настроек элементов управления.

Знач е ния Skin ID в определениях т ем ы долж но быть уникальным


только в группе однотипных элементов. Э то значит, что мы можем
создать несколько групп настроек разнотипных элементов с

одинаковыми з начениями атрибуга Ski nI О и ПОДЮlючать из одной


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

• ~Добавьте в страницу TestTheme.aspx элемент Table из


ВЮlадки НТМL панели Toolbox. Таблицу расположите между
кнопкой и предшесmвующил1U элеменmал1U. Она будет
структурировать расположение части элементов управления на

странице

Для нашего примера таблица долж на иметь три столбца и пять строк.
Оболочка не обладает развитыми средствами редактирования таблиц ,
поэтому проще настроить таблицу в режиме Source .

• ~ оместите и з ВЮlадки Stапdаrd панели Toolbox в средний


столбец таблицы пять серверных элементов Label , а в правый -
пять серверных элементов CheckBo x
• ~становите в добавле нных объектах свойства в соответствии
с контекстом таблицы

SkinID не ПОДЮlючен:действуют общие


В.М. С Н"",,,В Про,рй ммupoвtJN Ш' Na ASP. N ET

н астройки п о умолчанию

Именованные настройки подключены:


LаЬеlЗ СhесkВо х З
SkiпID= " Vа ri апtЗ "

Именованные настройки подключены:


Labe14 CheckBo x 4
SkinID= " Var i ant4 "
SkinID= " Var i ant5 " п од ключен , но

тема подавлена: Labe15 CheckBo x 5


Enable Theming= " False "
Подключен н есуществующий
S k i n I 0= " ХХ Х " : настройки тем ы не Labe16 CheckBo x 6
действуют

• IJ$Откройте файл оформл е ний FirstSkin.skin и дополните его


индивидуальными на стройками стил е й , чтобы общий код его стал
таким

<asp:BulletedList runat="server" ВасkСоloг=' 'Уеllоw'' BorderCo!or='Red


BorderSty!e='Ridge" BorderWidth="10px"
BulletSty!e=''Numbered '' FогеСо!ог=' 'Вluе '' 1>
<asp:Labe! runat="server" Ba c k C olor =' OВ!ue " Fоге С оloг= ' 'УеlЮw ''
ТооIПр =' Текстовая метка " 1>
<asp:CheckBox nmat="server" BackCo!or="Red " BorderSty1e="Groove "
Fопt- Bo!d ='True" ForeCo!or='White" 1>
<asp:Button nmat="server" BackCo!or=''#FFCOCO'' Borde rC oIoF ' OВ!ue "
BorderSty!e="Solid" BorderWidth=''2px''
Fопt- Bo!d ='True" ForеСо!ог=' 'В !uе '' 1>

<asp:Labe! ruпаt="sеrvег" Васk С оloг =' 'В!uе '' ForeCoIoF ''Yellow'' SkinII
<asp:CheckBox nmat="server" BackCo!or="Red " BorderSty1e="Groove "
Fопt- Bo!d ='True" ForeCo!or='White" SkinID =' 'Vагiaпt2 '' 1>
<asp:Labe! ruпаt="sеrvег" FогеСо!ог=' 'Вluе '' SkinID =' 'VагiaпtЗ'' 1>
<asp:CheckBox nmat="server" BorderSty!e=''Dotted '' Fопt- Bo!d='True"
ForeCo!oF 'R ed " SkinI D =' 'VагiaпtЗ '' 1>
<asp:Labe! runat="server" Ва с k С оloг =' 'УеlЮw '' ForeCo!oF 'Red" SkinID
<asp:CheckBox nmat="server" BackCo!or="Red " BorderSty1e="Solid"
ForeCo!oF ''YeUow'' SkinID=' 'Variant4 '' 1>
<asp:Labe! runat="server" Ba c k C olor =' OВ!ue " FогеС оloг= ' 'УеlЮw '' SkinII
<asp:CheckBox nmat="server" BackCo!or="Red " BorderSty1e="Groove "
Fопt- Bo!d ='True" ForeCo!or='White" SkinID=''Variant5'' 1>
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Fопt- Bold='True" ForeColor='White" SkiпID =''Vа гia пt5'' 1>


<asp:Label ruпаt="sеrvег" Васk С оloг=''Вluе '' Fоге С оloг= "УеlЮw " SkiпII
<asp:CheckBox nmat= "server" BackColor="Red " BorderStyle="Groove "
Fопt- Bold='True" ForeColor='White" SkiпID =''Vа гia пt6 '' 1>

Листинг Код файла оформлений FirstSkiп.skiп темы

МуТЬете

• ~ыполните тестовую страницу, результат д олжен быть

Можно сделать все свои стилевые оформления именованными. В этом


случае , если в элементах ynравления на странице не БУдет задан атрибyr
s kin 1 О, ТО эти стилевые настройки никогда не БУдyr применяться.

Оформления сложных элементов управления

Сложные элементы ynравления включают в себя несколько разделов ,

требующих ИНДИВИ дУальных стилевых оформлений. Эти настройки


MOryr занимать много места, если их использовать вместе с

дескрипторным кодом страницы. Поэтому для таких элементов

выносить громо здки й код стилевых настроек в отдельный файл


оформлений очень даже удобно. Приведем пример с настройками
элемента Calendar .

• ~Создайте новую страницу со встроенным кодом подце ржки и с


именем TestCalenda r . азр х

• ~ азначьте страницу стартовой и поместите на нее и з вкладки


Stапdагd элемент ynравления Calendar
• ~Определите для объекта Ca l endarl следующие стилевые
настройки

<asp:Calendar ID="Calendarl " runat="server"


ВасkСоюг= ''white'' F orесоlог= 'ы ak" ВогdегСоюг= ' ыak"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Fопt-Size=''9рt'' Height="2S0px" Width="SOOpx"


N extPrevF опnat= "S ho пМ о пth" Sе lectio пм ode= "day"
>
< Sе lected Оа yS tyle Ва ck С о Ior= "d агkorапgе "
ForeCo lor=''white'' />
<DayStyle ВасkСоlor="orапgе " Fo nt-Bo ld =' 'true''
ForeCo lor= ''white'' />
<N extPrevStyle Fo nt-Bold=''true'' Font-Size=''8pt''
ForeCo lor= ''white'' />
<DayHeaderSty1e Fопt- Воkl =' 'truе '' Font-Size=''8pt''
FогеСоlог= ''#ЗЗЗЗЗЗ'' Height="8pt" />
<TrtleStyle BackColor="firebrk:k" ВогdегStуlе= "попе "
Fопt- Bold=''true'' Fопt-Size= " 12рt "
ForeCo lor= ''white'' Height="12pt" />
<OtherMonthDayStyle Васk Со lог= "паvаjоwЫtе "
Fопt- Bold="false" ForeColor="darkgray" />
</as p:Calerкlar>

Листинг . Стилевые настройки объекта Calendarl страницы


TestCalendar.aspx
• r;:;'в пан ел и Solution ЕХРloгег вы зовите ко нтекстное мен ю для
папки M yТheтe и командой Add New ltem создайте н овый файл
оф:Jрмлений с именем Calendar . skin
• ~Запом ни те, как пишугся коммен тар ии в дескр ип тор н ых файлах
ASP.NET и очистите ав томатически с генерированный текст в
файле оф:Jрмлений Calendar. skin
• U$Скопирyitте из стран иц ы TestCalendar.aspx в файл оф:Jрмлений
Calendar.skin вес ь дескр ипторный код объекта Ca l endar 1 вместе
с его стилевыми настройками и удали те в ко пи и атрибyr
ID= " Calendar l "
• ~далите в дескрип торном коде страницы TestCalendar.aspx код
стилевых настроек объекта Са 1 е nda r 1 , выделенный в
пр иведенной выше таблице красным цветом , чтобы от объекта
осталось только простое ' 'мокрое место"

<asp:Calendar ID="Calendarl" runat="server''>


</as p:Calerкlar>

• Г;;:;=Через панель Properties выделите объект DOCUMENT и


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• ~ ерез панель Properties выделите объект DOCUMENT и


ПОЮlючите к странице тему My Theme в свойстве Theme
• ~ыполните страницу и убедитесь, что вынесен ный со
страницы в тему большой блок стилевых настр оек элемента
Calendar работает также, как если бы он находился на самой
странице

Ниже приведены два варианта пр едставле ния объекта Calendar 1

Address I itе6;Теstcаlепd.aг.aspх'" /f'GJ

< ~eJIЪ 2007 г. >


Пи Вт Ср Чт Пт Сб Вс
26 27 28 29 30 31 1
- - - - - - -

2345678
9 10 11 12 13 14 15
16 17 18 19 20 21 22 Внешние стилевые
настройки работают
23 24 25 26 27 28 29
30 1 2 3 4 5 6

Local iп1Т.:nеt

Тема с н астройками не ПОДЮlючена

с п омощью внешних файлов оформлен ий и тем можно ПОДЮlючать


стилевые компоненты рисунков . Пусть мы хотим исп ользовать
н есколько кнопок элемента управления ImageBut ton с разными

рисунками в завис и мости от контекста применения. П усть для кнопок

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

позволяют легко решить эту за.цачу.

• ~ панели Solution Explorer через контекстное меню на папке


МуThеше командой New Folder создайте подпапку
Ви t t onImages для хранения рисунков кнопок

• ~ панели Solution Explorer ч е рез контекстное меню на новой


папке But t onI mages командой Add Existing Item вызовите
диалоговое окно копирования и из прилагаемого каталога Рictшеs
скопируйте файлы ButtonCanceLpng, ButtonOK.png
dd E><i5tng Item C·\a.Jr\Book \\\I!:В\ЛSr>.NЕТ 2 0\6) СтаНдcVТИ'aLjИЯ CTPCf-И..l\WеЬ8,tеб

Lcok п 1"::' Pictиos

му FТ o)eCtS

Fles oftyp€: IAl FI""(" ,*)

• ~Добавьте на страницу TestCalendar.aspx две картиночных


кнопки lmageButton из ВЮIaДКИ Standard панели Toolbox и
настройте через одноименные свойства в панели Properties их
дескрипторы так

<asp:lmageButton ID='1mageButtonl " runat="server"


lma geUr l="~/App_ThemeslМyThemelВuttonlmageslВuttonOK.png"
SkinlD=''OKButton'' />
<asp:lmageButton ID='1mageButton2 " runat="server"
lma gеUг l="~/Ар р_Thе шеslМуThеmеlВuttoпlma gеslВ uttoпСа пс еLрпg
S kinlD =''CancelВutton'' 1>

• ~ контекстном меню на папке MyTheme выполните команду


Add N ew Itе щ чтобы добавить в тему новый файл оформления
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Add New I tещ чтобы добавить в тему новый файл оформления


Bu t tOnS . s ki n
---.11~

[;; о:::


T...-rpl""'"

i!i. ~ ~ ..;
[\J ~ iJ
5ty1e Sheet X~ L f i le Te,t File

"- ~ 9- T г1 е
liIIIiII С",,, D"Ч~m

• ~Скопируйте настроенные дескрипторы элемен тов

ImageBu t ton в файл Butto ns.skin, п редвари тельн о очистив его

от автоматически сген ерированн ых инструкций


• IJ$Откорректируйте оформле н ия в файле Вuttопs.skШ, чтобы они
выглядели так

<asp:lmageButton runat="selVer"
lma geUr l="ButtonlmagesIБ uttonOK.png"
SkinlD=''OKButton'' />
<asp:lmageButton runat="selVer"
lma ge Url="Butto nlmage sIБ utto пС апсе Lpng"
S kinlD =''С апсеlВuttоп'' />

Обратите в н имание, что мы в атрибуге I mag e Ur l указали пугь только


отно с ительно каталога темы. Пугь до кор н я виртуально го катало га сай та
"~/Арр _Тhеmе slМуThеше/" добави т ASP.NET при компиляц и и это го кода
и автоматически п реобразует его в абсолют н ый п угь файловой си стемы
сервера.
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

SOU"on Explorer '" J;l Х


~I
~ С:\ ... \WеЬSitеб\
В--- Арр_ТПете:;
В МуТПеmе
В·, ButtonImages
<iI ВuttonCancel.png
[iiI Вuttогr:Жong

г: : ~~С:~~:~~п
1___ ~ Frstskin,skin
Iii BackgroundImage.bmp
;" ... ~ ExternalCSS.css
<iI MyWeb.Jpg
i!j Sty1eShe€t.css
I.@] Testcalendar,aspx
lЗ TestcSS,aspx
В--- [з ТеsППеmе.asрх
~ TestTheme.aspx,cs
~ Web.Config

• ~Откорректируйте дескрипторы ImageButton в файле


TestCalendar.aspx. чтобы от них осталось следующее

<asp:lmageButton ID='1mageButtonl" runat="server" SkinID="OKButtol


<asp:lmageButton ID='1mageButton2" runat="server" S kinID ="CancelВ ul

• ~ сполните стран ицу TestCalendar.aspx и получите следующий


результат с внешним и оформлениями в темах сложно го кален да ря
и р и суноч н ых кнопок
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

'1 untitled Page - Мiсrоsоft Internet Explorer


Fi e Edit V ~!Y Fava ites Tools !-'ер

~BacК. ". -t ". 10 aJ Gj I If\ Sea-сh !±I Fava ites t@Мeda


Acktess 111 htф:/frx.ft"ost: llбlМеЬэtе6!Теstcаlendcr ,.aspx

:!'ш Апрель 2007 г. DПii

IIи С, В,

Cq nce
ОК

По смотр и те, на ст р анице на ходи тся дескрип торны й код тол ько создания
сложных элементов управления, а большой КОД тонких нас троек
вын есе н в файлы темы. Э то очень удобно и для ц е нтр ал и зова нн ого
и зменения стилевого оф:J рм ления элементов управле ния , и для
ч и табел ьн ости самой страницы.
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

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

Если У нас имеются хорошие наработЮ1 CSS, то ASP.NET позволяет


и спользовать их дл я qюрматирования НТМL-дескрипторов актив н ой
страницы. Чтобы П ОДЮIючить CSS к активной странице , нужно сделать
следующее:

1. Ско пировать файл вне l.Шl еЙ CSS в каталог тем ы


2. ВЮlючить тему в свойстве Theme объекта DOCUMENT страницы
з. Если CSS содержит Юlассы , устанавливать им е на нужных ЮIассов
в свойстве CssClass элементов управления ст р аницы
4. Вместо дескриптора <link> , используемого п ри тради ци онном
способе П ОДЮIючения к странице , проследи ть, чтобы
заголовоч н ый дескриптор стра ницы был объявлен как серверный
« head r unat= " server " » . В этом случае ASP.NET сама
с генерирует столько дескрипторов <l i nk> в выходн ом HTML -
коде , сколько файлов CSS бу,цет находи ться в ПОДЮlюченной к
странице теме

Проверим это на пр имере. В панели Solutlon Explorer оболочЮ1


выполните следующие действия:

• ~Скопируйте файл TestCSS.aspx и назначьте копии и мя


ThemeCSS . asp x и назначьте новую страниц у стартов ой
• ~Скопируйте таблицу стилей Externak:SS.css и назначьте копии
имя ThemeCSS . css
• ~ ереместите файл ThemeCSS .css в п апку MyTheme проекта
• ~де р жив ая ЮIавишу Ctrl, выделите файлы Васkgrоundlmagе.Ьшр
и MyWeb.jpg в корне виртуал ьного каталога и выполните для них
командУ Сору кон текстного меню
• ~елкните правой кнопкой мыlllИ на узле МуThеше и
выполните кома н ду Paste, чтобы рисунЮ1 оказались в одном
катало ге с таблицей ThemeCSS.css
• ~Откройте страницу ThemeCSS.aspx на редакти рование,
удал ите в ней дескр иптор <l i nk> ПОДЮlючения внешней
таблицы стилей. Удостоверьтесь, что заголовочный дескриптор
<head> является серверным
• Г;:;=Исполните страницу и убедитесь, что стили пока не

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

действуют, потом у что н е подключены

Теперь только осталось подключить тему My Th e me к странице.

• ~ пан ели Properties выделите объект DOCUMEN T и установи те


е го свойство Theme в значение MyTheme
• ~ыполните страницу ThemeCSS.aspx и убедитесь, что стили из
внеlШ-lей таблицы ThemeCSS.css работают
• ~ азначьте страницу TestCSS.aspx, гд е мы CSS использовали
напрямую, стартовой и выполните ее

Чтобы сделать некоторые выводы, сравним полученные результаты ,


прив еденные ниже в уменьшенном виде.

''Найдите десять отличий!" Ха-ха-ха ...

Заполните анкету! "'---- ....


Заполните анкету!

Введите ИНН : ГI- - - - - -


I
С т иль класса laЬel
Стиль класса label

• Т уриз ...
• Отдых
' Е'"
z.
3.
4.
","Х
няти.
<g I
• ЗаНЯ ТIiIЯ
• Сп"",
Тet: СТО8ая .меп:а г Фл ажсж Страница ThemeCSS.aspx

С траница TestCSS.aspx

Используется CSS для

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Используется ТОЛЬЮ) CSS для несе рверных н есервер ных элементов

элементов управления и для одного управления , а для

серверного. Для остальных сервер н ых сер верных элементов

элементов стили неопредел ены де йствуют оф:Jрмления


темы

Выводы:

1. На левом рисунке п одключена только одн а CSS, Ю)торая стилизует


дескрипторы НТМL на стороне броузера, и то, только те, Ю)торые
не им е ют внугрен ни х стилей .
2. На правом рисунке CSS и оф:Jрмления т ем ы действуют вместе .
С истема ASP.NET н а стороне сервера трасф:Jрмирует серверные
элементы упр авления в НТМL-дескрипторы с уже готовыми
внугренними стилями, согласно оф:Jрмле ни ям темы . На
заключительн ом этапе, перед отсылЮ)й сф:Jрмированной HTML-
страницы н а броузер, она п одключает дескрипторам <l i nk>
ссылку на внеlШlЮЮ CSS. Броузер , п олучив ссылку на внеlШlЮЮ
CSS, проверяет в соответствии справилом приоритета стилей
возможн ость их применения только в тех дескр ипторах НТМL , в
Ю)торых нет своих в н угренних стилей, сген ер ированных на

сервере .

Теперь осталось проверить тот факт, что ASP.NET подключает к


странице все таблицы стилей , п омещенные в тему.

• ~ каталоге Theme сделайте еще три Ю)пии файла ThemeCSS.css


с им е н ем ThemeCSSl . css , ThemeCSS 2 . css ,
ТhеmеСSSЗ . сss

• ~ азначьте страницуThеmеСSS.аsрх стартовой и выполните ее


• ~ a появившемся окне броузера выполните Ю)манду
Ю)нтекстного меню View Source для присланной с сервера

статической страницы

Исследуем блок Ю)да за головочного дескриптора <h e ad> . Он будет


содержать такие строки

<head >
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

< title > Документ со встр ое нн ой CSS </tide >


<meta сопtепt= ' 'tехt/html; charset=wind ows- 1251" http-еquiv="Со пtепt-Туре
< liпk href="Ap p_The meslМyThemetтhe me CSS. css" type=''text/cs5'' rel="sty~
< liпk hre f= "Ap p_The meslМyThe metтhe me CSS 1.c5s" type=''text/c5s'' re l="5t~
< liпk hre f= "Ap p_The meslМyThe metтhe me CSS2 . c5S" type=''text/c5s'' re l="5t~
< liпk hrе f= "Ар р_Thе mеslМуТhe mеtтhе mе СSSЗ . С5S" type=''text/c5s'' re l="5t~
</head>

Мы видим, что среда испо лне ния AS P.NET ав томатиче ски вставляет в
код столько дескрипторов подключения CSS, сколько файлов с
таблицам и находится в каталоге темы. Обратите внимание , что п уги в
ссылках прописываются относительно корня виртуального каталога, в

котором находится сама страница. Ну и по следнее, строки подключения


CSS в HTML-кode пр описываются системой ASP.NET, ну совсем как по
теории .

• r;:Fyдалите лишние файлы ThemeCSS1.c5s, ThemeCSS2.css и


Thеmе СSSЗ .С5S , чтобы они дальше не мельтешили у нас в гла зах

Применение общей темы в конфигурационном файле

До сих пор мы спокойно удаляли файл web.config приложения с


уверенностью, что он будет вновь создан оболочкой. Тем более, что там
содержалась только за го товка кода. Теперь ПРИlШlа пора редактировать
этот файл и Удалять его уже будет жалко.

Ранее мы говорили, что при под ключении к странице темы (в наших


при мерах - MyTheme ) через свойство Theme объекта DOCUMENT
оболочка ав том атически вставляет соответствующий атрибуг в
директиву @Page этой стран ицы , тем самым под ключая к странице
индивидуальную тему.

Например

<% @ Ра gе L апguagе="С#"Thеmе=''МуТhe mе ''% >

Обычно пр оектировщики ратуют за одинаковое стилевое оформление


страниц и используют в каждой ИЗ ни х одну и ту же тему. В этом случае
удобнее будет не под ключать каждУЮ страницу к одной и той же тем е, а

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

указать общую тем у в конфигурационноЛ1 файле, которая будет


использоваться по умол чанию многими страницами , когда в них не

ПQЦключена ин дивидуал ьная тема . Для этого нужно вставить в


конфuгурационный файл текущего каталога Web-сай та
соответствующее указание для ASP.NET

• Г;:;=Откройте страницы наlШfХ примеров, использующих темы , а


именно: TestTheme.aspx, TestCalendar.aspx, ThemeCSS.aspx, и
удали те в них из директивы @Page атрибyr
Theme= " My Th e me "
• u;.;rн азначая каждую страницу стартовой , исполните их по
очереди, чтобы убедиться , чт о ОТЮlюченная тема в них не
действует. Пока получилас ь грустная, унылая картина
• IJ$Откройте на редактирование заготовку файла web.config,
автоматически созданную оболочкой
• Г;;:;=Отредактируйте код файла web.config, добавив всего один
дескриптор с указанием общей темы <pages
theme= " My Th e me " / >, и сохраните изм ен е ния на диске

Ниже приведен окончательный код файла web.config с указанием общей


темы по умолчанию, в котором убраны громоздкие комментарии и
пустые дескрипторы

<?xml vеrsЮп="l . О '?>


< с опfigшаtioп>
<system.web>
<compilation debug=''true''/>
< а uthепtk:аtiоп mode='Windows"/>
<pages theme="MyTheme" />
</system. web>
</сопfigша tioп>

Листинг Код файла web.config с подключением темы по

умолчанию, перекрываlOЩей индивидуальные настройки элементов


управления

• r;.:.=назначая каждую и з перечисленных выше страниц стартовой ,


вновь исполните их по очереди, чтобы убедиться , что тема опять
заработала так, как будто-бы она была индиви дуал ьно подключена
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

к каждой странице

Если нужно сделать так, чт обы общая т ема действовала по умолчанию


на множестве страниц , но не пер еза писыв ала на них ИНДИВИдУальные

стилевые настройки элементов ynравления, то конфигурационный файл


долже н быть таким

<?xml version="1.0'?>
< с опfigшаtioп>
<system.web>
<compilation debug=''true''/>
<authentk:ation mode='Windows"/>
<pages styleSheetТheme=' M yТhe me" />
</system. web>
</сопfigша tioп>

Листинг Код файла web.config с подключением темы по


умолчанию, не перекрывающей индивидуальные настройки
элементов управления

Если на какой-нибудь странице нужно сделать так, чтобы общая тема не


де йствов ала на нее по умолчанию, то есть два варианта:

1. Установить для страни цы ИН ДИВИ дУальную тему, как ЭТО мы

делали раньше, вставив в директиву @Page атрибyr


Тhеmе= " Дру г ая т ем а "

2. Вообще ОТЮJючить тем у, чтобы действовали ИНДИВИдУальные


стиливые свойства элементов ynравления, на знач е нные нами или
уста новленные п о умолча нию библиотечными знач е ния ми. Для
этого в директиву @Page страницы н ужно вставить атрибyr
EnableThe ming= " fa l se "

Следует заметить, что есл и к странице явно ПОДЮJючена CSS


дескриптором <l i n k > или в конфигурационном файле каталога, где
размещена страница, установлена тема по умолчанию, содержащая хотя

бы одну
CSS , то ОТЮJючение темы по умолча нию атрибyrом
EnableThem i ng= " f al se " ОТЮJючает только skin -файлы, CSS все
равно останется ПОДЮJюченноЙ.
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Во всех наших при мерах мы создавали актив ны е страницы в кор н евом


виртуальном каталоге саЙта. Но для сайта с тысячами страниц это
неприемлемый способ. С траницы могуг группироваться (брыкаться ,
кусаться, кричать "Я пойду жаловаться в обком!") по любому признаку;
например тематическому; и размещаться в отдельных папка х развитой
древовидной системы виртуальных каталогов. Корнем это го дерева
должен быть виртуальный каталог сайта, его еще называют корнем
Web- дерева.

В развитом Web-дереве применение общей темы по умолчанию


является Удобным способом стилизации страниц. В каждом каталоге
можно разместить отдельный файл wеЬ.сопfig со своей общей темой и
все ст р аницы этого каталога будуг использовать эту тему по умолчанию .

Применение тем по выбору пользователя

До сих пор мы рассматривали случай, ко гда р азработчик сам жестко


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

конфигурационного файла.

Все, что нужно сделать, это предУсмотреть на странице интерфейс


выбора темы, а в коде страницы динамически присвоить свойству
Page . Theme или Page . StyleSheetTheme выбранное
пользователем значение. При этом важно понимать, что тема
настраивается перед инициализацией страницы, поэтому
соответствующий код нужно поместить в обработчик
Page Р r е I П l t() Если это сделать позже, в обработчиках других
событий, то попытка присвоить новое значение свойству
Page . Theme или Page . S t yleSheet Theme вызовет ошибку
компиляции.

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


создания стран ицы , когда присваивать свойству темы новое значение
уже поздно. Поэтому дина мическое задание темы н ужно выполнять в
два этапа:

'"
В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

1. Прочитать выбор пользователя, когда это станет возможным


по сле полной загрузки страницы
2. Принудительно п е резапустить страницу на сервере , чтобы в
обработчике Page Prelnlt () на з начить новую тему

При перезапуске страницы она должна быть пере адр есована на саму
себя. Такую операцию можно выполнить либо методом
Response . Red i rect() , либо методом Server . Transfer() .
Первый метод реализует полный ЦИЮl с отправкой на броузер и
ав томатическим возвращением на сервер. Он тр атит лишнее время на
пересылку Второй метод перезапускает страницу сразу на сервере без
ЦИЮlа ч е ре з клиен та. Но есть одна существенная особенность: оба
метода сбрасывают состояние вида всех элементов управления и
запускают страницу как в при п ервом за просе. Поскольку выбирать не
из чего, то мы выбир аем Pepsi и второй метод Se rve r . Т ran sf еr ()!

Рассмотрим все это на примере. Прежде всего, нужно создать несколько


тем , чтоб ы было и з чего пользователю выбирать.

• ~ пан ел и Sulutioп Explo rer вызовите контекстное меню для


папки MyTheme и выполните команду Сору
• ~ пан ел и Sulutioп Explo rer вызовите контекстное меню для
папки App_Themes, где должны храниться все темы приложения ,
и выполните на ней команду Paste два раза, чтобы создать еще две
тем ы

• u;.;rп рисвоЙте копиям таЮ1е замысловатые имена, ка Ю1е давал и


нам в глубоком детств е на ули ц е у родного батюшки , например ,
MyTheme 1 и MyThe me 2

Обратите внимание, что новые темы имеют старое содержание, которое


было бы желательно подправи ть, чтобы нагл ядно видеть влияние
выбранной темы на офо рм ление страницы. Мы это сделаем попозж е и
ПОМЯПllе - об чем должна болеть голова , пр ежде всего, у нашего
дизайнера ( за llПо ему; акаянному; только деньrn плотють ). Н а ше дело -
режь , мей и запускай. СТУде нт З иборов! - и ... чтобы еще р аботало!

Уч итывая , что протокол НТГР не подцерживает сохранение состояний


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

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

MOryг быть cookie - наборы ( куки -фа йлы) на компьютере юшента ,


которые мы туда за пишем без его ведома, если он забыл выключить их
паддержку. Э ТО MOryг быть скрытые поля состояния вида (
VIEWSTATE ), которые мы будем пересылать ТУда -сюда. ЭТО MOryг быть
глобальные объекты уровня сеанса или приложения , которые
существуют на сервере, пока не зако нчится сеанс с пользователем или

не закроется ( на обед или профилактику ) приложе ни е. Мы выбираем


свободу, демократию и объект уровня сеанса Ses s i оп !

• r;:Fчерез панель Solution Explorer копируйте в корневой


виртуальный каталог нашего сайта с примерами файл
TestTheme.aspx и назовите е го Tes t Sw i tchThemes . asp x
• IJ$Определите новую страницу TestSwitchThemes.aspx стартовой
• ~Откройте файл TestSwitchThemes.aspx на редактирование и
добавьте в верхнюю часть страницы из вкладки Standard элемент
по льзовател ьского интерфейса для выбора темы, раскрывающийся
Dr opDownLi s t
список

• ~ереименуйте lD списка в lstSw i t chThemes


• r;:Fчерез панель Properties в режиме Еvепts создайте для списка
заготовку обработчика события Selec t edInde x Changed ,
которое поступит на сервер с обратной отсылкой, если
пользователь изменит выбор в списке
• r;:;='Добавьте на страницу п еред списком серверный элемент
Label с именем lblF ir stLoad

На всякий пожарный случай (чтобы вам - его скопировать, а мне -


отчитаться по объему текста перед зав. кафедрой Горенским Б.М.) ,
приведУ полный дескрипторный код, который будет иметь страница
после проведения по след них "оперативно-следственных" мероприятий

<%@ Page L апguagе="С#" Аutо ЕvепtWirеuр=' 'truе ''


CodeFile='TestS witchТhemes.aspx.cs" Iпhегits = 'TestТheme" % >

<html xm1пs=''httр ://www.wЗ.огgl1999/xhtml'' >


<head nmat="server">
<title>TecT применения TeM </tide>
<lhead>
<body>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

< fопn id= "forml " runat= "server''>


<div>
<asp:Labe! ID=''lblFirstLoad'' runat="server" Text=''Labe!'' 1>
<asp :DropDownList ID =''lst5witchТheme s'' runat= "server"
О п5 е !ected lndexC hanged = "lst5 witchТhemes _ 5 е lected IndexC ha nged
</asp:DropDownList>
< Ьг 1>
< Ьг 1>
<asp :ВullеtеdList ID =''Вullеtеd Listl '' runat="server''>
< asp :Listl tem> Тур и зм </asp :Listl tem>
< asp :Listl tem> С п о pT</asp :ListI tem>
< asp :Listl tem> М узы ка </asp :ListI tem>
< asp :Listl tem> Тан Ц ы </asp :ListI tem>
</asp:BulletedList>
<asp:Labe! ID=''Labe!l '' runat= "server" Теxt='Текстовая метка " 1>
<asp:CheckBox ID="CheckBoxl" runat= "server" Теxt="Флажок"
ВасkСо!ог=''В!асk '' ForеСоюг=''Уеllоw'' EnableТheming='True" 1>
< Ьг 1>
< Ьг 1>
< Ь > Тема подключена к странице ч ерез свойство Тhеше объекта I
< Ьг 1>
<tab!e width= "100%" border="l ">
<tr>
<td >
5kinID не подключен: действуют общие настройки по умо
</td>
<td >
<asp:Labe! ID=''Label2'' runat="server" Text= ''Label2 '' 1>
</td>
<td >
<asp:CheckBox ID="CheckBox2" runat= "server" Text= "C heckE
</td>
</tr>
<tr>
<td >
Им е н ованные настройки подключены: 5kinID=''VагiaпtЗ''
</td>
<td >
<asp:Labe! ID =' 'LаЬеlЗ '' runat="server" Техt= ' 'LаЬеlЗ ''

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

SkiпID =''Vа гia пtЗ'' 1>


</td>
<td >
<asp:CheckBox ID="С hесkВохЗ" runat="server"
Техt=''С hесkВохЗ'' SkiпID=''VагiaпtЗ '' 1>
</td>
</tr>
<tr>
<td >
Им ен ова нны е на ст р ойки П GДЮlюч ены: SkinID=''Variant4''
</td>
<td>
<asp:Labe! ID=''Label4 '' ruпаt= "s еrvег" Text=''Label4''
SkiпID =' 'Vагiaпt4 '' 1>
</td>
<td >
<asp:CheckBox ID="CheckBox4" runat="server" Text= "CheckE
SkiпID =''Vа гia пt4 '' 1>
</td>
</tr>
<tr>
<td >
SkiпI D =''Vа гia пt5'' ПОДЮlюче н , но т ема подавл е на: EnableThI
</td>
<td >
<asp:Labe! ID=''LabelS'' ruпаt="s еrvег"Text=''LabelS''
ЕпаЬ!еТhemiпg=''F аlsе '' SkiпID =''VагiaпtS '' 1>
</td>
<td>
<asp:CheckBox ID="C heckBox5" runat="server" Text= "C heckE
ЕnaЬ!еТhemiпg=''F аlsе '' SkiпID =''VагiaпtS '' 1>
</td>
</tr>
<tr>
<td >
ПОДЮlюче н н есуществующий SkinID="XXX": на стр ойки п
</td>
<td >
<asp:Labe! ID=''LabeI6'' ruпа t="s еrvег" Text=''Labe!6''
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

SkinID="XXX" 1>
</td>
<td >
<asp:CheckBox ID="С hесkВохб " runat="server" Text= "C heckE
SkinID="XXX" 1>
</td>
</tr>
</table>
<br 1>
<aspButton ID=''Вuttопl '' runat="server" Теxt= "Отправить " 1>
</div>
</form>
<!body>
</html>

Листинг Окончательный дескрипторный "ОД страницы

TestSwitchThemes.aspx

• г;;;?Откройте на редактирование файл ю)Да

TestSwitchThemes.aspx.cs и зап ол н ите е го так

using System;
Ilusing System.Data;
Ilusing System.Configuration;
Ilusing System.Co Uectio ns;
Ilusing System.Web;
Ilusing System.Web.Security;
Ilusing System.Web.UI;
Ilusing System.Web.UI.WebContro ls;
Ilusing System.Web.UI.WebContro ls.WebParts;
Ilusing System.Web.UI.HtmlControls;

public partial class TestТheme : System Web.UI.Page


(
protected void Page_Load(object sender, EventArgs е)
{
if (!Page.lsPostВack)
{
IblFirstLoad.Text = ' Перв ая загрузка страницы ";
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

11 3аполняем список именами каталогов тем


SystemIO.Directorylnfo thешеDir =
new 5ystemIO.Directorylnfo(5erver.MapPath("App_Themes'));
1<;t5witchThemes.DataTextField = "Name";
1<;t5witсhThеmes.Dаtа50шсе = themeDir.GetDirectoriesO;
1<;t5 witchThemes. Оа taBind О;
}
e~e
IblFirstLoad.Text = 'Повторная загрузка страницы";
}

protected void Page_Prelnit(object sender, EventArgs е)


{
if (Session['Тheme"] != null)
{
11 Был ранее сохраненный выбор, ВЮlючить его
Page.Theme = (stгing)5еssiоп[ ' Тhеше'1;

11 Восстанавливаем новое состояние списка


1<;t5witchThemes.Selectedlndex = (int)5ession["index'1;
11 Восстанавливаем текущее состояние "Флажка"
CheckBoxl.Checked = (Ьооl)5еssioп["Флажок'1;
)
}

protected void IstSwitchThemes_5electedlndexChanged(object sender, Event


(
11 3апоминаем новый выбор пользователя
Session['Тheme'1 = Ist5witchThemes.SelectedValue;
11 3апоминаем новое состояние списка
Session["index"] = IstSwitchThemes.Selectedlndex;
11 Сохраняем текущее состояние "Флажка"
Sеssioп["Флажок"] = CheckBoxl.Checked;

11 Первый вариант:
11 Обновляем страницу с полным ЦИЮlом,
11 чтобы новая тема вступила в действие
IlResponse.Redirect(Request. Url ToStringO);
ш
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

11 Второй вариант:
11 Обновляем страницу без пол н ого ЦИЮJa ,
11 чтобы новая тема вступила в действие
5 erver. Transfer(Request. F ile Р ath);
}
}

Ли стинг Код вы бора темы файла TestSwitchThemes.a spx .cs

Прежде, чем выполнить страницу, сделаем некоторые пояснения п о


прив еденному С#-коду

1. Объявления пространства имен закомментирова ны специально


как н еис пользуемые в данном файле (хотя это можно и н е делать) .
Действи тельно:
о объ екты пользовательского интерфейса определ ены в
дескрипторной ча сти страницы ;
о масс Directorylnfo мы явно указали с пространством
имен Sys te m. 10 и компилятор его увидит

о объ екты Sess i on , Se r ve r, Response , Request


яв л яются общедоступными свойствами масса
Syste m. Web . U1 . Page , который наследуется нашим
массом TestTheme , а значит явно преобретает все эти
свойства
2. Оставлено незакомментирова нны м объявл е ние пр остранства
имен System только потому, ЧТО В коде имеются Юlючевые слова

st r ing , i n t, boo l, используемые при явном приведении


типов . Но и его можно было бы закомментировать , если
использовать полные и мена библ иотечных типов
Sys t em . s t ring , Syste m.i n t, Sys t em . bool
з. При прин у,цительной п ерезагрузке страницы полностью

сбрасывается состояние вида ее элементов управлен и я, поэтому


нужно искать д ругие с по собы сохранения и х состояния. Мы
позаботили с ь об этом только для списка и ОДного фrJaжка .
4. Язык С# допускает использование в и дентификаторах символов
кириллицы при условии соблюдения общепринятых правил:
должны состоять из букв цифр и знаков п од черкивания , не
должны начинаться с цифры , и т. д.

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

s. При внyrренней обработке кода страницы можно (в разумных


пределах) использовать весь арсенал библиотеки .NET Framework,
а не только специализированные Web-средства

Теперь осталось внести какое-либо видимое различие в оqюрмления


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

• ~ызовите на редактирование файл


App_ThemeslМyTheme l!ГhemeCSS .c ss и поменяйте в селекторе

body определение стиля qюна bac k ground, чтобы qюн

• ~ызовите на редактирование файл


App_ThemeslМyTheme2!ГhemeCSS .c ss и поменяйте в селекторе

body определение стиля qюна bac k ground, чтобы qюн

Наступил момент истины ...

• r;:;'исполните страницу и убедитесь в справедливости


сказанного. Должен получиться такой уменьше нный результат
в.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET
... и _ _ _ _
. ы"

~ ..._"*-"'--
".-- _ 'JO~"""""

I
Т.IIIIII rIOlЖII_ U IC С rpilIlМц.'*f!И t80itcnoo T r..m. оБW+nI
DOCU"-EN1'
эtlIDII'iI ~li!Кд;;t1 c:I I,юr~1I
'~"" Y"'OJI'<_"
\.t .. e~~n~ _
SI!'lI()о"'VМВNЗ" L"'("Ч:.~~~.~~.З;:
Hfll~ 1llilCТpCttr;м nG:.;I:J'.IC"I"':
~"'V\II1 ;/1~"
LIIIМW tI::ш&t '
3Ь1J DO "'VIИaN5" IЮ,U(IIDЧI!t+. fЮ TII~

1Ю,iI!1fl 1Мl EniIt4!t '~о '1'.mи·


r\I:t,I~ ... ~t'/IOЩnii SiIII'lID.!')X(" App _ThemeslМyThemel
"""'l""""" ........ "" ",t:!IIicт."",
1-

Арр_ ThemeslМyTheme

подобным образом программно можно мен ять и дрyrnе сти левые


свойства страницы и ее элемен то в, нап ример , и менованные
оф:Jрмления элементов уп р авления, определе нн ые атрибугом Skin ID .
Не обязательно давать пользователю возможность настройки стилевого
оф:Jрмления напрямую . Можно сд елать оф:Jрмление страниц и
элемен тов косвенно зав и с и мым от выбора п ользователя .
Принципиал ьной разницы с точки зрен ия кода здесь мало , главное - не
п ереусердствоват ь !

и последн ее .. . Все, что было сказано выше для д еЮJaративного спо с оба
п одключения тем и п риоритетов их пр именения , остается

справедливым и для ПрО2раММНО20 спо соба. Э то касается и страницы в


ц елом , и отд ельных элемен тов управления.

Вот и закончилась тема п ро ' 'темы '' !

Мастер-страницы

Оче нь часто требуется зафиксировать структуру стран ицы так, чтобы

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

одни и те же элементы управле ни я п ользовательского интерфейса


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

шаблонов.

Ша блон р азме ча ет именованные области визуализации на исполнимой


странице , в кото ры х будуг размещены либо при кре пл енные группы
элемен тов ст р аницы, либо содержимое именованной области самого
шаблона. Группы элемен тов уп р авления страницы, закре п ленные за
и менованными областями шаблона , называются содержимым (con tent) .
Страница , к которой п одключен шаблон, должна содержать гр уп пы ,
каждая из которых может ссылаться только на одну именованную

область шаблона. Если для какой-то именованной области ша блона


при крепле нн ой группы н ет, то на ст р анице п оявится содержимое
именованной области.

Именованные области шаблона , п одключ е нн ого к страни ц е, как бы


пр оец ируются на стр а н ицу и структурируют ссылающиеся на них

гр уппы содержимого страни цы и ли свое го собственного содержимого .


Ч асть шабло на , находящаяся вне именованных областей, может иметь
соде р жимое, которое на зывается заполнителем шаблона. Именованные
области шаблона и заполн и тель шаблона MOryг содержать любую
комби на цию HTML -кoda, серверных элементов управления или кода
пр о гр амм н ой подцержки (внугр ис тро чны й или в отдельном файле) -
все то, что используется на обычной ст р анице.

Перекомпоновка подключенного шаблона или его соде р жимого, а также


п одключе ни е к исполнимой странице нового шаблона на этапе
проектирования или п ро гр аммно п риводи т к немедленном у изменению

ее структуры и содержимо го шаблонной части.

Испол ни мая ст р ани ца получает от используемого шаблона его


компоновку, соде р жимое и за п олнитель. За полни тель ша блона
пр оец ируется на исполнимую стра н ицу полностью. Если на
и спол ни мой ст р анице есть хотя-бы одна группа , пр икре пл енная к
соответствующей именованной области шабло на , то именованная
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

област ь заполняется содержимым этой груп пы. Если такой груп п ы на


странице нет, то п роецируется содержимое самой именованной области
шаблона. Если прикреплен ная группа есть , но она п устая, то
именованная область н е про е цируется .

Мастер_
СТран ица Стр аНица
I I
(шабпон) замеща lOщеrо
ЛЮбые Э"еJ.1 е li rы
•.I11aster

N
.заГЮ'nн~ rеll~ Содержимого
*.aspx
CO,r:H:)PJoI.;~J.1 of!
~ I
лIoБые Зl1емеl-ltы
Сопtеп,з .заnОЛI-I"rе","
На Месте
СоntеПIРlасеНОICiегз

ОПЯТЬ "Юб~lе
1''
I
I
I
I
;СоntепtР lасеНоldегз
со I;fЮИм
(;QAep)!(l1"'bIM ~.,•••
,-

.'.

С О Пlепt 1
с за""ещаI()ЩL1М
CQДерЖlolмым

э"еменrы J. )- Опя ть лю6ы8 i ., СОПlеПIЗ


эаnОl1НИJеля

С~ержимое
1'.
I
I
I
эnемеНtы
эа П Ol1НИ Jеля

pontentP lal:eHolder1
(g ••
1- _
с 3QfllещаЮЩL1М
содержимы M

r
COt1tent, Н<I lYIес
CClrтtentp lac;eHold:~,
J.
1'.- I
I I
00 """"_
Содер)!(и",ым
r< ,•

I I
ContentP laceHolder2
Cc.6cr&eHlioe
iC{ (:aдep~lYIoe
Оntе ntp la CeHClICier2
.J. 1 со """"_
Coдep)!(l1"'bIM
'7' I
I I
I I
О nяrь
Опять

~ J rllQбbjе
!l lQБ Ые
ЭnемеНJЫ
~eMe flTbl
эа ПOf1 Ни'еля
заПо,n н и rе" я т I
I I
ВР<>М ..
~ЫnOJlJie.fUfst
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Шаблоны представляют собой обычные страницы, за ИСЮlюч е ни ем


нескольких отличий :

1. Шаблоны нельзя выполнить напрямую, они MOryг только


подцерживать ссылающиеся на ни х исполнимые ст р аницы

2. Файлы шаблонов и меют расширение .П1аstег, а файлы кода


подцержки для них на языке С# - .master.cs
з. В деЮlара ции дескрипторнorо представлен ия шаблона вместо
директивы @Page используется директива @Mas t er
4. Класс кода подцержки шаблона наследУет базовый класс
Sys t em . Web . UI . MasterPage , вместо базов02О масса
Sys t em . Web . UI . Page для обычной исполнимой страницы
s. Элемент управления Con t en t PlaceHolder используется для

резервирования именованных областей содержимого только в


ша бло нах. Если р аскрыть ВЮlадку Standard панели Toolbox при
редактировании обычной страницы, то мы этого элемента пр осто
не увидим , поскольку оболочка его скрывает до момен та

редактирования шаблона
б. Элементы Con t entPlaceHolder можно размещать в ячейках
таблицы. При выполнении ЭТИ ячейки за пол нятся

присоединенным содержимым, а остальные ячейки можно занять


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

Генерация заготовки мастер-страницы

Ша блон пр едставляет собой полноц е нную стран иц у, готовую к


выполнению , но не самостоятельно, а ч ерез исполнимую страницу

содержимого. Оболочка имеет мастер для создания заготовок шаблонов ,


как и обычных страниц. Для при мера, давайте создадим пр остую
эталонную шаблон-страницу и п устую (вначале) исполнимую страницу,
чтобы испытать шаблон .

• г;.:.='Добавьте к проекту командой Website/Add New Item шаблон с


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

именем F i rs tM as t erPage . тas t er с разделяемым кодом

.. .1J~
Terrp~tes: 111 "
е -~

1'100 Fe< m '••а• т


~
l'Iob Uo..-
Cm1rol
1!1
H T~P"9" 1'100
~
_Y O: ~
~
C~,
~
sty k> ShGot

~
с <ы

"оо
~
X~ Fi "
tm
XI~ Schema
li1
Text Fi "
!IJI
Resc....-ce Fi "
IJ
SQ.- Database
"W 'o:atL" Crnfg...-ati",

tm
DataSet -~, ~
Si l9~
шf-
~ i " Web
~
VВScr"t Fi "
,,_.
~ ~
JScr " t Fi"
~ff Fe< m

ri=\;" g' ,811 1,;; Ф .1 R1


IА f,'.:.stff ~ fc< Web /o.pp I O:~'~
Name : IF r-sМзste.-Рage ,'шste.-
L~: IVisual С, iJ 17 Росе [ ode n sEp<f"ate fi"
Г 58 ее! m.ster рзgе

Вот какой дескри n тор н ый код создал мастер

<%@ Master Language="C#" AutoEventWireup=''true''


CodeF ile=''FirstМaste rPage. ma s ter.c s''
Inherits= ''FirstMasterPage'' % >

<html xm1ns=''httр ://www.wЗ.огgl1999/xhtml'' >


<head nmat="server">
<title>Untitled Page</tide>
<lhead>
<body>
< fо пn id="forml" runat="server''>
<div>
<asp :contentplaceholder ю = "ContentPlace Holderl " runat="server''>
</asp:contentplaceholder>
</div>
</foпn>
<!body>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</html>

Листинг Дескрипторный код шаблона FirstMasterPaqe.master

Этот КОД почти такой-же, как и у за готовки обыч н ой исполнимой


стр а н ицы .aspx

• Г;;:;=Удалите дескриптор Co n t en t P la ceH o l der и через


контекстное меню редактора выполни те командУ Add Content Page
(добавить страницу содержимого)

.!! Cut

1: Сору

Paste
Paste Alteгnate

'х D€~te

V~W code

I[\QI AddCootent Page [

Synchroniz:e Document OutJine

Foгmat selec:tion
Fогmа1jjпg аnd VаliШtioп .. ,

Оболочка сгенерирует такую заготовку файла Defauh.aspx

<%@ Page Language="C#"


М asterP age F ile ="~ IF irstМ asterP age. master"
АutоЕvепtWirеuр= ' 'truе '' Code File="Default.aspx.cs"
Inher its='~Defa ult" ТItlе =' Тестовая страница содерж имого " %>
<%-- Add content controls here --%>

Листинг Заготовка страницы содержимого в файле

Default.aspx

Пустой файл , - только директива @P age страницы со ста н дартны ми


атри бугами страницы и атрибугом ПОДЮlючения шабло на .

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Обратите внима н ие , как можно вставлять комме н тарии <% -- ... --%>
в дескрипторный код файлов ASP.NET

Оболочка прописала значение атрибуга подключения


MasterPageFile с пугем отно с и тельн о корня Web-Аерева нашего

сай та Сн у, там наш шаблон и находится). Если уже ПОДЮlюче нн ый к


каким - то страницам шаблон п ереместить из корня в д ругую папку Web-
де рева , то оболочка не меняет автоматически пугь атрибуга
MasterPageFile во всех ссылающихся на шаблон страницах. это
придется делать вручную (ох и работы , можно запугаться!). Поэтому
нужн о за р анее с п ланировать, будем ли мы использовать ма стер­
страницы и где они будуг н аходи ться .

• ~Создайте в п ан ели Solution Explorer через кон текстное мен ю


для Web-кор н я подпапку MasterPages командой New Fok:ler
• r;:;nереместите мышью в п ап ку MasterPages шаблон
F ir stMas t e r Page . maste r

Теперь давайте откорректируем дескрипторный код исполнимой


страницы .

• ~ панели So lution Explorer дайте файлу Defauh.aspx новое и мя


F ir stMas t e r Page . asp x
• ~Откорректируйте дескри пторный КОД страницы

FirstMasterPage.aspx так

<%@ Page Language="C#"


М asterP а ge F Пе="~ IМ asterP ages/F irstМ asterPage. master"
Auto EventWireup=''true'' С ode F Пе= ''F irstМ aster Р а ge .aspx.cs"
Inherits=''FirstMasterPage'' ТItlе='Тестовая страница содерж имого "
<%-- Add content co ntrols here --% >

Листинг Скорректированный код страницы


FirstMasterPage.aspx
• ~Откройте файл FirstMasterPage.aspx.cs коман д ой View Code
контекстного меню стра н ицы и измени те имя De f ault класса
страницы на F ir stMas t e r Page

• r;.:.=назначьте страницу FirstМasterPage.aspx стартовой и


исполните ее , чтобы убедиться в отсугствии ошибок

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Появилась п устая страница с фоном , определенным темой по


умолчанию MyTheme , ВЮlюче нн ой нами ранее в конфuгурацuонный
файл Web.Config

< сопfigшаtioп>
<system.web>
<pages theme="MyTheme" />
</system. web>
</сопfigшаtioп>

Листинг Тема по умолчанию в конфигурационном файле

Web.Config

Никакого содержимо го п ока стра ниц а не им еет.

• Г;;:;-Добавьте в файл FirstMasterPage.aspx произвольный т екст,


например

<%@ Page Language="C#"


М asterP age F ile ="~ IМ asterP а ges/F irstМ aster Р age .master"
AutoEventWireup =''true'' CodeF ile="FirstMasterPage.aspx.cs"
Inherits=''FirstMasterPage'' ТilJе='Тестовая стр аница содержимого" %>

<%-- Add content controls here --%>


< h1 > Прив ет СТУдентам из "стра ницы содержимогоl"! < lhl >

Листинг Добавили СТРОХУ в страницу содержимого

FirstмasterPage.aspx

Если сейчас исполнить такую страницу, то мы получим ошибку времени


выполнения! Отсюда мо р аль:

Страница , использующая шабло н , может иметь любое содержимое


только в специальн ых контейнерах <asp : Con t en t >
</asp : Con t ent> .

• ~ оместите строку текста в контей н ер <asp : Con t ent> и


исполните страницу

<%@ Page L апguagе="С#"


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

м asterP age F ile ="~ IМ asterP а ges/F irstМ aster Р age .master"
AutoEventWireup =''true'' CodeF ile="FirstMasterPage.aspx.cs"
Inherits=''FirstMasterPage'' ТiI:!е= ' Тестовая стр аница содержимого " %>

<%-- Add content controls here --%>


<asp:Content>
< h1 > Прив ет СТУдентам из "страницы содержимогоl "!< lhl >
</asp:Content>

Ли стинг Поместили страху в хонтейнер на странице


FirstмasterPage.aspx

Опять ОlШfбка , опять мораль:

Каждый контейнер <asp : Соп ten t></ asp : Соп ten t> обязательно
до лжен ссылаться на свою имеНОВQННУЮ оБЛQсть в подключенном
шаблоне в соотношении "Один к одн ому". Только ч ерез прикрепленную
имеНОВQННУЮ оБЛQсть содержимое кон тейнера может по явиться на
стр анице и именно в том месте , где эту область зарезерв ирует шаблон .

• IJ$Откройте на редактирование файл


~ lМаstегРаgеslFirstМаs tегРаgе.mastег в режим е Design и пом е стите
на шаблон из вкладки Standard элемент уп р авления
Con t entPlaceHolder , эюемпляр которо го мы р анее удалили
• ~ ерейдите в режимSource на странице FirstMasterPage.master и
поместит е внугрь созданно го конт е йн е р а
Con ten tPlaceHolderl текстовую строку, чтобы
дес крипторный код стал таким

<%@ Master Language="C#" AutoEventWireup =' 'true ''


С ode F ile= "F irstMaster Р age. master.cs"
Inherits=''FirstMasterPage'' %>

<html xmIns= ' huр ://www.wЗ .or&,1999/xhtml" >


<head runat="server">
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nшat="sе rvег">
<div>
'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<asp:ContentP!aceHok:ler ID="ContentP!aceHok:ler1" runat= "server'


<h1 > Привет СТУдентам и з ' 'именованной области1 " мастер
</as р:С о ntentP !асе Н о Ider>
</div>
</fопn>
</body>
<lhtml>

Листинг Дескрипторный .од шаблона


FirstMasterPage.master
• ~ ерейдите в реж им Design и убедитесь, что именов а нн а я
область шабл она при обрел а свое собственное содержимое
j"MasterPagesjFir ",sterPage,master* ~

СontепtРlосеНoldег - ContentF'laceНolder 1

Привет студентам из
"именованной области1"
мастер-страницы!

Теперь нужно настр о ить страницу содержимого , испол ьзующую


шабло н .

• ~О ткрой те на реда ктирование в р ежиме Source страницу


содержимого FirstMasterPage.aspx, к которой п одключен шабло н , и
определ ите в контейн ере <asp : Content> атрибугы ID самого
де скриптора страницы и Con ten tPlaceHolderID
подключенного шабл она , н а которую БУдет ссылаться де скриптор
содержимого. Пользуйтесь услугами п одска з чика кода IntelliS ense,
который вызыв ается каждый раз при до бавлении пр обела внугри
де скриптора.

Иден т ификато р ID само го кон тей нера <asp : Соn ten t> в странице
содержимого определять н еобязательно , если только мы не п ла нир уем
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

управлять им пр о граммно. И зме н ен н ый код будет таким

<%@ Page L апguagе="С#"


М asterP age F ile ="~ IМ asterP а ges/F irstМ aster Р age .master"
AutoEventWireup =''true'' CodeFile="FirstMasterPage.aspx.cs"
Inherits=''FirstMasterPage'' Тil:Ie= ' Тестовая ст р аница содержимого " %>

<%-- Add content сопtrоls here --%>


<asp :Content ContentPlace HolderID= "ContentP laceHo ld erl " runat= "server">
< h1 > Прив ет СТУдентам из "страницы со.цержимогоl " ! < lhl >
</asp:Content>

Листинг Контейнер содержимого на странице

FirstмasterPage.aspx

• ~ с п ол ни те ст р аницу Firs tМ aste rPa ge. a s p x, долже н п олуч и ться


та кой р езул ьтат

....) Тестовая страница содержимого - Мicrоsоft Inter


File Edt V~w Н€lp

Привет студентам
из "страницы
содержимого1 "!
DоП€ Local iпtппеt

• ~ омест и те на ша бло н еще од и н ко нтей н ер ша блона


Co nten t P l a c e Hol der и на пол ни те е го та ки м кодом

<%@ Master Language="C#" AutoEventWireup =' 'true ''


С ode F ile= ''F irstMasterP age. master. cs"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Inherits=''FirstMasterPage'' % >

<html xmIns= ' huр ://www.wЗ .or&,1999/xhtml" >


<head runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id= "form1 " nmat= "server''>
<div>
<asp:ContentP!aceHok:ler ID="C ontentP!aceHok:ler1 " runat= "server'
<h1 > Привет СТУдентам из ' 'именованной области1 " мастер
</asp:ContentPlaceHolder>
< Ьг 1>
<asp:C о ntentP !асе Н о Иег ID= "С ontentP!a се Н о Иег 2" runа t= "server'
< h1 > Привет СТУдентам из ' 'именованной области2 " масте р
</asp:ContentPlace Holder>
</div>
</fonn>
<lbody>
<lhtml>

Листинг Дескрипторный .од шаблона


FirstмasterPage.master

• Г;:;=Перейдите на страницу содержимого FirstМasterPage . aspx в


режиме Design, которая станет такой
В.М. СН"""'
г.;;'~~~~~~~~;='В""",,,,,,,,,,,,,,~,,,,,~,,,,,,,,,,~п~,,,~,,="~="~-="=",~"="~"'='=.N~';iJ'
irstMasterPage,aspx MasterPagesjFr .. sterPag:>.master .... Х

Content - Contentl (custom)

ривет студентам из

"страницы содержимого 1 "!

ривет студентам из

'именованной области2"
Iмасп:~р-с~тр,аниц]ы!

Мы ВИДИМ, что мастер-страница задает схему размещения на итоговой


странице. Причем , еСЛИ на итоговой странице есть контейнер с
соде р жимым, при вязан ны й к именованной области шаблона, то на
место именованной области вставляется е го содержимое . Если
кон тейнер с содержимым есть, н о пустой , то нич его не вставляется. Но
еСЛИ контейнера с содержимым вообще н ет, то на и то говой странице
п оявляется содержимое именованной области.

Мы мажем рассматривать итоговую стра ниц у пользователя как


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

закре пленные за ни ми контейнеры нижн егО слоя.

Иными СЛОвами , им е нованная область шаблона спроецируется на


ито говую страницу ВСегда: либо с содержимым (в том числе п устым)

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

при крепленного к ней контейне р а, либо со своим содержимым (при его


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

Обратите внимание на заголовки именованных областей и и х фон. Там ,


где подставлено содержимое прикр е п ленно го контейне р а, фон светлее и
в скобках надпись (Custom) - заказной. Там, где пр оявилось содержимое
мастер-страницы, фон тем н ее и надпись (Master).

Давайте добав им кон тейнер содержимого к ни жней именованной


обла сти и напол ни м его .

• ~ a стра ниц е FirstMasterPage .aspx в режи ме Design вызови те


контекстное меню дл я нижней именованной области и
выполните командУ Create Custom Content

Оболочка добавит п устой конт е йн е р содержимо го и автоматически


свяжет е го в дес крипторном коде с именованной областью. Отсюда еще
одна мораль:

Если планируется создание одн ой и ли нескольких стра ниц на базе


мастер-страницы, то разработку лучше нач ать с Л1Qстер-страницы .
После того, как мастер-страница БУдет готов а , на ее базе можно
создать сколько угодно заготовок стра ниц с содержимым, выполняя в

кон тектном меню шаблона команду Add Co ntent Page. При этом , если
мастер-страница имеет файл отделе нного кода * .cs, то и страницы
соде р жимо го также БУдУГ создаваться с файлами отделенного кода.
в м С""",,,в

/ Ma5terPage5 /Fir ,. ,5t егР age ,ma5ter


Я~
Про,раммupoвtJNШ'

.
110 ASP.NET

х.

, ~
Conten1:PlaceКJlder - Content?lace/-blder 1 1:

,ji CUt
IПривет студенп ~ Сору

"именованной о ~ Paste
Paste Alternate
мастер-страниц) >< Delete

''''~
\/iew Code
View Component De ~gne r
conten1:PlaceКJlder Content?lace/-b1der2
II ~ Add CmtentPaJe I
IПривет студенп Edit Image

"именованной о
show Smart Tag

~ Refi"estJ
мастер-страниц) ~ Properties

После того, как на вновь созданной ст р анице с содержимым прояв ятся


именованные области шаблона, и х мож н о переопределить и за полни ть ,
создав командой контекстного меню Create Custom Content ко нтей н еры
индивидуал ьн о го содерж имого . Удали ть конте йн ер содержимого можно
командой Default to Master's Content.

Если именованные области ша блона пустые и их не переопределять


индивидуал ьны м содержимым ДЛЯ какой-то страницы, то на этапе
выполнения эта область н е БУдет видна .

Компоновка содержимого мастер- страницы

Приведем более содержательный пример разработки стра ниц с


использован ием шабло нов. Уч и тывая , что НТМL п одцерживает тол ько
п отоковую компоновку, прим е ним таблицу для фиксации содержимого .
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Нач н ем с создан ия мастер-страницы.

Создани е заготовки мастер-страницы

• ~ п а н ел иSolutio n Ехрюгег вызовите контекстное ме н ю для


п а пки MasterPages, которую мы создали ранее , и выполни те
командУ Add N ew Item
• ~ окне мастера создания за готовок выберите шабло н Master
Page и создай те эталонную стра ни цу с именем Т i tl е . mas ter
без файла отделенно го кода

-1J~
Terrp~tes : 111 "
е
_0_

1'100 Fe< m •
',ма т
~
l'Iob uoc>r
Cm1rol
~
H T~P"9"
~
1'100 SerVCG
~
C~C
~
sty k> ShGGt

&J
с <ы
iЭ •• 1m li1 JjJ 1]
"оо X~ File XI~ Schema Т ехl File Resc...-ce Fi le SQ.- Database
r.w 'c atL " Crnfg...-ati".

1m !i]
- , ~ ~. ~ ~ ~
DataSE't
~~
Si"~ ~ i le
1'100
Fe<m
VВScrjJt File
"-' JScr " t File

ri=\;" ~' ,811 1,;; Ф .1 R1


IА f,'.:.s!e< P<IgO fc< Web /o.pp l c~,~
Name : IТitle. master
L~: IVisual С, iJ Г Росе [ 000 n sEp<f"ate file
Г 58 ect mзster рзgе

Оболочка добав ит заготовку эталонной страницы в ка талог MasterPages,


где ей и место.

Создани е баннера

• ~ ереведи те в редакторе этало нную страницу Tttle.master в

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

режим Design и удалите пока автоматически созданный эюемпляр


элемента ContentP l aceHolde r (чтобы не пугался под
ногами)
• ~ режиме Design и з ВЮIaДКИ Standard пан ели Toolbox поместите
в самом нач але мастер-страницы эюемпляр элеме н та Image как

контейнер для размещения баннера. Присвойте ему и мя


ID= " I mageBanner "

Замечание. Элемент Iтage из ВКlIадки НТМL не будет


пр оявляться на странице содержимого , потому что не

обрабатывается сервером (если только ему не при сво ить атрибyr


runat= " server " )

• ~ызовите контекстное меню для папки MasterPages и


выполните команду Add Existing ltem. Найдите через открывшееся
диалоговое окно файл Banner.png, который находи тся в
прилагаемом к данной работе каталоге Рiсtшеs, и скопируйте его в
MasterPages текущего сайта
папку
• ~ыделите эюемпляр lmageBanner и при соедините к нему через
свойство I mageUrl рисунок Banner.png из папЮ1 MasterPages
Web-дерева саЙта. Наш баннер слишком великоват, но для
локально го компьютера сойдет и такой
• r;;:;'p азместите после баннера заголовочный дескриптор с
внyrренним стилем

<Ы style="color: Green''>


Мы приветст вуе м Ва с на нашем сай те!! !
</h1>

Листинг Заголовочный дескриптор

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

Элеме н т шаблона ContentPlaceHo l de r по умолчанию


растягивается по всей ширин е страницы. Чтобы позиционировать его
на Л1Qсmер-сmранuце, нужно при мени ть таблицу. Мы хотим создать с
помощью табли цы следующую структуру пользовательского интерфейса

'"
В.М. СН"",,,В

Пра BaR кол онка: контейнер


Ссылки ContentPlaceHolder2 с
навигации:
основным текстом и цветом
без фона Rчейки табли цы
контейнера (замеНRемое содержимое)
(noCToRHHoe
содержимое)

Нижни й кол о нтитул: контейнер


Соn tеntРl асеНоl dегЗ с цветом фона Rчейки
таблицы (замеНRемое сод ержимое)

в тр ех ячейках табл ицы БУдет размещаться поте нциал ьно заменяемое


содержимое мастер-страницы, поэтому там должны находится

контейнеры Conten t PlaceHolder . В разных ячейках табл ицы мы


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

Мы должны четко представ лять, что элемен ты управления


ContentP l aceHolde r и Content яв ляются про зрачными

контейнерами для свое го содержимого , если только мы искусстенно не


создадим в них фон другими элеме н там и , например, элементом Panel,
Iтage , Table . Поэ тому, если мы на странице содержимого не
создадим свой фон в замещающих элементах Content , то будет
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

проявляться В итоговой странице фш элемента-контейнера мастер­


страницы .

• r;:;n оместите на мастер-страницу FirstMasterPage.aspx после


заголовочного де скриптора и з вкладки НТМL панели Toolbox
элемент управления ТаЫе

• ~ спользуя боковые маркеры таблицы и команды меню Layout


оболочки, по стройте таблицу из трех строк и двух столбцов ,
чтобы она соответстворвала приведенному выше рисунку

Рекламация Большому Биллу: Мы конечно осознаем все

революционные возможности Visual Studio 2005 по разработке


программ. Но нас-то тоже нужно понять, мы привыкли к развитым
HTML -реаакmорам (ворованным), а в оболочке возможностей
редактирования таб ли ц маловато (хотя она тоже украдена, но мы же
учимся).

в конечном ви де таблица вм есте с вyrр енними стилями должна


описываться следующими HTML -Koaaм

<tab le border="O" width="100%">


<tr>
<td colspan="2''>
</td>
</tr>
<tr>
<td style=''width: 25%; ЬасkgrОШld-соloг: #9DFF7E" valign=''to p''>
</td>
<td stуlе='Ъасkgrоuпd-соloг: #FFB8FF">
</td>
</tr>
< и stуlе='ЪасkgrОШld -соlо г: #FFFF92">
<td colspan="2''>
</td>
</tr>
</tab)e>

Листинг Дескрипторный код таблицы

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Внешний вид таблицы БУдет таким

Теперь все готово для р азмещения элеме н тов управления в ячейках


созданной таблицы.

• ~ оместите из вкладки Starкlard п ан ели Toolbox в верхнюю


строку таблицы элемент управления Panel , к которому мы
п рисоединим рисунок, задающий фон ячейки . 1 D=Рапе 1 1 копии
этого элемента изменять не БУдем, п оскольку не план ируем в
дальнейшем им п ро грамм н о управлять
• r;;:FЗадайте для созданного эюемпляра элемента управления
Рапеl значения свойств: Wi dth= 1 00% ; He i ght=100% ,
чтобы элеме н т полно стью за н ял верхнюю ячейку таблицы
• ~ ерез проводник Windows найдите в прилагаемом к да нн ой
работе каталоге Pk:tures файл BackТItleSrc.jpg и в л юбом
графическом редакторе вырежьте из н его область с хорошо
стыкуемыми при повторении рисунка гра н ицами , или возьмите

м н ою вырезан н ый готовый рисунок BackТItle.jpg

Рисунок не д олжен быть слишкам большим, чтобы ' 'не застрял в


проводах" по пуги к п ользователю.

• ~ п а н ели Solution Ехрюгег в ко н текстном меню для папки


MasterPages выполните команду Add Еxistiпg I tещ найдите ваш
ри сун ок BackТItle.jpg и скопируйте е го в эту пап ку
• ~ыделите на странице эюемпляр Рапе11 в верхней строке
таблицы и через панель инструментов Properties при соедините в
свойстве Bac kl mageU r 1 этот рисунок, который многократным
повторени ем займет всю площадь элемента Рапе 11

Теперь можно р азместить в ячейках таблицы прозрачные кон тейнеры­


шаблоны элемен та управления СОП t en t P1aceHo1de r .

• ~ оместите из вклад ки S tarкlard п ан ели Toolbox в верхнюю


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

строку табл ицы в объе кт Panel1 элемент- контейнер


Con t entPlaceHolder , который БУдет представлять на
странице имеиовQИИую оБЛQсть Conten t PlaceHolder 1 дл я
р азме щения верхиего колонтитУЛQ

• Г;;:;=ТО же самое сделайте для прав ой_средн ей и нижней ячеек


та бли цы
• ~ контейнер Conten t PlaceHolder 1 встав ьт е и

отредактируйте такую строку

<div style="font-weight: bold; font-size: xx-large; color: red; text-align: се п


Сведения об ав тош}([)Ле в целом
</div>

• ~CTaBЬTe в правый кон тейнер ContentPlaceHolde r2


любой текст, напри мер, такой и л и е го ч асть

Вот уже более 12 лет мы занимаемся подготовкой водителей


категории "В" в г.Красноярске и все гда занимали первые места
в сводках МРЭО ГИБДД п о качеству обучения. Автошкола всегда
на успех наlШfХ клиентов в сдаче экзаме н ов ГАИ с первого раза
и своевременном получении води тельского удостоверения .

Мы обеспечиваем максимальные Удобства своим клиентам. Для


это го существуют вечерняя, воскресная и заочная ф:J р мы обучени
Наши курсан ты имеют возможность бесплатно инео граниченно
компьютерным классом. Учебные автомобили прибывают по зая
клиента к назначенному им месту. Развивается сеть филиалов ав т
в г.Красноярске .

Наша компьютерная экзаменационная про грамма успешно исш


в ГИБДД г.Крас н оярска, Железногорска, Назарово, Емельяново, U
для государственной аттестации кандидатов в водители. Мы н ео)
выпускали цветные учебно-методические по соб ия по Правилам )
движени я, которыми постоянно по льзуются большинство aBTOI.J.lli
города и края .

Лекц и онные занятия в автошколе ведуг квалифицированные п


с учеными степенями и званиями с применением современных КI

технологий. Комплексный подход к обучению и разнообразие ф:JI


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

позволяют максимально сократить ус илия наших юшентов и срш

усвоения ими учебного материала. Парк учебных автомоб и лей н ё


более 15 uпук, включая иномарки .

. ~
резервирующий
ни жний
место
конт е йн е р
под
ContentP l aceHolde r 3 ,
нижний колонтитул, вставьте
пр имер но такой код

<strong>
Автошкола Д иалог-Сервис в целом работает без перерыва
на обед и выходных с 8 часов уг р а до 9 часов вечера!!!
</strong>

• Г;:;=П оместите в левую ячейку таблицы надпись, а из вкладки


Standard п а нели Toolbox три 2иперссЬ/лки элемента yn р авле ния
Hype rLi nk

Дескрипторный код содержимого левой ячейки таблицы будет


примерно таким

<td style=''width: 25%; ЬасkgrО Шld -соlo г : #9DFF7E" valign="to p">


<strong style="colo r: Blue''> Наши филиалы:</stгопg> < Ьг />
< Ьг />
<aspHyperLink ID=''НурегLink1'' runat="server''> Ле нинский р айо н </аsр:
< Ь г />
<aspH yperLink ID=''НурегLink2'' runat= "server''> Це н тральный р айон< /а!
< Ь г />
<aspHyperLink ID=''НурегLinkЗ'' ruпаt="sеrvег' '> Свердловский раЙОН </ё
</td>

Сейчас мы пока н е определ яем в гип ерссылках элем енты адресации до


тех пор , пока не создадим несколько страниц содержимого ,

использующих эту Л1йстер-страницу . Мы еще верн емся к этим


гиперссЬ/лкам (мумия всегда возвращается!) .

Все , таблиц у мы за полнили. Попробуем разм естить е ще что - нибудь


ниже таблицы , наприм е р , товарный знак и ст р ашилку от воров
интеллектуал ьной собственности! Хотя, мы сами ее воруем у други х,
будуг воровать и у на с .
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• IJ$Отступите ниже таблицы одну-две строчки и добавьте из


вюыДки НТМL панели Toolbox элемент управления Image .
Щел кните на нем правой кнопкой мыши и выполните команду
RШl As Server ControL чтобы содержимое элемента проявилось в
БУдущем на странице содержимого
• ~ панели Solullon Ехрюгег вызовите контекстное меню дл я
папки MasterPages и скопируйте в проект командой Add Existing
Item из прилагаемого каталога Pictures рисунок LIGHTICO нашего
товарного знака, сворованный ранее из ресурсов Большого Билла
• ~ ерез панель Properties и свойство S r c (Sошсе - источник)
при соедините ссылку на файл LIGHTICO к нашему компоненту
отображения Imag e
• ~ paBee товарною знака разместите за явку на
интеллектуальную собственность

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

<р style=''text-align: right; союг: Blue; font-family: 'Co urier New'; font: ЬоИ italic'
< iшg ю='1МGl" runat="server" src="LI GHT.I CO" 1>
&nbsp;Copyright &сору 2007
</p>

• ~Для наглядности , поместите еще один контейнер в самом низу


Л1Qстер-страницы и внесите в него какой-ниБУдЬ последний писк,
например такой

<asp :ContentP laceHolder ID="ContentP laceHolder4" runat= "server''>


< stгопg><е m>Вы уж, пожалуйста, нав едыва й тесь к нам почаще ! < /еm>
</asp:C о nte ntP \а се Н о lder>

и по следний uприх к оqюрмлению мастер-страницы нужно

отцентрировать все ее содержимое.

• ~айдите вверху дескр ипторного кода самый внешний


дескриптор <d i v > и определите в нем внугренний стиль CSS
такой

<body>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

< fо пn id="form1 " runat="server''>


<div style=''text-align: center">

</div>
</foпn>
<!body>

Наступил момент и стины! Пора тиражир овать страницы содержимого


на базе созданной мастер -ст раницы и пров е рять сделанную р аботу
При это м не н ужно забывать , что страница н е должна быть сл ишко м
дли нной. Наилучше й счи тается дл ин а 1-2 экра на , максимум 3 экрана.
Шир и на непереносимого содержимого страницы должна быть около
770 пикселов, чтобы своб одно вписываться в ра зр е шение монитор а по
ширине от 640 до 1024 рх.

Создание страниц содержимого для мастер-страницы

Мы для наше го примера создадим 4 стра ницы соде ржимого с прос тыми
и менам и :

1. Sate l l it es . asp x - первая стра ница , главная, не БУдет им еть


свое содержимое, значит в ся мастер стра ница проявится на

выходе . Осталь ные тр и страницы будyr п ерео пр еделять все


шабло ны Л1йстер-страницы, кроме первого - колон титула
2. Sate l l it e 1. asp x - БУдет вызыв аться по первой ссылке в
р азделе ' 'Наши филиалы " и п ереопределять содержимое всех
контейнеров , кроме верхнего колонтитула
з. Sate l l it e2 . asp x - БУдет вызываться по второй ссылке в
р азделе ' 'Наши филиал ы "
4. Sаtе l l it еЗ . аsр х - будет вызываться по третьей ссылке в
р азделе ' 'Наши филиал ы "

Есть несколько способов со здания мастер-страниц с помощью


обол очки. Попробуем их.

Первый способ
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• ~ панели Solutio n Explorer выделите Ю)ре нь Web-дерева и


выполните Ю)манду ме н ю Website/Add New Item (или Ю)манду Add
New ltem Ю)н текстно го меню)

• u;.;rв появившем ся диалоговом окне отметьте показанные


настройки , ВЮlючая Select master page
---.1J~

T""l""»> ri! о:::


l/ШIiIIIII м.,,,
D
• .- Pogo
[!j]
_ с_

ccrn-o l
00
КТf.1.. Pogo
!i
W еЬS.п~е
~
Ck!"
lfiI
stj i< SCe" t

~
C~,

"«J I Ea~ .. ,
-
~
crn~gJ a ~I ",
~F,o,
)(]VL ХМ-
JfJJ
Schotm
~
То," Fil2
~
R о=л: о

;.
Fi:"
ij
SQ.-o..:..b=

1m
оазset -~, ~
5100 M~
I[!r"
M:N e I'Jeb
~
\1\5(r"" Не
~
,-,
~
JS'Ip ~ "е
l-Iord iof '.m
ОС::{' ~ -"'" ~ ",- ф1 jjJ
I д form for Wob {FP b"=n<

~W I Sdtel 'ite ,d5p(

L~: I Visuз l С' iJ '" Р!асе ссОэ n "1R~ fi le


'" Selea mзsOOf I""J"

• ~ следующем окне выберите мастер-страницу


elect iI Master Page -iЕJ
Рго;эсt bl:lers ' Сопtentз offolOO-'
a -~ С:\. .. \WООSiteб\ U F r-sl:МastE.-Рage, master
i!] c.' App_Trerr.as -jjЩМii€@l$l
liJ а ~щ-р~ ~

ос CaK,,1

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Созданная страница добавится в коре нь WеЬ · дерева и будет содержать


контейнеры с ПОДЮlюченным пустым содерж и мым для всех шаблонов
выбранной Л1Qстер·страницы .

Второй способ

• ~ пан ели Solutlon Explorer выделите н ужную мастер·страницу


и выполните командУ меню Website/Add Content Page (ил и команду
Add Content Page контекстно го меню)

Будет создана страница содержимого , размещен ная в то м же каталоге ,


что и выделенная мастер-страница, но добавленный атрибyr
МазtеrРаgеFilе будет прописан относительно корня Web-дерева ,
напри мер ,

Маз te rPageFi le= " - / Маз ter Раgез / т i t l е . таз ter " - (как-бы
абсолютный адрес в пределах сайта)

ЭТО значит, что мы можем переместить страницу содержимого в любую


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

Поэтому, перемещайте мастер-страницу по Web-дереву куда хотите, но


до тех пор, пока не начали создавать для н ее страницы содержимого .

Иначе п отом при дется долго искать ошибки.

Третий способ

• Г;:;=Откройте мастер-страницу на редактирование и щелкните на


ней в любом месте правой кнопкой мыши. Появится контекстное
меню с уже известной нам командой Add Content Page

Обратите внимание, что двумя последними способами страница


создается без отдельно го файла подцержки С# . Э ТО легко исправить ,
добавив к проекту файл .cs с пр едшествующим и менем стр аницы.

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Правда, оболочка при этом спросит, создавать ли для этого класса


отдельную папку со стандартным им енем Арр Code , на что нужно

ответить Нет. И еще , при таком способе добавления к странице фай ла


поддержки нужно вручную прописать необходимые атрибугы в
декларации @Page

AutoEventWireup =''true'' CodeFile="XXX.aspx.cs" Inherits=''YYY''

Вернемся к нашему примеру. Мы не собираемся программно управлять


нашими страницами при иллюстрации рассматриваемой темы мастер­
страниц. Н ам, главное , убедиться, что все , о чем мы так дол го болтали ,
работает! Поэтому, создадим страницы со встроенным кодом подцержки
(пустым, естественно).

• r;:;'щелкните правой кнопкой мыши на открытой мастер­


странице ~ lМasterPagesmtle.master в любом месте и командой Add
Content Page создайте страницу содержимого Default.aspx
• Г;:;=Переименуйте страницу Defauh.aspx в Satell i te . asp x и
п ерем ест ите ее в корневую папку Web-дерева
• Г;:;=Подобным же образом создайте и переместите в корень
остальные страницы содержимого: Sa te 1 1 i te 1. asp x,
Sate 1 1 i te2 . asp x, Sаtе 1 1 i tеЗ . аsр х . Но можно просто
ра ско пировать в корне в тре х эюемплярах файл Satellite. aspx,
учитывая, что все страницы БУдУГ ссылаться на одну и туже
Л1Qстер-страницу

Теперь давайте корректировать заготовки страниц содержимого. Но


прежде всего нужно доделать нашу мастер-страницу, определив

ссылки в левой ячейке таблицы на только что созданные страницы


содержимого.

• г;.:.=выполните команду Window/Close All Documents, чтобы


закрыть все редактируемые на текущий момент файлы
• ~ панели Solution Explorer щелкните правой кнопкой мыши на
файле ~ lМаstегРаgеs!Пtle.mastег и выполните командУ VIew
Dе sigпe г, чтобы открыть мастер-страницу сразу в режиме Design
• u;.;rп оочередно выделяя элементы гиперссылок, уста новите их
свойство Na v igateUr1 на соответствующие страницы
содержимого Satellite l.aspx, Satellite2.aspx, SаtеllitеЗ.аsрх. Сохраните

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

и закройте мастер-страницу TttIe.nыster

Отредактируем страницы содержимого, начнем с Satellite.aspx

• r;;:;=в панели Solution Explorer назначьте страницу Satellite.aspx


стартовой и откройте ее на редактирование в режиме Design

Что мы видим на данном этапе времени проектирования:

1. Мы видим просвечивающуюся сквозь страницу_содержимого


люстер-страницу (шаблон) . Прич ем заполн ители (элементы вне
контейнеров-шаблонов) мастер-страницы просвечиваются
тусюlO. Э то говорит О том, что их редактирование недоступно из
страницы содержимого, но они полностью отобразятся и будyr
доступны на этапе выполнения

2. Места, где на мастер-странице расположены контейнеры­


шаблоны , показаны ярко , но закрыты п устыми (пока)
контейнерами содержимого . Прич ем закрыто только содержимое
шаблонов Л1Qстер-страницы , а фон полность просвечивается.

• ~далите все контейнеры содержимого из страницы


Satellite.aspx, оставьте только строку с директивой @Page . Э та
страница у нас бу,цет стартовой и своего содержимого иметь не
будет
• r;;;rперейдите на странице Satellite.aspx в режим Design и мы
видим, что проявилось и содержимое шаблонов мастер­
страницы . ОНО и будет отображаться при выполнении во всех
местах, где нет своих прикреп ленных контейнеров на странице
содержимого

• ~ сполните страницу Satellite.aspx, п олучится ожидаемый


результат

'"
В.М. СН"",,,В Про,рйммupoвtJNШ' Na ASP.NET


dgJ1iJ
F* Еа: V~" F.... C<1t'" ТOOI3 Нф

" а;;;::- -;,. . . . ~ :1) с:! I 'Q Seadl !li FаУClIЖ '3 flOO.a () lb- :.i ~ :.::J ~ О
AO<:t'" I.:.J r-:ttp:/!осмh:J,;I:: 1 16 1rw<ЬSitt!St5~'",щ)х

---- ---------- --- --- ---- --- --- -----


.--r-. e-mail:dialog-service@list.ru

Мы приветствуем Вас на нашем


сайте!!!

Паши филиа.лы: Вот уже более 12 лет мы зшшмасмся подготовкой водшслей


ь,<tтеroрШ1 "В" в r , KpacHoКPCKe и всегдаЗШШМaJШ первые места
ЛеНI1НСКИЙ ЩUIЩJ в сводках л,rPЭО ГНБДЦ по качсству оБУЧСIШЯ . Автошкола
всегда нацелена на у спех наших юшенroв в с даче экзаменов

liеmpальНblЙ р аЛон Г АН с первого рuзa н своевремеюlOМ JIOJJучеш1Jt ВОДlпельскorО


удостовереюlЯ .

Св ердловскнй район
~1ы ОООCJШЧII8!ШМ .\ltlкcJIАншыlеe удобсТВII CBOIIM ICЛНClпам
ЛпО' '\1У'1Н' I"rтп",.,......vmт ""и""иО'" "('>...-.rtV'{''П''''- 'П ~ ""llП"" т""....-.., ~
Г гг ~ LОС~ ПI,.,ne{

• ~ ощелкайте по ссылкам и обратите внимание, как меняется


адрес в броузере (ссылки работают). На адресуемых страни ца х мы
пока не уб р али и не изменили контейнеры содержимого , поэтому
там на месте контейнеров шаблона ничего не будет (пустое
содержимое контейнеров место при исполнении не занимает).
Ум на я технология Большого Билла!

Теперь нужно наполнить страницы ссылок индивидуальным

содержимым.

Приведем окончательный вариант дескрипторного кода для всех

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

стра н и ц да нн ого примера

Мастер-стр а н ица ТItle.master

Обрат и те в ни мание, что все кон тейнер ыConten t PlaceHolder


долж н ы н аходи ться внуг р и дескри п тор а <form></ f o rm > !

<%@ Master Language="C#" %>

<html xmlns=''httр ://www.wЗ.огgl 19 99/xhtml''>


<head nmat= "server">
<title>Untitled Page</title>
<lhead >
<body>
<form id=' 'forml '' nmat:::::"selVer">
<div style= ''text-align: center''>
<asp:Image ID='1mageBarmer" runat= "server" ImagеUгl="~ lМаstегРаgе slВап
< Ы style="color: Green''>
Мы приветствуем Вас на нашем сайте!!!
<lhl >
< Ьг 1>
<table border= "O" width="100%">
<tr>
<td colspan= ''2''>
<asp:Panel ID=''Panell '' nmat= "server" Height= "100%" Width= "100%" Васl
<asp:ContentPlaceHolder ID=''ContentPlaceHold erl '' runat="server">
<div style=''font-weight: bold; fo nt-size: xx-large; союг: red; text-align: cent(
Сведения об автошколе в целом
</div>
</asp :ContentP IaceHolder>
</asp:Panel>
</td >
</tr>
<tr>
<td style=''width: 25%; background-color: #9DFF7E" valign=''top ''>
<strong s tуle="союг: Вluе "> НаlШ1 филиалы:</s trопg>< Ьг 1>
< Ьг 1>
<asp:HyperLink ID='HyperLinkl " nmat="selVer" NavigateUrl="~/Satellitel.
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

< Ьг 1>
< аsр:НурегLiпk ID= ' 'Н урегLiпk2" runat="selVer" N avigate Url= "~/Sa tellite2.
< Ьг 1>
< аsр:НурегLiпk ID= ' 'Н урегLiпkЗ" runat= "selVer" N avigate Url= "~/Sа tеllitеЗ.
</td >
<td stylе='ЪасkgrОШ1d-соlог: #FFB8FF">
<asp:C ontentP lace Н о k:lег ID= "С о ntentP la се Н о lder2" runa t= "server">
Вот уже более 12 лет мы занимаемся подготовкой водителей катего
и всегда занимали первые места в сводках МР ЭО ГИБДД по качест
всегда нацелена на успех наших клиентов в сдаче эюаменов ГАИ с
получении водител ьского удостоверения.

< Ьг 1>
< Ьг 1>
Мы обеспечиваем максимальные удобства своим юшентам. ДЛЯ 3TI
воскресная и заочная формы обучения. Наши курсанты имеют возм
неограниченно пользоваться компьютерным классом. Учебные авт
заявке юшента к назначенному им месту Развивается сеть филиало
</asp:ContentPlaceHolder>
</td >
</tr>
< и stуlе='ЪасkgrОШ1d-соlог: #FFFF92">
<td colspan="2">
<asp:ContentPlaceHok:ler ID="Со пtепtРlaсеНоldегЗ" runat="server">
<s trопg> Автошкола Диалог-Сервис в целом работает без перерыва
на обед и выходных с 8 ча с ов угра до 9 часов вечера!!!
</strong>
</asp:ContentPlaceHolder>
</td >
</tr>
</table >
< р sty1e=''text-align: right; color: Blue; font-family: 'Сошiег New'; font: bold ital
< iшg ю =' 1МGl " runat="selVer" src= "LIGHT.I CO " 1>
&ampnbsp;Copyright © 2007< /p>
<asp:C ontentPlaceHolder ID="C ontentPlaceHold er4" runat="server">
<strong><em>BbI уж, пожалуйста, наведывайтесь к нам почаще! </е m>
</asp :ContentP IaceHolder>
</div>
</form>
<!body>
,ОС
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</html>

Листинг Файл Title.master

За пускающая страница содержимого Satellite.aspx

Все контейнеры <asp : Сап ten t> уничтожены, поэтому страница


используется только как за п уска ющая и не добавляет к мастер­
странице своего содержимого.

<%@ Page L апguagе="С#" MasterPageFile="~ lМasterPagesmde.master" 1ide:

Листинг Файл Satellite.aspx

Стра ница содержимого Satellitel.aspx

Стра ница имеет все контейнеры пер ео пределяющего содержимого ,


поэтому от Л1Qсmер-сmранuцы проявляются только заполнители.

<%@ Page L апguagе="С#" MasterPageFile="~ lМasterPagesmde.master" 1ide:

< аsр:Сопtепt ID ="Со пtепtl " ContentPlaceHok:lerID="ContentPlaceHok:lerl " ru


<div stуle=''foпt-wеight: bold; font-size: xx-large; союr: red; text-align: сепtеr'~
Сведения о филиале в Ленинском районе
</div>
</asp:Content>

<asp :Со пtепt ID ="Со пtепt2 " Co ntentPlaceHok:lerID= "ContentPlaceHok:ler2" RI


Филиал в Ленинском районе такой хороший ! < Ьr 1>
.... .... .... .... ..... .... .<br />
и т. д.

</asp:Content>

<asp :Со пtепt ID ="Со пtепtЗ " ContentPlaceHok:lerID= "Сопtе пtРlaс еНоk:lеrЗ" RI
< strопg>Филиал в Ленинском районе работает без перерыва на обед
часов угра до 9 часов вечера!!!
</strо пg>
</asp:Content>

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<asp :Content ID="Content4 " ContentPlaceHok:lerID= "Co ntentPlaceHok:ler4" RI


<strong><em>BbI уж, пожалуйста, нав едыв ай тесь к на м почаще в фил
</asp:Content>

Листинг Файл Satellitel.aspx

Страница содержимого Satellite2.aspx

Страница имеет в се кон тейнеры переопредел яющего содержимого ,


п оэтому от Л1Qсmер-сmранuцы проявляются только заполни тели.

<%@ Page Language="C#" Ма stе гРа gеFile="~lМаstегРа gеsmdе . ma s tег" 1ide:

<asp :Content ID="Contentl " runat= "Server" Co ntentPlaceHolderID="Co ntentPI


<div sty1e=''font-weight: bold; font-size: xx- large; СОIoГ: red; text-align: center'~
Сведе ния о филиале в Цен траль ном районе
</div>
</asp:Content>

<asp :Content ID="Content2 " runat= "Server" Co ntentPlaceHolderID="ContentPI


Филиал в Центральном районе такой хороший!<Ьг />
.......................... < Ьг />
и т. д.

</asp:Content>

<asp :Content ID ="Со пtепtЗ " runat= "Server" Co ntentPlaceHolderID="Co ntentPI


<strong>
Филиал в Центральном районе р абота ет с перерывом на обед и с I
</strong>
</asp:Content>

<asp :Content ID="Content4 " runat= "Server" Co ntentPlaceHolderID="ContentPI


<strong><em>BbI уж, пожалуйста, нав едывайтесь к на м почаще в фил
</strong>
</asp:Content>

Листинг Файл Satellite2.aspx

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Страница содержимого Satellite3.aspx

Третий контейнер страницы содержимого oTcyrcTByeT, поэтому на его


месте пр о явится содержимое третьего шаблона мастер-страницы.
Четвертый контейнер содержимого существует, но п усто й , поэтому на
его месте ничего не пр ояви тся.

<%@ Page L апguagе="С#" MasterPageFile="~ lМasterPagesmde.master" 1ide:

<asp :Со пtепt ID ="Со пtепtl " ruпаt= "Server" Со пtепtРlaсе Н о ld ег ID="Со пtепtР I
<div stу1е=''foпt-wеight: bold; font-size: xx-large; СОloг: red; text-align: сепtег' ~
Сведения о филиале в Свердловком р айоне
</div>
</asp:Content>

<asp :Со пtепt ID ="Со пtепt2 "


runat= "Server" Со пtепtРlaсе Н о ld е гID="Со пtепtР I
Филиал в Све рдловском районе такой хороlШlЙ! < ЬГ 1>
.......................... <br />
и т. д.

</asp:Content>

<asp :Со пtепt ID ="Со пtепt4 " runat= "Server" Со пtепtРlaсе Н о ld ег ID="Со пtепtР I
</asp:Content>

Листинг Файл SаtеllitеЗ.аsрх

Программное управление мастер-страницей из

страницы содержимого

в странице содержимого мы можем менять только содержимое


контейнеров <азр : Content> , а содержимое за полнителей мастер­
страницы и ее заголовок являются недоступными на этапе

проектирования. Но иногда, не тр о гая спроектированную мастер­


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

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

1. Вначале ASP.NET создает элементы управления мастер­


страницы , а потом дочерние элементы на странице содержимого

2. Затем ге н е рируется событиеPage . In i t Л1Qстер-страницы ,


вслед за которым возбуждается событие Page . In i t страницы
содержимого

З. Затем срабатывает событие Page . Load Л1Qстер-страницы , а за


ним то же событие страницы содержимого

Такой порядок означает, что если мы программно меняем одни и те же


на стройки в мастер-странице и в странице содержимого , то
послед ними останугся изменения , выполненные в коде страницы

содержимого.

Управление заголовком

Мастер-страница имеет заголовок <head> ... </ head> обычной


страницы , где можно задавать все составляющие его дескрипторы и это
появится на результирующей странице. Но иногда на странице
содержимого нужно определить свои дескрипторы заголовка.
ДеЮlаративно (на эта пе проектирования) в странице содержимого
можно переоперелить только дескриптор < t i tl е> , добавив в
директиву @Page атрибугTi tle= " . .. " страницы содержимого. В
этом случае дескриптор <head> мастер-страницы должен
обязательно быть серверным (что и делает по умолчанию мастер
заготовок оболочки).

Программно можно п е реопределять не только дескриптор < t i t 1 е> ,


но и другие дескрипторы за головка. И опять, дескриптор < h еа d>
мастер-страницы должен обязательно быть серверным. Для
программного управления элементами заголовка <head> мастер­

страницы из текущей страницы содержимого нужно в странице


содержимого получить ссылку на объект Page Л1Qстер-страницы. ЭТО
делается через свойство Page . Maste r объекта текущей страницы
содержимого, у которого, в свою очередь, свойство Master . Page и
определяет ссылку на объект Page мастер-страницы.

Ниж е приведены равноценные коды получения ссылки на объект Page


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

мастер-страницы из страницы содержимого

Page masterPage = base.Master.Pa ge;


Page masterPage = this.Master.Page;
Page masterPage = Master.Page;

Ключевые слова Ьазе или th i s не являются обязательными. Они


напоминают, что Ма s t еr является свойством объекта текущей
страницы.

Декларшивное переопределение <title>

• ~Создайте копию страницы Satellite.aspx, назначьте ей имя


Sa te 1 1 i teE x t . азр х и сделайте стартовой

Попробуем на странице SatelliteExt.aspx переопредели ть


дескриптор <t i t le> мастер-страницы. Текущий код страницы
такой

<%@ Page Language="C#" МаstегРаgеFilе="~ lМаstегРаgеsrПt1е.mastе]


Trtle='Untitled Page" % >

Листинг. Файл SatelliteExt.aspx


• ~3амените атрибyr Ti tle директивы @Page на следующий

<%@ Page Language="C#" МаstегРаgеFilе="~ lМаstегРаgеsrПt1е.mastе]


Тrtlе="ДеЮJaративный заголовок SatelliteExt.aspx" % >

Листинг. Файл SatelliteExt.aspx


• ~ сполните страницу - результат будет таким

Программное переопределение <title>

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Поскольку мы н е создавали для страницы Sate lliteExt.aspx отдельный


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

• ~ ереведите страни цу SatelliteExt.aspx в режим Design и


щелкните дважды на притушенной области пр остynающего
заполнителя Л1Qсmер-сmранuцы

Оболочка ав томатически создаст блок скрипта и вставит в него


заготовку обработчика события Page . Load.

• ~3аполните обработчик так

<%@ Page Language="C#" МаstегРаgеFilе= "~ lМаstегРаgе srПt1е.mastе]


Тttlе= "ДеЮJaративный заголовок SatelliteExt.aspx" % >

<s cгipt гunat= "seгveг''>

pгotected void Page_Load(object sепdег, ЕvепtAгgs е)


{
// Получаем ссылку на мастер-страницу
Page masteгPage = Ma steг.Page;

// Переопределяем строку заголовка


masteгPage.Headeг.Тitle := ''Прогр амм ный заголовок SatelliteExt.,
}
</sc гipt>

Листинг Файл SatelliteExt.aspx после добавления


обработчика Page_Load()
• ~ сполните страницу - результат будет таким
11 Программный заголовок SatelllteExt.aspx - Мiсrоsоft Jnternet Explorer ~25J
FIe Ecit View Fav<Xites Tc:ds ~ ;
... ВасК .......... ~ ш ~ I ~ seэ:сh [±j Favorites ~ мeda G I ~ . . €t ~ ~ "7 D
Aroess 111 http :J;'о::atю~t: 1161/WеЬэtе6/Satе.tеЕхt.iЩ)Х :::::J 8'rл

Несмотря на то, что мы оставили декларат ивный атрибуг T i tle,


обработчик пер ео пр еделил е го в окончательном выводе. Э ТО и понятно:
декларативный атрибуг инициируется при создании объекта за головка ,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

а обработ ч ик Page Load () срабатывает п озднее.

Управление друг ими элементами мастер-страницы

Рассмотрим управле ни е элемен тами за п ол ни теля мастер-страницы и з


стра н и ц ы содержимо го н а примере дескриптора <hl> , о п ределе нн ого
в за п ол ни теле так

<Ы style="color: Green''>


Мы приветствуем Вас на нашем сайте!!!
</h1>

Листинг Дескриптор h1 мастер - страницы

-/МаstеrРаqеs/Тitlе.mаstеr

Его отображе ни е в броуэере БУдет следую щи м

Мы приветствуем Вас на нашем сайте!!!

• r;:;='До п олните дескриптор <hl> мастер-стр а ницы

т i t l е . mas ter необходимыми для про гр амм н ого уп р авления


атр ибугам и

<Ы style="color: Green" runat="server" id="Header1 ''>


Мы приветствуем Вас на нашем сайте!!!
</h1>

Листинг Атрибуты дескриптора <Ы> в файле Title.master

Уп равлять будем из стра ниц ы Sate lliteExt.aspx одним из двух способов :

1. Ин ка п сули р уем (упакуем) в м а стер-странице де скриптор <h 1 > в


отдельн ое свойство с и ме н ем MyHeader l и из стра ниц ы
содерж и мого БУдем обращаться к нему через это свойство
2. Не тро гая код мастер-страницы , н айдем из стра ниц ы
содерж и мого дескриптор <h l > п о его ID и будем обращаться к
н ему н ап рямую
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Первый способ

• IJ$Двойным щелчком н а свободном месте мастер-страницы в


режиме Dеsigп (или вручную) создайте блок скриптов, который
заполни те так

<%@ Master Language="C#" %>

<script runat= "server''>

protected void Page_Load(object sender, EventArgs е)


{

риыic s triпg MyHeaderl


{
get { return Headerl.lnnerText; }
set { Headerl.InnerText == value ; }
}
</script>

<html XmInS= ' huр ://www. wЗ.or&,1999/xhtml' '>


<head runat= "server''>
<tide >М асте р - страница 1ide.master</tide >
<lhead>
<body>
<form id ="forml " nшat= "sе rvег ''>
<div style=''text- align: center">
<asp:lmage ID ="lma gеВаппе г" nшat= "sе rvег" I mageUrl="~ lМast
<hl style="color: Green" ruпаt= "sеrvег" id= 'Headerl ''>
Мы п рив етс твуем Вас на нашем сай т е! ! !
<lhl >

</div>
</fопn>
</body>
<lhtml>

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET
Листинг До бавление свойства доступа ~ дес~риптору

<h1> в файле Title.master


• ~До п олни те стр аницу соде р жи мого SatelliteExt.aspx следУЮЩИМ
КОДОМ

<%@ Page Language="C#" МаstегРаgеFilе="~ lМаstе гР аgеsrПt1е.mastе]


Тttlе="ДеЮJарати вный заголовок SatelliteExt.aspx" %>

<%@ MasterType Vll1uaIPath= "~lМas terPagesffttle.master" %>

<script runat= "server''>

protected void Page_Load(object sender, EventArgs е)


{
// Получаем ссылку на мастер-страницу
Page masterPage = Master.Page;

// Переопределяем строку заголовка


masterPage.Header.Тitle := ''Программный заголовок SatelliteExt.,

// Управляем дес криптором h1


Master.MyHeaderl = ''Э то программно подмененный "
+ "заголовок мастер-стр аницы (способ 1)!";
)
</script>

Листинг Дополненный код страницы содержимого


SatelliteExt.aspx
• г;.:.=и с п олните страни цу SatelliteExt.aspx и убеди тесь, ч то
де скриптор <hl> , относящийся к заполн и телю ма стер­
стра н ицы , п одмен яется н ашим текстом

Это программно подмененный заголовок мастер-страницы (способ 1)!

Циректива @ Mas te rType указывает ASP.NET в и ртуальный п угь к


соответствующему файлу мастер-страницы.

Второй сп особ
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• ~ зме ните стр аницу содержимого SatelliteExt.aspx следУЮЩИМ


образом

<%@ Page Language="C#" МаstегРаgеFilе="~ lМаstегРаgеsrПt1е.mastе]


Тrtlе = "ДеЮJараТИВНblЙ заголовок SatelliteExt.aspx" %>

<%@ MasterType Vll1uaIPath="~ lМasterPagesrгrtle.master" %>

<script runat= "server''>

protected void Page_Load(object sender, EventArgs е)


{
// Получаем ССblЛКУ на мастер-страницу
Page masterPage :::: Master.Page;

// Переопределяем строку заголовка


masterPage.Header.Тitle = "ПрограММНblЙ заголовок SatelliteExt.,

// Управляем дескрип тором hl


// Master.MyHeaderl = ' Зто прогр аммно подменеННblЙ"
// + "за голово к mactep-ст р аНИЦbl (с по соб 1)!";

HtmlGenericControl h1 = Master.FindContro~ ' Headerl') as HtmlGE


~ (h1 != null)
{
hl.lnnerText :::: 'Зто программно подменеННblЙ"
+ "заголовок mactep-страНИЦbl (способ 2)!";
)
}
</script>

Листинг Измененный ход страницы содержимого


SatelliteExt.aspx
Метод FindCon t rol () ищет указаННblЙ элемен т на масmер­
ст ранице среди э лементов зада нного типа , и если находит, то

возвр ащает странице содерж и мо го ССblЛКУ на этот элемент. За тем


уже Мь! обращаемся к конкретны м свойствам эт ого элемента.
• ~ с полните стр аницу SatelliteExt.aspx и убеди тес ь, что
дескриптор <hl> , отн осящийся к заполнителю масmер-
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

страницы , подмен яется наши м текстом

Это про г ра ммн о подмененный за гол ово к м ас тер -стра ниц ы ( с п ос об 2) !

Второй способ более предпочтительный , поскольку мы н е вмешива емс я


в код спроектирова нной мастер-страницы, которая может бы ть
под ключе на еще к чему- ниБУд Ь !

Программное пер еключе ние мастер-страниц из

страницы содержимого

Иногда может во з никнугь необход имость дать возможность


пользователю п одключать необходимые Л1Qстер-страницы . Мы уже
рассматрив ал и подобный способ, ко гда гов о р или о д инамическом
под ключе нии те м. Там мы пр о граммно о пр еделяли з нач е ни е атрибуга
Page . Theme в директиве @Page . Теперь н ам нужно пр о граммно
менять ат ри буг Page . Mas ter PageF i le .

Здесь н ужно иметь вви ду следую щее:

1. Стр аница содержимого, динамичесЮ1 меняющая мастер­


страницу, н е до лжна и меть ссылок на н ес уще ствующие в н овой
Л1Qстер-странице контейнеры СОП t entP laceHo l der 1 О
2. Замена Л1Qстер-страницы должна выполняться в обраб отчике
события Page . Pre 1 n i t страницы соде р жи мого. Есл и эт о
сделать в обработчика х более по зд ни х событий , то будет
с генерировано исключ е ни е

З. Все страни цы соде р жимо го, на которые и меются ссылЮ1 в


те куще й странице содерж имого , должны иметь код подключения
выбранной мастер-страницы
4. Для межстранич но й п е редачи информации о выбранной мастер­
странице ее нужно где- то сохран ять. Ка к и в случае с темами, эт о
MOryr бы ть скрытые поля состо яния вида ( VIEWSTA TE ),
глобал ьны е объекты уровня сеанса или п риложения

Уч итывая , что н а ши стра ницы Satellite.aspx, Satellite1.aspx, Satellite2 .aspx,


SаtеllitеЗ.аsрх со гл асованы с Td:1e.master, сделаем и х копи и и настроим
п од динами ч ескую смен у мастер-страниц.

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• IJ$Откройте Л1Qсmер-сmраницу 1ide.Irnster и добавьте выше


объекта ImageBanner (после открывающего дескриптора
<div> ) элемент Con t entP1aceHo1der с им ен ем
Con t entP1aceHo1derL i s t . Сохран ите и закройте фай л
1ide.Irnster
• ~Сделайте копии соответствующих файлов и присвойте им
имена Tit 1 e1 . maste r , Sate1 1 iteDynamic . asp x,
Sa te 1 1 i teDynam i c1 . а sp x , Sa t e11 i t eDynamic2 . asp x,
Sаtе 1 1 i tеDупаm i сЗ . аsр х

• ~Определите страницу SatelliteDynamic.aspx ста ртов ой


• г;.:.=ОткроЙте мастер-страницу 1idel .master и выполните в ней
следУЮщее:

о Полностью Удали те контейнер скриптов <sc ri pt


runa t = " se r ver " > .. . </scri pt>
о Удали т е объект Image Banne r и внесите еще каЮ1е-нибудь
визуально отличимые изм е н е ния

о Добавьте к 2иперссылкам Hype r L i n k еще одну с


названием" Автош к ола в ц ело м "

о За полнит е свойство Nav i gateUr1 гиперссылок

значениями новых страниц содержимого

• г;;;?Откройте страницу содержимого SatelliteDynamic.aspx и в


режиме Design создайте контейнер содержимого для шаблона
Con t entP1aceHo1derL i s t , выполнив на нем КOMaHAyCreate
Custom Content контекстного меню
• ~Добавьте в контейнер содержимого предваряющи й текст
" Выбер и те мас т ер - страни ц у :" и элемент

DropDownL i st с именем 1stMas t e r Pages


• ~Заполните раскрывающийся список 1s t MasterPages так
Text Value
Мастер-страница с
I t e ms[ O] ~ lМasterPagesmde.master
баннером

Мастер-страница без
Ite ms[ l ] ~ lМasterPagesmdel.master
баннера

• ~становите для списка 1stMas t e r Pages свойство


Au t oPos t Bac k =" T r ue "
. ~ режиме Design двойным щелчком на тускrю

просвечив ающемся заполн ителе мастер-страницы создайте


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

контейнер для скрип тов , обработч ик Page Load () и


п ереименуйте е го в Page 1 nl t ()
• ~Скопируйте за готовку об р аботчика Page Inlt () и
п е реименуйте копию в Р age Рr e 1n 1 t ( ) , поскол ьку в се они
имеют одинаковую сигнатуру

• ~ р еж и ме Dеsigп двойн ым щелчком на объекте


lstMasterPages списка создайте обработчик изменения
выбора опции
lstMaste r Pages Se l ectedlnde x Changed()
• ~3ап ол ни те обработчики так, чтобы окончательный код
страницы б ыл таким

<%@ Page Language="C#" МаstегРаgеFilе="~ lМаstегРаgеsrП!:1е.mas!:е]

<script runat= "server''>

pro!:ec!:ed void Page_Init(objec!: sender, EventArgs е)


{
if (Session["index"] != null)
{
// Восстанавливаем новое состояние списка
Is!:Mas!:erPages.Selec!:edIndex = (in!:)Session["index"];
)
}

pro!:ec!:ed void Page_PreInit:(object sender, EventArgs е)


{
if (Session["Mas!:er"] != null)
{
// Был ранее сохраненный выбор , включить его
Page.Mas!:erPageFile:= (s!:ring)Session["Mas!:er'1;
)
}

pro!:ec!:ed void IstМas!:erPages_Se1ectedIndexChanged(objec!: sender, 1


{
// Запоминаем новый выбор пользователя
Session["Mas!:er"] := IstМas!:erPages.Selec!:edVaJue;
// Запоминаем новое состояние списка
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Session["index"] = lstМasterPages.Selectedlndex;

II Обновляем страницу без полного ци кла,


II ч тобы новая мастер-страница вступила в действ и е
S erver. Transfer(Req uest. F ile Р ath);
}
</script>

<asp:Content ID="C ontent1 " runat="server" Co ntentPlaceHok:lerID="Col


Выберите мастер-страницу:
<asp:DropDownList ID="lstМasterPages " runat="server"
О nS е lected IndexC hanged = ''1stMaster Р ages _ S е lected IndexC hang
AutoPostВack='True">
<asp :ListI tem Value ="~ IМ asterP а ge sfГn:1e .master''> М а стер - стр ан и
</asp:Listltem>
<asp :ListI tem Value ="~ IМ asterP а ge sfГn:1e 1. master''> М а стер- стран
</asp:Listltem>
</asp:DropDownList>
</asp:Content>

Листинг Окончательный код страницы


SatelliteDynamic.aspx
• IJ$Откройте поочередно файлы SatelliteDynamic1.aspx,
SatelliteDynamic2.aspx, SаtеllitеDynаmiсЗ.аsрх и добавьте в каждый из
ни х после директивы @Page такой блок скр ип тов

<script runat= "server''>

protected void Page_Prelnit(object sender, EventArgs е)


{
if (Session["Master"] 1= null)
{
/1 Был ранее сохраненный выбор , включить его
Page.MasterPageFile = (string)Sessio n['Master'1;
)
}
</script>

Листинг Скрипты остальных страниц содержимого для


загрузки выбранной мастер - страницы
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• ~ сполните начальн ую стра ни цу SatelliteDynamic.aspx и


убедитесь, что мы дали п ользователю п ол н офункцио н альный
механизм выбора Л1Qстер-страниц

Мн огослойное подключени е мастер-страниц

Принципиально возможн о п одключение одной мастер-страницы к


другой - ASP.NET это позволяет. Можно испол ь зовать столько уровней
вложения мастер-страниц , сколько это необходимо. Но нужно иметь
ввиду, что м н огокаска,цная схема п одключения мастер-страниц делает

код за п уганным и ненадежным, п оэтому рекомендуется использовать

только один уровень мастер-страниц . К тому же, режим Design


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

Мicrosoft Vlsual Studio

De3igl vie!! does mt sц::рс:п creatr.;) or edtn;j nested master рзges . То create or edt neste::J master рзges , u:e
Sot.rce \IiEw.

J
Но мы , все-таки, рассмотрим эту возможность н а п римере мастер­
страниц двух уров н ей. Мы создадим две мастер-страницы с
п оследовательным п одключением н ижне го уровня Levell к верхнему

LevelO .

• ~Создайте в кор н е Web-Аерева мастер-страницу нижнего


уровня с именем Маз te r PageLevel l . mas ter

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

.1J~
T""l""»> ri! о:::

llijJ
I'J.b Form •
'4мъt4
_ с_ [!j]
ccrn-o l
00
КТf.1.. Pogo
!i
W еЬS.п~е
~
Ck!"
lfiI
stj i< SCe" t

~
C~,

"«J I Ea~ ",


-
~
crn~gJ a ~I ",
~F,o,
)(]VL ХМ-
JfJJ
Schotm
~
То," Fil2
~
R о=л: о Fi:"

;.
ij
SQ.-o..:..b=

1m
оазset -~, ~
5100 M~
I[!r"
M:N e I'J eb
~
\1\5(r"" Н е
~
,-,
~
JS'Ip~ "е
l-Iord iof '"m

~
ОС::{'
-"'" ~
I д м",,/о< Р'9' fcr lМ>b Af~ l t,too<
",- ф1 jjJ

~w I Мd'MP~""" l l , ",,,'M
L~ : I V isuз l С' iJ Г Р!асе с сОэ n "1R~ fi le
Г ... юm't?rr""J"

• ~oд страницы сделайте таким

<%@ Master Language="C#" % >

<html XmInS= ' huр ://www.wЗ .or&,1999/xhtml">


<head runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form ю= "foгml " nmat= "server''>
<div style=''text-align: center; color: #OOOOff" >
<hl >
Мастер - страница уровня Levell - наибольшей глубины.
Ее можно использовать как верхний колонтитул
<lhl >
<asp:ContentPlaceHokler ID="C ontentPlaceHok:lerLevell" runat=
<Ias р:С о ntentP Ia се Н о Ider>
</div>
</fOmI>
<lbody>
<lhtml>
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Листинг Дескрипторный код страницы


MasterPageLevell.master
• ~ Тепер ь создай те мастер-страницу верхне го уровня с именем
Mas t e r PageLevelO . maste r и подключи те к ней
пр едыдщую через атр ибут Mas t e r PageF il e директивы
@Master

Код страницы должен выглядеть так

<%@ Master Language="C#" MasterPageFile="~ lМasterPageLevell.master" ~

< asp :С о ntent ID= "С о ntentLeve lO" С ontentP Ia се Н о ld erID= "С о ntentP Lзсе Но ld еl
<table width="100%" s tуlе ='Ъас kgrоuпd -соloг: #ссfЮО" border="l ">
<tr>
<td colspan="2">
<h2>
Мастер-страница уровня Leve lO - верхнего уровня
<1h2>
</td>
</tr>
<tr>
<td style=''width: 200рх''>
<strong>3Aecb мож но р асполож и т ь элеме н ты навигации </s trопg:::
</td>
<td stуlе='Ъ асk grоuпd -со loг : #ccffff'>
<asp :ContentP LзсеНоldег ID="ContentP IaceHolderLevelO" runat="sel
</asp :Conte ntP Lз се Н о lder>
</td>
</tr>
</table>
</asp:Content>

Листинг Дескрипторный код страницы MasterPageLevelO.master

• ~ыпол н ите для ст р ани цы Ма stегРаgеLеvеЮ.mastег команду


Website/Add Content Page , чтобы создать для нее ст р аницу
содержимого

• ~ змените имя п о умолчанию Default . asp x созда нн ой


ст р аницы соде р жимо го на TestMas t e r PageLevel . asp x и
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

отр еда ктируй те ее так

<%@ Page Language="C#" Ма stегРа gеFilе ="~ lМа stе гР аgе L е vеЮ . ma stЕ

<asp:Content ID= "C ontentl " ContentP IaceHold erID=''C ontentPlaceHoldl


<stгопg> Это е ст ь заменяюще е содержимое дл я mact e p - с траНИЦl
</asp:Content>

Ли с тинг Де с крипт о рный ко д страницы

Te s tмa st erPageLevel . a spx

• ~ а зн ачьте стра н иц у содержи мо го TestMasterP age Leve Laspх


старт овой и ис п олни те ее

Р езул ьтат БУдет таки м

-!i Untitled Page - MI<Tosoft Internet Explorer


Мастер-страница уровня
Level1 - наибольшей глубины.
Ее можно использовать как
~

верхнии колонтитул

I мастер-стрamща уровня LevelO -


верхнего уровня

Это есть заменяющее содержимое для


мастер-страницы BepXHero уровня
LevelO

ГГГ~ Lоса h trooet

И так, вс е работа ет, н о н а м это не н адо - сл ишко м зап угано и п о см отреть

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

в Design нельзя!

Подключение мастер-страницы через

конфигурационный файл

Для страниц, которые не имеют подключения мастер-страницы


посред ством атрибуга Maste r Pa g eF il e , можно задать ма стер­
страницу по умолчанию в кофигурационном файле блоком

< сопfigша tioп>


<system. web>
<pages masterPageF ile="XXX.master" />
</system. web>
</со пfigшаtio п>

Этот подход не считается надежным, поскольку требует строгого


согласования всех страниц сод ержимого с шаблонами од ной ма стер­
страницы. Как только это условие БУдет нарушено , появится
исключение. Если необходимо применить именно этот вариант, то
нужно создать отдельную папку со своим файлом web.config и
поместить в нее мастер-страницу и согласованные страницы

содержимого

Наши перспективы

Ну вот и приплыли, граждане студенты. До сих пор я писал изложение ,


а вы его читали. Теперь вы БУдете писать сочинение , а я его буду
смотреть в апестационную и зачетную недели! Отсюда вам мой наказ
(читай "Указ! ' '):

1. На занятия можете не ходить - это ваше личное дело, но знать


данный материал вы обязаны (если я Оl.Ш1баюсь - спросите у
декана). Э то уже вопрос государственной безопасности! (чтобы
перед Болы.ш1M Биллом не краснеть)
2. С очинение БУдете писать на вольную тему в виде
взаимосвязанных активных страниц на ASP.NET 2.0
3. С егодня (беру слепок сверху) 19.03.2009 11:51 и материала для вас
уже изложено достаточно , чтобы пристynить к работе
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

4. Ни один не получит зачет (я не боюсь директор магазин ,


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

7. Все, что я знаю и умею по этому средству, должны знать и уметь


вы. А то какое-то неравенство и стыд получается!
8. Пора и власть употребить
9. Как говорил наш шеф, куй железо не отходя от кассы
10. Как гласит народная МУдрость, время - де ньги ; не расчитывай на
деньrn , если нет времени!

-
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Управление состоянием ASP.NET


Ynравление состоянием на клие н те. Состояние вида. Восстановление
состояния вида элемента списка через коллекцию запроса. Защита
инфо рмации в состоянии вида . Скрытые поля. Строки запроса .
Межстраничн ая об р атная отсылка данных . Сооkiе-наборы. Проверка
п оддержки cookies ЮlИентом. Сохранение данны х в состоянии сеанса .
Сохра н ение данных в состоянии приложения. Хранение данных в
статических переменных при ложен ия.

Файлы к лекции Вы можете скачать здесь скачать:

httр :l/оkl . iпtШ . ruld ераrtmeпtliпtеmеtlр rasp netl 10/1о.пр

Главная особен н ость Удаленных приложений состо ит в том, ЧТО они


MOryг одновременно обрабатывать множество пользователей. К тому
же сервер может выполнять одновременно н есколько разных

при ложений. Поэтому среда исполнения устроена так, что после


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

Такой факт вынуждает разработчиков Web-приложений изыскивать


другие способы хранения информации о состоян ии между запросами, с
п оследУЮЩИМ ее извлече ни ем и использованием. В ASP.NET
существует два способа хранения информации между запросами: на
клиенте и на сервере. Разработчик сайта сам решает, какую группу
методов хранения данных состояния ему выбрать.

Хранение информации на клиенте имеет следующие преимущества:

• Лучшая масuпабируемость - не расходуется память сервера для


хранения состояния, что позволяет обслужить больше клиентов
• Подцержка множества Web-серверов - обработку поступающих
запросов можн о распараллелить междУ несколькими серверами .

При этом код при ложен ия модифицировать н е нужно, п оскольку


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

вся необходимая инфор мац и я о состоян ии постynает вм е сте с


каждым запросом

Хранение июlюрмации на сервере имеет следующие пр еимущества:

• Безо п асн ость защищенность да нны х состояния ОТ

злоумышленников. Информация yn р авления состоянием на

клиен те может быть похищена с клие н тско го компьютера и ли


п е рехвачена в п уги. А хр анение на сервере конфиденциальных
да нных, таких как п ароль, урове нь достynа, состояние

авторизации делают это безопас ны м


• С нижение н а гр узки н а каналы связи - с ни жение времени загрузки
ст р аницы и увеличе ни е масштабируемости, особе нн о дл я
моб ильн ых кrlИе нтов

Управление состоя нием на клиенте

Управление состоянием пуг ем хранения данных на кли е нте удоб но с


точки зре ни я эконом ии памяти сервера, но требует до п ол н ительных
р есурсо в канала связи , п оскольку данн ые курсируют между клие н том и

сервером п ри каждом за п росе и отклике. К тому же их тру,цно защи тить


от зло нам еренного п ользователя.

Различают следующие методы хранения данных н а клиен те:

1. Состояние ви да ( v i ew state ) - используется для сохр анения


значений элемен тов ynравл е ния , доба вл е нны х конечным
пользователем. Применени е состоян ия вида ос новано на
свойстве Vi ewS t ate ти па System . Web . UI . S t a t e Bag ,
наследУемом от класса Cont r o l люб ы м элемен то м ynравления и
самой стран иц ей.
2. Скр ытые поля ( h i dden fi e l ds ) - сохранение данных в
скрытых полях НТМL-вывода. Они также хра н ят информацию об
одной стран иц е, но в отличие от состояния ви да скрытые поля не
подце р живают хэширован и е, шифрование , сжатие и хра н е ни е п о
ча стя м. При испол ь зован ии скрыты х п олей данные формы на
се рв ер долж ны отправл яться методом POST (по щелчку кнопки
Submit), а не методом GET (по щелчку на 2иперссылке) .
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

з. Строки запроса ( query strings ) - сохранеl-ше данных в URL.


Видимы для пользователя в пол е адреса
4. Межстраничные обратные отсылки - присланные вызывающей
страницей данные остаются в памяти сервера на момент работы
страницы-приемника

s. Куки-наборы ( cook i e -файлы ) - созданные на сервере данные


записываются на компьютер ЮIИен та в небольших файлах (в
количестве до 20 фай лов и до 4 Кб кажд ый) и автоматически
п е ресылаются броузером на сервер вместе с каждым за про сом .
Э то лучший способ хр а нения состояния , доступного многим
страницам при ложен ия

Ра ссмотри м последовател ьно п ере чи сле нные методы хр анения

состояния на ЮIИенте.

Состояние вида

ЭТО про стой способ хранения информации на клиен те между


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

При пос туплен ии обратной отсылки на сервер в память загружается


ад рес уемая страница в своем п ервозда нном виде ,

инициницализ ируются ее ин терфейс ны е элементы начальн ы ми

настройками, затем извлекается пос тупившая в скрытых полях


инфо рма ция о состоянии на момент предыдуще го ОТЮIИка и свойств а
элементов корректируются. После этого срабатывают события
элементов управления о по след них действиях пользователя и состояние
элементов управл е ния еще р аз корректируются. ТаЮ1М образом ,
состояние интерфейсных элементов при создании страницы
п ереза писыва ется по меньше й мере тр и раза: п ерво начальными
на стройками , п оследними сохранными значениями и новыми
знач ениями , инициированными пользователем.
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Все серверные WеЬ · элементы ynравления используют состояние вида


по умолчанию (не обязательно вмючать
EnableViewState= "t rue " ). В состав каждого из них входит
своЙство·коллекция Vi ewState , наследуемое от масса
System . Web . UI . Con t rol . Это же свойство напрямую наследует и
масс Page , который мы расширяем при проектировании активной

страницы. ОНО создается и за полняется постynИВIlD1МИ данн ыми вместе


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

После обработки страницы ее текущее состояние , а также состояние


элементов ynравления, автоматически хзшируется (hash . шифруется ,
превращается в мусор; не пyrайте с кэшем· сохранением в памяти) и
строка с хзшем пересылается броузеру в скрытом поле страницы вместе
с отображаемым НТМL. Если да нные получаются очень объемные и не
помещаются в одном поле , то ASP.NET автоматически дели т их на
части и за писывает в нескольких скрытых полях. Максимальный объем
одного скрытого поля определяется свойством
ma x PageStateF i eldLength масса Page (по умолчанию равен ·1
). Для изменения начальных настроек объекта страницы значение этого
свойства нужно поместить в конфигурацuонный файл, например

<?xml vеrsЮ п="1 .0" encoding=''utf-B'? >


< со пfigшаtioп xmlns= ''http ://schemas.microso ft. coml. N etC о пfigша tio nlv 2 .0">
<system.web>
< сошр ilatiо п debug= ''true'' />
<pages maxPageStateFieldLength="1024" />
</sys tеш. wеЬ >
</сопfigшаtioп>

Коллекция Vi ewState построена по типу словаря (ассоциативного


массива) , в котором значения адресуются строковыми уникальными
КIIючами. Элеме нтами коллекции являются ссылки на объекты
обобщенного типа Obj ect , поэтому она способна хранить объекты
любого типа. При извлечении из коллекции состояния вида данные
нужно при водить к соответствующему тип у. Если в коде попытаться
извлечь значение , которого нет в коллекции , БУдет выдано исмючение
Nul l ReferenceE x cept i on , поэтом у необходима предварительная

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

пров е р ка возвращаемой ссыл ки на nu l l -з нач ен и е.

Не все типы объектов MOryr бы ть сохранены в состоян ии вида.


Прос тые типы сохраняются безусловно, а более слож н ые типы долж ны
п оддаватьс я серuалuэа циu ( пр еобразовыватьс я в поток ба й тов). Если
объявлению класса предшествует атр и буг [Serializable) , то
порожде нный эт им классом объект мож но сохранять в состоянии вида.
В противном случае, при попытке сохранить такой объект в состоянии
вида AS P.NET выдаст ошибку выполнения. Библиотечный тип
Hashtable из простр анства и ме нSyste m. Collect i ons также
пр едставляет собой словарь с полями Кеу и Va l ue . Он подцается
сериали3Qцuи, по этому н астр ое нный объект тако го типа мож н о целиком
сохранять и восстанавливать в Vi ewSta te .

в качестве иллюстрации сказанного приведем 2 при м ера, где


испол ьзуется програ мм ир ова ние словаря Vi ewS ta te самой страницы.

Упражн ение 1

в этом при мере мы создадим qюрму С интерфейс ными элеме нта ми, в
которых отключим ав томатич еское сохранение состояния вида, а БУдем
его сохранять и восстанавливать вручную. Интерфе йсны е элеме н ты мы
разместим в серверной табл иц е и БУдем использовать р екурс ивн ую
логику для опроса всех ее до черни х элементов, размещенных в

коллекции Controls . В качестве Юlюча для доступа к элементам


словаря V i ewState уровня страницы будем исп ользовать
и де н ти фикатор ы элеме н то в .

• Г;:;=Создайте пустой проект с и менем ViewStateTest


командой FilelNewlWeb SitelEmpty Web Site

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

.1J~
T...-rpl ..,... Гf! ;:;:

~ ~ ~ ~
АЧ' r.ET \',00 ASP J-ET W3!J ж-sma l Vloo ЕrrщWeIJ
S ib SOfYEO S i'" stoc"" K~ S i.,

[:'-0"'''' .. ,

• г;;.:;='Добавьте к проекту н овую Web-стр аницу с им ен ем

Viewst a teTes t . азр х и н азначьте ее стартовой


.1J ~
T<><rpla>?> ri! ;:;:

~ D [!j]
_ с_ 00 !i ~
VI<b Form м", ,..- Р"9" КТf.1.. " "9" Web S• .., ~e С",,,
ccrn-o l

CiiJ
C~,

"«J 1 ~a~ ",


-
[}
crn~l;JJ a ~I .. ,
~
)(]VL F,",
\JjJ
Х М- Schotm То "
~
Fil2
~
R о=л: .

.
Fi:"
ij
SQ.- о..:..ь=

1m
Dазset -~, ~
5Ite М"!)
1J]r"с

M: N e VIOO
~
\'В5C r "" F(e
lf.jJ
,-,
~
J5CfjX ""
I-I.rde.. ' ..m

rв::;" ~ -"'" ~ ф1 jjJ


Iд form for Wob ц"ь""",
~W
L~:
~1I Vislя
'~.~~"~5~;&~!@ij!:===::;---:~=~:-:-===:----==]
l С, ::=J ~ ссОэ S€pЗIае PliO:e n fii3
Г Selea rrвstef IВ'J"

• ~3апустите командой
Website/ASP.NET Со пfigшаtioп страницу
WAT (Web Site Administratian Тай/) и выполните команду Application
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

СопfigшаtionlСоnfigше debugging апd tracing. На появившейся


странице ВЮIючите фrJaЖОК ЕnаЫе debugg i ng

Таким действием мы создадим файл конфигурации Web .config с


настройкой отладки.

• r;:;'в панели So lution ЕХРloгег щелкните на кнопке Refresh, чтобы


увидеть файл конфигурации в составе проекта
• IJ$Откройте интерфейсную часть страницы ViewStateTest.aspx в
режиме Sошсе и добавьте в открывающую часть дескриптора
<di v> внугренний стиль

<div s tуlе=' 'tехt- аligп: се пtег ' '>

и за головок

<h1 style="color: Rе d ' '> З ап олн и те aHKeTy<lhl >

• Г;;:;=Откройте интерфейсную часть страницы ViewStateTest.aspx в


режиме Dеsigп и поместите на нее элемен т ТаЫе из вкrыдки

НТМL панели Toolbox


• ~елкните на элементе ТаЫе правой кнопкой мыши и
выполните опцию Run As Se rv er Cont r o l. чтобы
превр атить его в серверный
• ~Откорректируйте интерфейсный HTML-кoa заготовЮ1 таблицы
следующим образом

<table ю =' ТаЫе l " width="100%" runat="server" s tуlе=''tехt- аligп: left; wi(
<tr>
<td style=''width: 2 00р х' '>
</td >
<td >
</td >
</tr>
<tr>
<td style=''width: 2 00р х' '>
</td >
<td >
</td >
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</tr>
<tr>
<td sty1e=''width: 2 00р х' '>
</td >
<td >
</td >
</tr>
<tr>
<td style=''width: 2 00р х' '>
</td >
<td >
</td >
</tr>
<tr>
<td sty1e=''width: 2 00р х' '>
</td >
<td >
</td >
</tr>
<tr>
<td style=''width: 2 00р х' '>
</td >
<td >
</td >
</tr>
</table>

Листинг

Созданная таблица имеет б строк и 2 столбца.

• ~ оместите в первую строку и первый столбец таблицы


приведенн ый ниже текст, а в остальные ячейки второго столбца -
элемент Te xt Bo x из ВЮJaДКИ Starкlard панели Toolbox
• r;:;n оместите после таблицы три кнопки Button из ВЮJaДКИ
Standard панели Toolbox и присвойте им имена cmdSubmi t ,
cmdSave и c mdRestore соответственно

После этих действий интерфейс страницы в режиме проектирования

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

будет та ки м

ViewStateTest,aspx

Заполните анкету
.~

~aHMeHOKaHHe ~ ;значенне
~МЯ: Ir

iПароль: Ir
IE Отправить IE Сохранить • Восстановить

Ему с оответствует тако й дескр ип тор н ый код

<%@ Page L апguagе="С#" АutоЕvепtWirеuр=' 'truе''


CodeFile='ViewS tateTest.aspx.cs" I пhе rits='ViewS tаtеТеs t " % >

<html xmlns="httр ://www.wЗ.оrgl 1 999/xhtml" >


<head nmat="server">
< title>Uпtitled Page</tide>
<lhead>
<body>
< fо пn kl="fо пn l" ruпаt="sеrvеr' '>
<div stуle=''tехt-аligп: сепtеr">
< Ы style="color: Rеd">3 а полн и те aH KeTy<lhl>
<table id='TabIel " runat="server" stylе="tехt-а ligп: le ft; width: SOOpx;">
<tr>
<td style="wklth: 200 р х''>
< Ь > Наи мено в ание < !Ь> < /td>
<td>
< Ь > З н аче ни е<!Ь > < /td>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

</tr>
<tr>
<td style=''width: 200рх''>
Имя: </td >
<td >
<asp :TextBox ID='TextBoxl" ruпаt= "server''></asp TextBox></td:
</tr>
<tr>
<td style=''width: 200рх''>
Учетный HOMep:</td >
<td >
<asp TextBox ID='TextBox2" ruпаt= "server''></asp TextBox></td:
</tr>
<tr>
<td style=''width: 200рх''>
Возраст:</td >
<td >
<asp :TextBox ID='ТехtВохЗ" ruпаt= "server''></asp TextBox></td:
</tr>
<tr>
<td style=''width: 200рх''>
E-mail:</td >
<td >
<asp :TextBox ID='TextBox4" ruпаt= "server''></asp :TextBox></td:
</tr>
<tr>
<td style=''width: 200рх''>
Пароль:</td >
<td >
<asp :TextBox ID='TextBox5" ruпаt= "server''></asp :TextBox></td:
</tr>
</table>
< Ьг 1>
<aspButton ID="cmdS ubmit" runat="server" Теxt::::: "От пр авит ь " 1>
&пЬsр;&пЬsр;&пЬsр; &nbsp;
<aspButton ID="cmdSave" nmat="server" Техt="Сохранить" 1>
&пЬsр;&пЬsр;&пЬsр; &nbsp;
< аsр:Вuttоп ID="cmdRestore" runat="server" Теxt=''Восстановить'' 1>
</div>

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</form>
<!body>
</html>

Ли с тинг Код интерфе йс н ой части стра ницы Vi ewS t a teTe s t. asp x

• г;.:.='ДвоЙным щел чком на каждой из двух п оследни х кнопок


cmd Save и cmdRestore в и н те рфейсн о й част и с траницы с о зда йте
дл я ни х заго товки о б ра б от чиков с им е на м и по умолчанию
• Г;:;=О ткрой те фай л отделенного кода и запол ните его сл едУЮ ЩИ М
КОДОМ

using System;
using System.Data;
using Sуstеm.Сопfigurаtiоп;
using Sуstеm.Соllесtiопs;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using Sуstеm.WеЬ.U I .WеЬСопtrоls;
using Sуstеm.WеЬ.U I .WеЬСопtrоls.WеЬРаrts;
using Sуstеm.WеЬ.U I .НtmlСопtгоls;

риыic рапia! class ViewStateTest : System Web . UI.Page


(
private Ьоо l executeFlag = true;

protected void cmdSave_Click(object sепdег, ЕvепtAгgs е)


(
11 Сохраняем присланные значен и я текстовых полей
SaveAllТext(TabIe 1.Сопtrоls, executeFlag);
}

private уою SаvеАllТехt(СопtгоlСоllесtiоп сопtrоls, Ьооl saveNested)


{
if (!saveN ested)
геturп;

11 Перебираем все дочерние элементы в переданной коллеКЦ I


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

foreach (Сопио! сопио! in controls)


{
// Выбираем элементы текстовы х пол ей и сохраняем
// и х содержимое в свойстве ViewState объе кта страницы ,
// и с п ользуя в качестве Юlюча идентификатор элемента
if (control is TextBox)
{
t:his.VIewState[controLID] = «ТехtВох)сопtrоl).Теxt;
)

// Н а ве рхних уровнях объекта ТаЫеl до черни м и элемента r


// являются строки и ячейки табл ицы , поэтому продолжае~
// рекурсивно спускаться ниже , пока не встретим объекты'
// Флаг saveN ested разрешает проверять вложе нные уровни
if (controLControls != null)
(
SaveAllТext( controLControls, saveN ested);
}
}
}

protected void cmdRestore_C lick(object sender, EventArgs е)


(
// Извлекаем пришедший с обратной отсы лкой сохраненный
// обрат ной отсылки и вставляем е го в текстов ы е поля, готов
RestoreAllТext(Tablel.Controls, executeFlag);
}

void RestoreAllТext(ControlCollection controls, Ьоо ! restoreN ested)


{
if (!restoreNested)
геtшп;

// Пер ебираем все элеме н т ы табл ицы , ВЮJючая вложенные, ч


// использовать и х идентификаторы как ЮlЮЧИ для и звле ч е н и
// возмож н о сохраненных з н аче ний из словаря VIewS tate
foreach (Сопио! сопио! in controls)
{
// Н а lШlИ текстовое поле

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

if (control is TextBox)
{
// Убеждаемся , что есть в словаре
if (t:his.VIewState[controLID] != null)
{
// Приводим типы и восстанавливаем
((TextВox)control). Text = (striпg)this. ViewS tate[ controLID];
)
}

// Рекурсивно спускаемся ниже к до черни м элементам


if (controLControls != null)
{
Resto reAIrГext( со пио LС о пио 15, resto ге Nested);
}
}
}
}

Листинг. Содержимое файла ViewStateTest.aspx.cs


• ~ спытайте работу страницы и убедитесь, что в любое время
можно восстановить состояние элементов управления ,

сохраненное ранее в словаре V i ewSta te страницы

Упражнение 2

Этот прим ер подобен пред ыдущем у; но в нем з начения текстовых полей


прежде поэлементно сохраняются в промежуго чном объекте
Hashtable , а затем этот объект ц ел иком сохраняется в свойстве
объекта страницы V i ewSta te . Интерфейсная часть ст раницы остается
в точности такой -же, как в предыдущем примере , а кодовая часть
изменится. При этом, чтобы не менять интерфейсную часть, мы
ди намически (в кодовой части) добавим в конце коллекции формы
f or ml текстовую метку для отображения на клиен те содержимого
промежугочного объекта-словаря.

• ~ ерез панель Solutlon Explorer создайте копию страницы


ViewStateTest.aspx и присвойте е й имя ViewStateObject5.aspx
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• ~ змените имя масса Vi ewStateTest на


Vi ewStateObjects в ю:щовой и интерфейсной частях
ско пир ованной ст р аницы
• г;;;?Заnолните кодовую часть следующим образом

using System;
using System.Data;
using Systеm.Со пfigша tiоп;
using System.Collections;
using System. Web;
using System. Web.Security;
using System.Web.UI;
using System. Web.UI. WebControls;
using System.Web.UI. WebControls.WebParts;
using System. Web.UI.HtmlControls;

public partial class ViewS tateO bjects : System Web.UI.Page


(
private Ьооl executeFlag:= true;

11 Создаем экземпл яр nром ежугоч ного словаря


Н аshtaЫе dictionary:= new HashtableO;

protected void спк:lSаvе_Сliсk(оЬjесt sender, EventArgs е)


(
11 Сохра ня ем nри сл анны е значения текстовых полей в словаре
SaveAlJГext(Table 1.Co ntrols, executeFlag);

11 С охраня ем пом ече нный словарь ц ел иком в состоянии ви да


this.VJewState["contentsState"] := dictionaгy;
}

private void SaveAlJГext( ControlCo llec tion controls, Ьооl saveNested)


{
if (! saveNested)
геtшп;

11 П е ребир аем все дочерние э лементы в п е реданной колле кции та е


fo reach (Control control in co ntrols)
'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

(
11 Выбираем элементы только текстовых полей и сохраняем
11 их содержимое в промежугочном объекте , используя
11 в качестве Юlюча идентификатор элемента
if (сопио! is TextВox)
(
11 3начения полей перед сохранением на всякий случай
11 URL- ко.цируем как поступившие от ненадежного источника
11 (предохраняемся от возможного ввода зловредных СКРИПТОЕ
11 Чтобы система не реагировала на угловые скобки в полях вв
11 нужно в директиву @ Page интерфейсной части вставить ат]
11 ValidateRequest="false" или в секцию
11 <pages validateRequest="false"> файла web.config
11 Внимание!!! ХМL~файл web.config чувствителен к регистру (
string text = «TextВox)control).Text;
text = Раgе.Sеrveг.нtmlEпсоdе(tеxt);

11 То же самое ...
11 text = НttрUtilitу.нtmlEпсоdе(tеxt);

11 Добавляем в словарь обезвреженный текст


dictionary.Add(controLID, text);
}

11 На верхних уровнях объекта Tablel дочерними элементами


11 являются строки и ячейки таблицы, поэтому продолжаем
11 рекурсивно спускаться ниже, пока не встретим объекты TextBc
11 Флаг saveNested разрешает проверять вложенные уровни колш
if (controLControls != null)
(
SaveAIrГext( controLControls, saveN ested);
}
}
}

protected void спкIRеstoге_Сlick(ОЬjесt sender, EventArgs е)


(
11 Извлекаем из состояния вида пришедший с
11 обратной отсылкой промежугочный объект и заполняем

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

11 из него текстовые поля сохраненными з нач е ния ми


RestoreAllТe xt( е xecute FIa g);
}

11 Если достyn к функции явно не объявлен, то по умол ч ан ию считае'


vою RestoreAllТext(bool restoreN ested)
(
if (!restoreN ested)
геturп;

11 Изв лекаем пом е ченны е р анее да нны е из состояния


11 вида в nр омежуго чный объект-слова р ь
diс tiопагу :::: (Hashtable )t:his. ViewS tаtе[ "со пtепtsS tаtе "];

11 П е ребир аем все элементы за п олне нн о го словаря и ищем н а


11 странице соответствующее текстовое поле. Заодно за полня ем
11 па р ам и словаря текстовую метку для отсылки ЮIИен ту Текстовук
11 метку создадим ди намич ески и добавим в конец коллекции фор м
Labellabel :::: new LаЬеЮ ;
10 nnl .С о пtrо Is.Add(1a Ь е 1);
label Text = "< м 1>" + "< Ы > Зн ачения словаря < Ih2 > ";

foreach (DiсtiопагуЕпtry pair iп diсtiо пагу)


(
11 Выделяем ключ и значение для очередной и звле ч е нной пары
striпg key = раir.Кеу.ТоStriпgО;
striпg value = раir.Vаluе.ТоStгiпgО;

11 Ищем на ст р ани ц е текстовое пол е с соответствующим


11 идентификатором, уникальным в пределах страницы
TextВox item = (ТехtВох)Раgе.FiпdСопtгоl(kеу);
if ( itеш != пull)
(
11 Если наШllИ , за полня ем поле и текстовую метку
itеш.техt = value;

label Text += stгiпg.Fоrmat('Ке у={О) , Value= {1} ", key, value);


label Text += "< Ь г 1>";
}

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

}
}
}

Листинг Содержимое файла ViewStateObjects.aspx.cs

Поскольку мы взяли на себя проверку достоверности да нны х,


введенных пользователем , то нужно ОТЮlючить такую проверку

системой ASP.NET при считывании за проса , поместив

соответствующую инструкцию в директиву @ Page страницы или в

файл конфигурации в секцию <pages> . При этом нужно строго


учитывать регистр символов и в директиву @ Page атрибуг помещать
таким Val i dateRequest= " false ", а в конфигурационный файл
таким validateRequest= " false ". Это общее правило ASP.N ET
для случая, когда настройки до пускают двойств енн ое размещение .

• г;.:.='Дополните файл конфигурации wеЬ.сопfigсекциеЙ <pages> с


ОТЮlюченной проверкой достов ер но сти

<?xml version="l.O" encodmg=''utf-8'?>


< со пfigш аоо n xmlns= ''http ://schemas. mkroso ft.co m/. N etC о nfigшаtiо n/у2,
<system.web >
< соmрilatюп debug=''true'' />
<pages validateRequest="false" />
</system. web >
</соnfigшаtiоп>

Листинг Файл web.config с отключенной проверкой


достоверности

• ~Запустите приложение и убедитесь в его работоспособности

Результат после восстановления ранее сохра н е нной в состоянии вида


инфор мации будет примерно таким

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

11 untitled page - Мiсrоsоft Internet Explorer


-------------------------------

FiI€ Edit V ~W Favorites Toos

1~~:;ti?~h;;ttp~:~1/оХ
~аIГюst: 1160!ViewStateTest!VieWStateobjects.aspx

Заполните анкету
Нанменованне Значенне
Имя: ICHeTKOB ВМ.

Учетный номер: 112345


Возраст: 158 &11:17 лэт&gl:
E-mШl: ISandr77@JLlstru

Пароль: ICaTYPH почти не виден

Отправить Сохранить Восстановить

ЗначеlШЯ словаря

Key=TextВox4, Va1ue=Sandт77@List.ru
Key=TextВox3, Va1ue=58 < 17 лэт>
Key=TextВox5, Va1ue=CaТYPH почти не видеи
Key=TextВox2, Va1ue=12345
Key=TextВoxl, Vа1uе=Сиетков В.М.

Оопе

• ~дали те из секц ии <system . web> файла Web.config


п а р аметр отключ ения пр оверки до сто в ер н ост и <pages
validateRequest= " false " 1> и включ и те его как ат р ибyr
ValidateRequest= " false " в состав д ирективы @ Page

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

страницы ViewStateObject5.aspx, чтобы он действовал только на


одну эту страницу

Восстановление состоя ния вида элемента списка через


коллекцию запроса

Иногда состояние вида в элемен те полезно ОТЮIючить, чтобы


уменьшить нагрузку на каналы связи. Но дл я некоторы х элементов это
нарушает их н ормальную работу. Возьмем , например , с пи ски ListBox
и Dr opDownList . Когда они заполнены большим количеством
элементов, объем п ересыл аемой информации состояния вида очень
большой и это свойство лучше ОТЮlючить. Для восстановления
состояния выделенного элемента списка в этом случае можно

воспользоваться информацией из коллекции Request . Form


страницы . Проверим это на примере.

Упражнение 3

• г;.:.='Добавьте к п роекту стра ниц у с именем ViewStateList.aspx без


файла отделенного кода и назначьте ее стартовой
• ~Оформите страницу так, чтобы код ее интерфейсн ой части был
следУЮЩИМ

<%@ Page Language="C#" %>

<html xmIns= ' huр ://www.wЗ.or!j'1999/xhtml" >


<head runat="server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nmat="server''>
<div style=''text-align: center''>
< h2 > ОТЮlючение состояния вида в списках< 1h2 >
< a s p :ListВox
ID=''ListBoxl'' runat="server" Height="200px" Width=
&nbsp; &nbsp; &nbsp; &nbsp;
<asp:DropDownList ID=''DropDownListl ''
runat="server" Width="150px">

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</asp:DropDownLisp <br />


< Ьг />
<asp:Button ID =''Вuttо пl '' runat="selVer" Техt="Отправить " /></di
</fопn>
</body>
<lhtml>
Листинг Код интерфейсной части страницы

ViewStateList.aspx
• ~Этому КОдУ В режиме пр оект ирования соответствует
следующее пр едставление

/ ViewStateList,aspx [ . . .- х

~
Отключение состояния
вида в списках

[U пЬоuпd

ru nbound 3
IEJ Отправить J
• IJ$Двойным щелчком на свободн ом месте страницы в режи ме
Design создайте блок скри птов с за готовкой обработчика
Page Load ()
• г;.:;=поместите в обработчи к Page Load () код заполнения
списков видимым содержи мым, который будет срабатыв ат ь пр и
каждом запросе стра ниц ы

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<script runat= "server''>

// П оле Юlасса страницы


private const int maxCount = 1000;

protected void Page_Load(object sender, EventArgs е)


{
// За пол няем списки программной генерацией з н ач е ний
for (int i == О; i < maxCount; i++)
{
ListВохl.Itеms.Аdd("Опция " + (i + l).ТоStriпg());
DгорDоwnListl.Itеms.Аdd( "Опция " + (i + 1).ToString());
}
}
</script>

Листинг ОбобработчиlC Раче _ Load () для заполнения

СПИСlCов

• ~ыполните стр аниц у и убедитесь, что при каждом новом


запросе по щелчку на кнопке Submit отмечен ны е пользователем
опци и списков возвращаются сервером сохране нн ыми

Пока что это работает механизм автоматического сохр анения состояния


вида АS Р. NЕт. Но давай те посмотрим , какой при этом получается
объем пересылаемой инqюрмации , и менно касающийся р аботы этого
механизма. Для этого ВЮlючим работу ASP.NET в р еж име выдачи
трассир овЮ1 на ин дивидуал ьных ст р аницах. Э ТО можно сделать, если
добави ть атрибyr Trace= " true " в директиву @ Page страницы ,
либо через yrи литу WAT , за п устив ее командой Website/ASP.NET
Configuration (или щелкнyrь на пи ктorрамме в панели So lution Explorer) .

• ~Запустите yrил и ту WAT, п ойди те п оследовательно п о ссылкам


Application СопfiguгаtiОnlСопfigше debugging and tracing и ВЮlючите
флажки " Capture tracing information " и " Di splay
tracing information ОП ondividua l pages" .
Закрой те yrилиту

в результате эти х де йствий файл конфигурации примет ви д

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<?xml vеrsЮ п="1 . 0 " encoding=''utf-8 '?>


< со пfigша tioп xmlns= ''http://schemas.microso ft. coml.N etC опfigша tio n/У 2 .0">
<system.web>
< иа се enabled=''true '' pageOutput=''true'' />
<compilation debug= ''true'' />
</system.web>
</сопfigшаtioп>

Листинг Файл иеЬ. config после включения трассир овки


утилитой WAT

• r;:;'вHOBb запустите страницу ViewStateList.aspx, поманипулируйте


с инт е рфейсными элементами, выполните обратную отсылку и
пр оанализируй те секц ию Control Tree в результатах
тра сс ировки , которая будет, при мерно, такой

Co ntrol Тгее

ViewSl
Render S.
Сопtrоl Size Bytes /"
Туре . / d' Ву'е
Unique ID ( те u mg Id
hild (ехс u
с геп) hiId
с "
_ Page ASP. viewstatelist_aspx 910866 О
cd02 System. WеЬ.UI.LitегаIСопtrоl 50 О

cdOO System. WеЬ.UI.Нtm1Сопtгоls.НtmlНеаd 46 О

cdOl S ystem. Web. UI.Нtm1СопtгоIs.НtmfПt1e 33 О

cd03 System. WеЬ.UI.LitегаIСопtrоl 14 О

fопn1 System. WеЬ.UI.нtm1СопtгоIs.НtmlFопn 910736 О

cd04 System. WеЬ.UI.LitегаIСопtrоl 129 О

ListВox1 System. Web.UI. WebControls.ListВox 227258 196031


ctlO 5 System. WеЬ.UI.LitегаIСопtrоl 47 О

DгорDоwпList1 System. Web.UI. WеЬСопtrols.DгорDоwпList 227246 19603!


ct!06 System. WеЬ.UI.LitегаIСопtrоl 32 О

Button1 System. Web.UI. WebControls.Butron 78 О

cd07 System. WеЬ.UI.LitегаIСопtrоl 12 О

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

cd08 System WеЬ.UI.LitегаIСопtrоl 20 о

Объем п ересылаемой по каналам связи в оба конца информации


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

списков. ОТЮlючим сохранение состояния вида в списках, а для


восстановления позиций выделенных пользователем опций
воспользуемся тем фактом , что с каждым запросом эти значения
передаются на сервер в словарь Reques t . Form объекта страницы.

• ~ ерейдите в режим Dеsigп редактора страницы


VIewStateList.aspx, выделите одновременно оба с пи ска и через
п анель Properties сбросьте свойства Ena bl eV i ewSta t e
• Г;;:;=Запустите страницу VIewStateList.aspx и убедитесь, что объем
сохраняемого состояния вида для списков стал нулевым

Замечание. Если количество запросов превысит зада нно е пар аметром


трассировки reque s tL i mi t значение (по умолчанию 10), то ASP.NET
при исполнении не будет ВЮlючать результаты т р ассировки в страницу
В этом случае нужно при о ч ередном запуске тестово го браузера вызвать
ч ерез строку адреса страницу trace.axd и щелкнугь на ссылке " с 1 еа r
cu rr en t t r ace " этой страницы. ВЮlючить безлимитную
трассировку можно более просто· добав ить в директиву @ Page
страницы параметр Tr ace=t r ue

Мы видим , что при ОТЮlючении сохранения состояния вида резко


уменьшился и общий объем страницы. Но сервер в своих ОТЮlиках не
сохраняет выбранные Юlие н том опции списков. Исправим этот
недостаток пр о гра ммно.

• IJ$Добавьте к странице код восстановления выбора пользователя


в списках

<script nmat="server''>

11 Пол е Юlа с с а страницы


private const iпt maХСО Шlt = 1000;

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

protected void Page_Load(object sender, EventArgs е)


(
11 3а п олняем сп и ски программн ой генерацией значений
fo r (int i = О; i < maxCount; i++ )
(
ListВохl.1tеms.Аdd("Опция "
+ (i + l).To String());
DгорDоwnListl.Itеms.Аdd("Опция "+ (i + l)ToString());
}

11 Отслеживание вы дел енных пользователем опций списков


if (this.IsPostBack)
(
string text = this.Rеquеst.Fопn[''ListВохl '1;
ListВo x l . Items.FindByText( text) .Selected
= true;
text = this.Rеq uе st.Fопn[''Dго рD оwпListl "];
DropDownListl.Items.FindByText(text).Selected = true;
)
e~e
ListВо х l .Sеleсtеd Iпd ех = Drop DownListl .Selected lndex = О;
}
</script>

Листинг Окончательный код блока скриптов,

восстанавливающий состояние списков

Броузер с обратной отсылкой присылает на сервер значения


выделенных элементов списка , собираемых дескриптором <form> из
HTML-Koda, представленнorо примерно таким фрагментом

<select size="4 " паmе ="ListВо х l " id= ' 1.istВ ox l " stуlе=' 'hеight:200рх;wюth:1 S0I
<option selected="se lected" vаluе= "Опция 1 "> Опция 1 <Ioption>
<option vаluе="О п ц ия 2' '> Опция 2<loption>
<option vаluе= "Опция 3''> Опция 3<loption>

</select>

Фактически броузер посылает пару ListВох1=Опция 1, которая


попадает в словарь Reques t . Form. доступ ный дл я извлечения и
использования в коде страницы на стороне сервера. Мы находим это
,;о
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

знач ен ие в сген ерирова нн ой коллекц ии значе ний с п иска и настраиваем


этот элемент коллекции как выделенный. После таких н астроек сп и сок
сген ерирует в текущем отклике сервера н уж ный HTML-кod ,
соответствующий состоянию с пи ска на ютиен те перед обратной
отсылкой .

• Г;:;=3апустите ст р аницу ViewS tateList.aspx с ВЮlюченной


тра сс ировкой и убедитесь, что выбранные опции списков
сохран яют свои по зи ции и ASP.NET ге н е рир ует неБОЛЫ1ЮЙ объ ем
клиен тского кода

Таким образом мы выяс н или, что состояние ви да элемен тов


управле н ия, которое включе н о по умолчанию , не все гда является

полезным либо про сто н е используется , и то гда е го лучше отютючать.


Отютючить состояние вида мож но следующим образом:

1. Н а уровне п р ил ожен ия для всех стра ниц в файле web.config корня


we b -дер ева сай та

<?xml version= "1.0" encoding=''utf-8'?>


< со пfigш аоо n xmlns= ''http ://schemas. microso ft.co rпI. N etC о nfigшаtiо n/у2,
<system.web >
< соmрilatюп debug=''true'' />
<pages enableViewState="false" />
</system. web>
</соnfigшаtiоп>

2. Н а уровне страницы , добав ив в директиву @ Page п а р а метр


Enab l eViewSta t e= "f alse " (в коде свой ство
Page . EnableV i ewSta t e = fa l se )
3. Н а уровне элеме н та управле ни я, добавив в дескр иптор элемен та
атрибуг EnableViewState= " fa l se " (в коде свой ство
Э л еме Н Т . Епа bl еV i еwStа t е = false )

Если более общая на стр ойка сохр а нения состояния ви да выключ е н а, а


дл я каких- то страни ц или элеме н тов управления ее н ужн о ВЮlючить , ТО

В соответствующее м е сто следУет доба вить атрибуг


EnableViewState= "t rue ".

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Защита информации в состоянии вида

Состояние вида п е редается клиен ту системой ASP.NET в скрытых


полях частично за шифрованным . Но это шифровани е пов е рхностное ,

чтобы не тр ебовало м ного проц ессор ного времени. При желании


злоумышленник может частично восстановить и прочитать эту

информацию.

Упражнение 4

• r;:;='Добавьте к проекту новую страницу (без фай ла отделенного


кода) с именем Di splayViewstate . aspx и установите ее
стартовой
• ~дали те из интерфейсной части страницы дескриптор <d i v>
</div>
• г;.:.=включите трассировку, добавив в директиву @ Page
страницы пар аметр Trace=true
• ~Добавьте в блок скриптов кодовую часть, чтобы окончательно
страница стала такой

<%@ Page Language="C#" Trace=''true'' %>

<script runat= "server''>

protected void Page_Load(object sender, EventArgs е)


(
// Объекты создаем каждый раз заново
Labe!labe! = new Label();
trus. fопn!. С о ntro Is.Add(1a Ь е 1);
trus. fопnl. С о ntro Is.Add( new Н tmlGenerk:Contro 1( 'Ъг ") );

Button button = new ВинопО;


trus. fопnl. С о ntro Is.Add(butto п);

if (!this.lsPostBack)
{

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

// Один раз настроили, а дальше работает состояние вида


IabeL Text :::: ''Привет всем!! !";
button.Text:::: "От править ";
}
}

protected void Page_PreRender(object sender, EventArgs е)


{
// Вывод на страницу строки состояния
~ (this.lsPostВack)
(
// Извлекаем строку состояния
string strViewState :::: t:Ыs.Request.Form{"_ VIEWSТAТE'1;

// Добавляем вывод к родительской ф:Jрме


Labe!labe! :::: new Label();
this. fопn!. С о ntro Is.Add(1a Ь е 1);
IabeLText :::: "<р>< Ь > Строка состояния как есть: < /Ь><Ьг />"
+ strViewState + "</р >";
IabeLEnableViewState = false;// Чтобы не влияла на результат

// Преобразуем строку из Ваsеб4 в массив АSСII-символов


byte[] ascii = Сопvеrt.FгоmВаsеб4String(stгViеwStatе);

// Вставляем в ОТЮJик
Response.Write("<b > CTpoкa состояния в ф:Jрмате ASCII:</b:
Resp о nsе. BinaryWrite( asc п);

// То же самое, только по турецки ...


// Десериализация и отображение строки
//string decodedViewState = System. Text.Encoding.ASCII.GetStJ
/lRespo nse .Write(decoded ViewS tate );
}
}
</script>

<html xmlns='huр://www.wЗ.or&,!999/xhtml" >


<head runat= "server''>
<tide >Untitled Page</tide>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<lhead>
<body>
<form id ="forml " nшat="sе lVе г ''>
</fопn>
</bod y>
<lhtml>

Листинг Окончательный код страницы


DisplayViewState.aspx
• ~3апустите страницу DisplayViewState.aspx и повыполните
обратную отсылку

HTML-отюJИК на стороне клиента, сгенерированный страницей


DisplayViewState.aspx при об р атной отсылке, будет выглядеть примерно
так

Стр ока состояния в формате ASC II:


'?D 7834305330doo О о DdD 00 О О 00 О О оТеЛD ОПРrlвет BceM111 О ForeColor '?о О 0-'
SBo о ddo о о о о о о о оОтправитьddd????mГуs'?N?? о?;??

Приветвсемlll

Стр ока состояния как есть:


wEРD.лЛJJNzgzND~ТМzD2QWАgIDD2QVVВАIВDw8WВh4ЕVGV4dАUУОJ
gNC40LLOl dGCINCyiJYHOldC81SEhHgIGb3JI029sb31KJOEeBF8hUOICBGR
kAgMPDxYCНwAFEtCeOYLQy9GAOLDOstC40YLRjGRkZLynv5ptbHIzYD90lZAEnzvaJN8Z

Мы видим, что н екоторая инфор мация, сохраняемая на клиен те в строке


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

Поскольку состояние вида формирует только сервер ная сторо на , то


п еред включением строки в скрытое поле НТМL-вывода ASP,NET
вычисляет контрольную сумму и прячет ее в ту же самую стр оку. При
получении этой хэшированной строки от клие н та система
десериализует ее, вновь вычисляет контрольную сумму и сравнивает с

ранее спрята нной, Несовпадение легко обнаружить . Подсчет


контрольной суммы включается в директиве @ Page параметром
EnableViewStateMac= " true ".
'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Для большей защиты строки состояния вида можно использовать


встроенное шифрование , которое ВЮIючается на странице параметром
ViewSta t eEnc r ypt i onMode= " Alw ays " директивы @ Page или
установкой в конфигурационноЛ1 файле секции

< ра ges viewS tate Епсгурtlo nм ode= "Аlwа ys ''>

• ~ЮIючите шифрование и выполните страницу

DisplayViewState.aspx. Сгенери рованный ОТЮlик на обратную


отсылку станет примерно таким

СТРОКЭ СОСТОЯНИЯ В формате ASCII:


В?\???30)7 ?? о ????0?0Ь?? 0ct?роу??G$О'Ю ?g ??ВhD?е??Е??А?r?IJ5D::m,-?А??3М=?т??д?????о[с????

ПРf'l3ВТ BceM 11!

Строка состояния как ест.:


Qрlс 20 Gr5SВJ LhdРomxQ"mDАs 81lIlRЬsh5В V=УLШCsrtJDm3DсАd5i i7Г\Y kckB',P'J
Dr5пgУVСаЕ3qZсуАqОWtgз SДп 3КSVТVЕЫ 3ifi.S\YfXсtВ kЬNТЮуОМ:JhОРft.pm7хQ
амм-ус .. Зр/орLtВоQg5lN Зm4 1 y.'GvtD 1FW7V51=

Теперь строка состояния стала за шифрованной и ее тр удно


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

Скрытые поля

Во ВЮIадке Standard панели Toolbox имеется элемент управления


HiddenField, который генерирует скрытое поле с единственной
пер еменной, определяемой его свойством Value . Э тот элемент не
поддерживает шифрование , хэширование и хра нение по частям.
По этому ЮIиенты в исходном коде НТМL- вывода могуг просматривать
эти да нные. Данные в скрытом поле хранятся до тех пор , пока
пользователь не перейдет к другой странице.

Упражнение 5
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• IJ$Добавьте к проекту новую страницу с именем

Hi ddenFie l dTest . asp x без файла отделенного кода и


назначьте ее стартовой
• ~ ереведите страницу в режим Design и двойным щелчком
создайте в кодовой части обработчик
Page Load ( )
• ~ оместите на Web-форму из вкладки Standard панели Toolbox
два элеме нта управления Hi ddenF i e l d и присвойте и м и мена
beginT i me и count Request
• IJ$Отключите для всех элементов страницы меха низм
сохранения состояния вида, добавив в директиву @ Page
пар аметр EnableViewState= " false "

• ~Заполните страницу следующим кодом

<%@ Page Language::::"C#" EnableViewState::::''fulse'' %>

<script runat:::: "server''>

protected void Page_Load(object sender, EventArgs е)


(
// Создаем текстовую метку
Ibrrmle = new Label();
divl. Controls.Add(lblrUIle);
div1. Controls.Add(new НtmlGепеricСопtrоЧ'Ъr'));

// Создаем кнопку Сшrе пtТпnе


Button ЬиНоп :::: new 8инопО;
div1. Controls.Add(button);
// ПОДписываемся на событие кнопки
button.Ctick += CurrentTuneClick;
button.Text:::: 'Текущее время";

// Добавляем промежугок междУ кнопками


Literalliteral:::: new Literal();
literaLText :::: "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
div 1. С о ntro Is.Add (literal);

// Создаем кнопку ОldТпnе


button:::: new ButtonO;
div1. Controls.Add(button);
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

// По.цписываемся на событие кнопки


Ьuttоп.Сtick += ОldТпneСliсk;
Ьuttоп.Техt = "Начальное время";

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


if (!this.lsPostBack)
(
ЬеginТпne.Vаluе = SystemDa teТIme.Now.To LongТnneStringO;
О IdТimeC lick(null, EventAгgs.Empty);
}
else
(
// Ведение счетчика запросов страницы
int.TryParse(countRequest.Value, out count);
соuпt+ + ;

// Или то же самое
// count = int.Parse(countRequest.Value) + 1;
}

соuпtRеquеst.Vаluе = count.ToStringO;
}

// Вынесены в поля класса для видимости в обработчиках


int count = О;
LаЬеllbIПmе;

void СшгепtТnnеСliсk(оЬjесt sender, EventArgs е)


{
Ibrrmle.Text = 'Текущее время:" + System.DateTnne.Now.To Lon,g
Ibrrmle.Text += "<Ьг /> Ответ NQ " + count.ToStringO;
}

void Ok:lTnneClick(object sender, EventArgs е)


{
Ibrrmle.Text = "Начальное время: " + ЬеginТпne. Value;
Ibrrmle.Text += "<Ьг /> Ответ NQ " + count.ToStringO;
}
</script>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<html xmIns='huр://www.wЗ.or&,1999/xhtml" >


<head runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nшat="sеrvег''>
<div style=''text-align: center" id ="div1" runat="server''>
<h1 style="colo r: Red''>
Испытание элемента Hkld enFie ld
<1h1>
<asp:Hkld enField ID ='ЪеginТnne " nшat="sеrvег" 1>
<asp:Hkld enField ID="countRequest" runat="server" 1>
</div>
</fonn>
<lbody>
<lhtml>

Листинг. Код страницы HiddenFieldTest.aspx


• Г;;:;=И сполните страницу и убедитесь, что скрытые поля,
генерируемые элементом Hi ddenF i eld , в пределах одной

страницы работают исправно

Строки запроса

Одно из самых серьезных ограничений состояния ви да состоит в том ,


ЧТО оно работает только на одной странице. При переходе пользователя
на другую страницу состояние вида прежней страницы уграчивается.
Одним из выходов является передача инф:Jрмации в строке запроса ,
которая может переносить инф:Jрмацию со страницы на страницу. Но
этот способ имеет несколько недостатков:

1. Инф:Jрмация является видимой для пользователя и доступна дл я


вмешательства с е го стороны. В результате страница может
получить такие данные , от которых она не имеет защиты

2. Инф:Jрмация должна кодироваться допуст имыми для URL


символами

з. Броузеры уста навливают ограничение на длину URL, которая


должна быть в пределах 1-2 Кб. Поэтому в строку запроса нельзя
помещать большое количество информации

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

4. Форма отправляющей страницы долж на использовать метод


п е редач и GET вместо POST
s. Формирование строки запроса и извлечение из нее информации
программист выполняет вручную

Отправляющая запрос страница инициирует передачу либо с помощью


2иперссылки (элемент HyperLink ), либо с помощью кнопки Submit, в
обработчик которой вставлен код Response . Red i rect (URL) . Для
извлечения информации из строки запроса на адресуемой (целевой)
странице используется встроенный в нее объект·словарь
Request . Que r yStr i ng .

Упражнение б

• ~Добавьте к проекту страницу без файла отделенного кода с


именем SourceQuerystring . asp x и назначьте ее стартовой
• ~Добавьте внугрь контейнера <d i v></div> дескриптор
строки · заголовка

<h1 style="colo r: Rеd' '> Введите учетную запись < lhl >

• г;.:.='Дополните открывающий дескриптор <d i v> стилем


ц е нтрирования

<div style=''text-align: center''>

• ~Создайте на Web-форме позиционирующую таблицу размером


Зх2 и поместите в ее ячейки из вкладки Standard панели Toolbox
серверные элементы с настройками согласно таблице

Таблица свойств элементов


управления страницы

Sо шсеQuегyS tring.аsрх

Элеме нт Свойство

Label ID= " Labell "


Те х t= " Имя :"

Te xtB o x ID= " Name "


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Label ID= " Labe12 "


Те х t= " Пароль :"

Te xt Bo x ID= " Passwo r d "


Te x tMode= " Password "
Button ID= "B ut t onl "
Те х t= " Отправить "

Ин терфейс стра ниц ы в режиме проектирова ни я БУдет таким

/ SourceQueryString.aspx I ~ х!

.=J
Введите учетную запись

I fI~ [ F
I ~аl)QЛЬ :!I F I
I
ltJ Отправить I
• ~ ереведи те стран ицу в режим Dе s igп и двойным щел чком на
элем е нте Button l создай те для н е го обработчик. Заполни те
об р аботчи к следУЮЩИМ кодом

protected void Buttonl_Clic k(object sender, EventArgs е)


(
string Иг l = 'TargetQ ueryS tring.aspx?N аmе="
+ Sеrve г. UгlEпсоdе(Nаmе.Теxt)
+ "&Password="
+ Server. Uг lEпсоdе(Р аsswогd.Теxt);
this. Response. Redirect(Url);

11 То же самое, только с п р ямой переадреса ц ией


11 this .ServerT ra nsfer(Url);
}

Ли с тинг Код о б ра бо тчика с обытия Cli c k элемента Buttonl

,СО
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Кнопка будет инициировать обратн ую отсыл ку, а ее обработчик


сф:J р мирует адр ес целевой страницы со значениями параметров , снятых
с эл е мен тов текстовы х полей. Перед включ е ни е м в строку адреса
введе нны х п ользователем значен ий мы приме н яем URL - коJuрованuе ,
п реоб р азуя тем самым ввод в допустимые символы . К сожалению ,
строку ад реса приход ится ф:Jрмировать вручную .

• ~ ереведи те страницу в режим Design и дво йным щел чком


создайте в кодовой части обработчик Page Load () . Заполни те
обработчи к кодом , восстанавливающий состояние текстового
поля Na me сохра н е нн ым в строке запроса з нач ением

protected void Page_Load(object sender, EventArgs е)


(
if(this.Request. QueryS tring['Name'1 != null && ! this.lsPostВack)
Nаше.Техt = this. Rеquеst. QuеryS tring["Nаше"];
}

Ли с тинг Код о б ра б отчика с об ытия Page_Lo ad () страницы


Sourc eQueryS tring . a s px

Страница SourceQueryString.aspx, отправляющая строку запроса , готова .


Вот ее полный код

<%@ Page L апguagе="С#" %>

<script nшa t="sеrvеr''>

protected void Buttonl_Click(object sender, EventArgs е)


(
string Url = 'TargetQ ueryString.aspx?N ате="
+ Server. Ur lEпсоdе(Nаше.Техt)
+ "&Password="
+ Server. Ur lEпсоdе(Р аsswоrd.Теxt);
this.Response. Redirect(Url);

11 То же самое с п рямой п ереадреса ци е й


11 this .ServerT ra nsfer(Url);
}

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

protected void Page_Load(object sender, EventArgs е)


(
if (this.Request.QueryStringI'N ame'1 != null && !ttlls.lsPostВack)
Name.Text = this.Request.QueryString["Name"];
}
</script>

<html xmlns=''httр ://www.wЗ.огgl1999/xhtml'' >


<head nmat="server">
< title > Uпtitled Page</tide>
<lhead>
<body>
< fопn id="fопnl" ruпаt="sеrvег''>
<div stуle=''tехt-аligп: center">
< Ы s tу!е="союг: Red">
Введите учетную запись< lhl >
<table border=''O'' width="100%">
<tr>
<td stуlе=''tехt-аligп : right; width: 412рх;' '>
&nbsp; <asp:Label ID='1.abell " nmat="server" Техt=' Имя:" 1>
</td>
<td >
&nbsp; < asp:TextВox ID='N ате" runat="server" 1>
</td>
</tr>
<tr>
<td style=''width: 412рх; tеxt-аligп: right''>
&nbsp; <asp:Label ID='1.abel2" runat="server" Техt=''Пароль:'' ,
</td>
<td >
&nbsp; < asp:TextВox ID=''Passwo rd'' runat="server" TextМode=
</td>
</tr>
<tr>
<td colspan="2" style="text-align: center''>
&nbsp; <asp:Button ID=''В uttо пl '' runat="server" Техt="Отправ
ОпСlick=''Вuttопl_Сliсk'' 1>
</td>

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

</tr>
</table>
</div>
</form>
<!body>
</html>

Листинг Полный код отправляющей страницы

SоurсеQuеrуStriпg.аsрх

Теперь нужно создать принимающую запрос (целевую) страницу На


целевой странице значения поступивши х параметров , извлекаемые из
строки ЗQПРОСQ, следует пр едварительно URL· раскод ировать. Затем
можно прин ять решение, что делать с п оступившими данными.

• ~Создайте страниц у с совмещенным кодом и именем


Ta r getQuerySt ri ng . asp x
• Г;;:;=Заполните страницу следующим кодом

<%@ Page L апguagе="С#" %>

<script nmat="server''>

protected void Page_Load(object sender, EventArgs е)


(
11 Критерии оценки зарегистрированного пользователя
const string NAME = 'USER", PASSWORD = ''ROOT';

11 Изв лекаем и раскодируем по ступ ивши е данн ы е и з строки запрос,


string пате = this.Request.QueryS tring[''Name'1;
пате = this.Server.UrlDecode(name);
string password = this.Request.QueryS tring[''Password'1;
password := this.Server. UrlDecode(password);

11 С оздаем текстовую метку для отображения решения


Labellabel = new LаЬеЮ ;
10 nnl .С о пtrо Is.Add(1a Ь е 1);

11 Р езерв ир уем место для размещения rnп ерссылки

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

PlaceHok:ler р\асеНipегLiпk = new P\aceHolderO;


fo пnl . С о ntro Is.Add(p \а се Нip егLiпk) ;

11 Создаем муляж кнопки


Button button = new ButtonO;
fo пnl . С о ntro Is.Add(button);

11 Анализи р уем да нны е и принимаем решение


5 triпgВ uildег message = new 5 tringВ uild erO;
if(nameToUppeгO == NAME && passwoгd.ToUppeгO == PASSWQ RI
(
11 Пр осто выведем хвалебное приветствие
message.Append("<h1 style=\"co lor: Red\''> ');
теssаgе.Аррепd("Приветствуем Вас , дорогой" + пате + "!');
message.Append("<lhl >');

11 ОТЮJючаем у кнопки с посо б но ст ь инициир овать отсыл ку


11 Ле нь посы лать даль ше зарегистрированного поль зователя
button.PostBackUrl = '~avascrip t : void(O)";
button.Text = ''Даль ше >";

11 Добавляем в зарезервированное место гиперссылку


HyperLink link = new Hyp erLinkO;
р !асе Hipeг Liпk. С о пtго Is.Аdd(liпk );
link. Text = "< Н азад";
link.NavigateUrl:= "~/50urceQueryS tring.aspx?"
+ ''Name='' + пате;

11 Добавляем в зарезервированное место про белы


Labellb!Space = new Label();
р все Hiper Link. С о ntro Is.Add(lb lS р асе);
lblSpace.Text = "&nbsp;&nbsp;&nbsp;&nbsp;";
}
else
(
11 Поруга ем и отправим на повторную регистрацию
message.Append("<h1 > ');
message.Append("BbI н ео по знаны< ь гr I> Повто рите регистрацию.,
message.Append("<lhl >');

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Ьuttоп.Ро stВас kUг! = "~/SошсеQ uегуS tгing. аsр х?"


+ ''Name='' + пате ;
Ьuttоп.Теxt = "< Наз ад";
}

// Выводим сф:Jрмированное сообщение


label Text = message.ToStringO;
}
</script>

<html xm1ns=''httр://www.wЗ.огgl1999/xhtml'' >


<head nmat="server">
< title >Uпtitled Page</tide>
</head>
<body>
< fо пn id ="fо пnl " ruпаt="sеrvег' '>
</foпn>
<!body>
</html>

Листинг Полный ход страницы TargetQueryString . aspx

Об р ат и те в ни ма ни е , что ин те рфе йс н ая ч асть ц еле в о й стра ницы


со в е ршенн о п уста я - все создается дина м ич ес ки .

• Г;;:;=Запустите стран и цу SошсеQ uегyS tгing.аsрх н а в ып ол н е ни е и


убеди т ес ь , что механизм межстранич но го обме н а ин ф:Jрма ц ией
ч ерез строку зй прОСЙ р а ботает

Стра ниц а TargetQ ueryS tring.aspx на юш е н те при на в еде нии курс ор а


мы ши н а 2uп ерссЬ/лке будет в ыглядеть так
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

~ Untltled Page - Мicr050ft Internet Explorer


- -....;...;

Приветствуем Вас, дорогой User!


< Наз ад Дагъше> I
!iJ ht1+>:/!ocahJst: llБОfljewStatеТest/3cuceQueryStr"J aspx7t-Jamе=Usег Г Г Г ~ Lосз iltriflet М

Межстраничная обратная отсылка данных

в классах кнопочных элементов ynравления Ви t ton , IтageBu t ton


и LinkButton имеется свойство Pos t BackUrl , позволяюще е сразу
адресоваться к целевой странице с достynом в н ей ко всем данным
текущей страницы. Свойству PostBackUrl кнопки обратной отсылки
при сваивается строка с URL целевой ст р аницы, которая и будет
за груж ена на выполнение по щелчку пользоват еля на этой кнопке. При
этом на ц елево й странице, бла годаря ее свойству PreviousPage ,
будет полностью достynен объект страницы, инициировавшей
обратную отсылку.

Идея реализации механизма межстраничной отсылки достато чн о


проста. Любая страница на этапе описания яв ляется классом
(инструкцией) с именем, равном им е ни страницы, которая при загрузке
в па мять се рв е р а пр евра ща ется в объект (экземпляр класса), адресуемый
средой исполнения. Исполняемый объект пр оход и т все необходимые
этапы жизни, начиная с инициализации элементов ynравления ,

кор ректировкой состояния, выполнением обработчиков, и закан чив ая


гене р а цией HTML -Koda (рендерингом).

То же самое пр оисходи т и со страницей, загруженной по кнопке с


н енулев ы м свойством Pos t BackUr l. Она также проходит все
нач аль ны е стадии жизни , включая выполнение об р аботч иков.
Непосредственно п еред генерацией HTML-кada выполнение исходной
страницы прерывается, но она продолжает оставаться в памяти сервера .

Одновременно запускается объект ц елевой страницы, которому в


свойство Pr eviousPage среда исполнения за пи сывает адрес объекта

,ее
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

п ервой стра ницы .

Теперь код целевой страницы может адресоваться к общедостynным


данным ис ходной страницы, но рендеринг для кrlИента будет
ге нерироваться только второй страни ц ей. Когда целевая страница
зака н чивает свой цикл жи зни , вместе с н ей из памяти выгружается и
ис ходная стра ниц а. Для того , чтобы закрытые или защищенные члены
класса исходной ст р аницы стали достynным и в классе целевой
страницы , их н ужно обернугь в общедостyn ны е свойства или функции
достynа .

Рассмотренная межстраничная связь может быть реализована не только


как "один к одн ому", но и в других со ч ета ни ях: "один ко м н огим",
''многие к одному" или "м н огие ко многим". М н ожестве нн ость на

ис ходной странице может бы ть ор ганизова на программным


формированием з нач ения свойства PostBac k Ur l в зависимости от
выбранных на это й странице пр едп очтен ий . Множественность на
ц елевой страни ц е реализуется проверкой того , к какому тип у (к какой
странице) отн ос ит ся записанный в свойство Pre vious Page объект.

Межстр анич ная обратная отсылка целевой страницы может бы ть


иници ирована не только по щелчку на кнопке с ненулевым значе ни ем

свойства Post Bac k Ur l , но и в любом месте кода вызовом


соответствующей nерегрузкu метода

public void Раgе.Sеrvег.Тгапsfег(striпg path, Ьоо! preserveForm)

где

• ра th - вызываемая ц елевая страница


• prese rve Fo r m - фла г передач и в целевую стра ниц у данных
QueryString и Fo r т

Оп тим альным БУдет вызов

Sеrvе г.Тгапsfег(Uг l, true);

Упражнение 7

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Проиллюстрируем межст р ани ч ную отсылку на примере двух стра н и ц ­


и сточников и двух ст р а н иц- п риемников.

• г;;.:;='Добавьте к проекту стран ицу с совмещенным кодом и имен ем


Sou r cePostBac kl. asp x
• ~ азначьте стран иц у ста ртовой и оформи те п ользовательский
и н те р фейс н а этапе проектuрова н uя так, как п оказан о н а ри сунке

/ SourcePostBackl.aspx 1 ТХ

~TO первая странпца-источии I<!

Сотудент

Фамилия: ~BaHOB Доцент

• POStB8CkUrl 1· Sеrvег.Тгапsfег()

i'Ia вторую страницу-источиик

Здесь ис п ол ь зова н ы серверные элеме н т ы Label , Te x tBo x,


Lis tBo x, Button и HyperLink .

• г;;.:;='Для элемента уп равления Li stBo x ВЮlючите свойство


AutoPostBack
• ~3аполните стра н и ц у следую щи м кодом

<%@ Page Language="C#" %>

<script runat= "server''>

// Функция доступа к закрытому полю Юlасса из внешнего кода


риыic striпg GetNameO
{
геturп txtName.Text;
}

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

// Свойств о доступа к закры тым данным кл асс а из внеlllilего КО/


риыic s triпg GetTrtle
{
get { return IbШIJе.Техt; }
}

stгiпg text;

protected void Page_Load(object sепdег, ЕvепtAгgs е)


{
// Пр осто отображаем страницу
if (lstPost.Se)ectedItem == пull)
геturп;

// Выбираем целевую стр аницу при AutoPos tВack слиCiЫ


text = IstPost.Se)ectedItem.Text;
if (Stгiпg.Соmpаге(tехt, "С туде нт ", true) == О)
ЬtпРоstВасk UrL PostВack Url = "~/C rossP аgеStudепt.аsрх";
.Is. ЬtпРоstВасk UrLPostВack Url = "~/C rossP ageLecturer.aspx";
}

protected void btn_Click(object sе пdег, EventArgs е)


{
// Контролируем нал и ч и е выбора при щелчках на кн о пка х
if (lstPost.Se)ectedItem == пull)
(
Stгiпg mess = "<sс гipt>а)егt('Выберите сотрудн и ка') </" + "scrq:
this.Response. Write(mess);
геturп;

text = IstPost.Se)ectedItem.Text;

// Различаем кнопки
Вuttоп btn = (Button)sender;
if (Stгiпg.Соmpаге(Ьtп.Техt, ''PostBackUrl'', true) != О)
{
if (Stгiпg.Соmpаге(tехt, "С туден т", true) == О)
,СО
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

tШs. S erver. Transfer( "~ IC rossP а ge S tudent.asp х ", true);


else
tШs.Sеrvег.Тгаnsfer( "~/С rossРаgеLесtшег.аsрх", true);
}
}
</script>

<html xmIns= ' huр ://www.wЗ .or&,1999/xhtml" >


<head runat= "server''>
<tide > Untitled Page</tide>
<lhead>
<body>
<form id= "forml " nшat= "sе rvег ''>
<div style=''text-align: center">
<asp:Label ID="lb rПdе " runat= "server" Теxt= 'Э то первая стран
< Ьг 1>
< Ьг 1>
Фамилия:&пЬsр;
< asp:TextВox ID=''txtN ате " nmat= "server''> Иван ов </asp :TextВ
< asp:ListВox ID=''lstPost'' runat= "server" Height="45px" A utoPos
< аsр:ListItеm> Студен т </аsр:ListItеm>
<asp :ListItem>Д о цент </asp :ListItem>
</asp:ListВox >
< Ьг 1>
< Ьг 1>
<asp:Button ID ='Ъ tnPо stВасkUг l" runat= "server" Text="PostBacl
<asp:Button ID ='Ъ tпSеrvе гТга пsfег" runat="server" OnClick = OЪtn
Text="Server.Transfer()" 1>
< Ьг 1>
< Ьг 1>
<asp:HyperLink ID =''НурегLinkl '' runat="server" NavigateUrl="S
На вторую страницу-исто чник</аsр:НурегLink >
</div>
</fOmI>
<!body>
<lhtml>

Листинг. Полный код страницы SourcePostBackl.aspx


• ~ олучите копию ст р аниц ы sошсе Ро stВасkl. а s рх под им ен ем
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Sou r cePostBac k2. asp x и скорректи руйте в ней элементы


lblT i tle и HyperLinkl
• ~Создайте новую страни ц у с им ен ем

CrossPageStudent . asp x без файла отделенного кода, в

которой блок скриптов за полните так

<%@ Page Language="C#" % >

<script runat= "server''>

// Поля, заполняемые данными вызвавшей страницы


Strmg пате, tЮе, classN ате;

// Наша функция, иcnользующая достyn С помощью механизма (


void GetInfoPreviousPageO
(
// Получаем ти п запускающей страницы для
// динамического вызова членов представляющего масса
System Туре typePreviousPage := this.PreviousPage.GetTypeO;
// Находим общедоступный метод масса
SystеmRеfleсtioп.Меthоd Iпfо methodGetNaтe ==
type Р revio us Р age .GetМ ethod( "GetN ате ');
// Выполняем метод предыдущей страницы
пате == теthоdGеtNате.Iпvоkе(this.РгеviousРаgе, null).ToStrmgO;
// Находим общедоступное свойство масса
SystеmRеfleсtioп.Ргор еrtуl пfо prop ertyGetТide ==
type Р revio us Р age .GetP го perty( "Ge tТide ');
// Выполняем свойство преДЫдУЩей страницы
title := propertyGetТide.GetGetМethodO.
Iпvоkе(this. PreviousPage, null). ToStringO;
// Извлекаем имя масса пр едыдущей страницы
className = this.PreviousPage.GetTypeO.Name;
}

protected void Page_Load(object sепdег, ЕvепtAгgs е)


{
// Получаем инфо рмацию с предыдущей страницы
GеtlпfoРгеvious РаgеО;

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Labe!labe! = пеw Label();


Югт!. С о ntгo ~. Add(labe 1);
stгiпg text = "< hl stу!е='tехt-аligп: eenter; со !or : Red'>";

if (t:his.PreviousPage == null)
{
text += "С траница запущена напрямую < lhl >";
IabeL Text = text;
геtшп;

text += "Методом межстраничной обратной отсылки получен


text += "< UI>";
text += "< ti> Заголовок:" + title + "<Ili>";

if (String.Compare(classN ате , "SошееРоstВасkl _а sрх", true) == (


text += "< ti>Данные приелала первая етраница < Ili>";
else if (String.Compare(className, "S ошсеРоstВасk2_аsрх ", true)
text += "< ti>Данные приелала вторая страница <Ili>";
text += "< ti> Фамилия СТУдента: " + пате + "</ti>";

if (t:his.PreviousPage.lsCrossPagePostВack)
text += "< ti> Обратная отсылка инициир ована свойством Р(
else
text += "< ti> Обратная отсылка инициир ована методом SeГ\o
text += "</UI>";
LзЬеL Text = text;
}
</script>

<html xmIns= ' huр ://www.wЗ .ог&,!999/xhtml" >


<head runat= "server">
<title >Untitled Page</title>
<lhead>
<body>
<form id= "forml " nmat= "server">
</fonn>
</body>
<lhtml>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET
Листинг Полный ~oд страницы - приемни~а данных

CrossPageStudent.aspx
• ~ олучите ко пи ю ст р аницы CrossPageStudent.aspx п од именем
CrossPageLecturer . asp x

Эти обе страницы-приемники имеют совершенно одинаковый код и


просто демо нстрируют р аботу схемы межстран и чной передачи данных
"многие ко мно гим". В обеи х страницах используется наша функция
Get I n f oPreviousPage () , в которую мы ynаковали код ,

извлекающий данные из масса страницы-источ ни ка на этапе


выполнения . Этот прием применен потому, что пр и прямой адре сац ии
к членам пр едыдущей страницы компилятор ищет их в текущей
странице и выдает ошибку компиляции (и пр авильно делает) . А пр и
ди намическом достynе он работает только со строковыми именами
свойств и методов предыдущей стр ани цы .

• ~ азбери тесь с кодом отсылающей и принимающей сторон и


испытайте и х работу

Вариа н т результата н а принимающей стра ниц е БУдет прим е рно таким


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

'1 Untitled Page - Мicrоsоft Internet E~plorer


Fi ~ Edit View F.avorites TooIs не р

(ij Favocites

Методом межстраничной
обратной отсылки
получены данные

• Заголовок Это первая стрamща-истоЧЮIК


• Д8ЮIЫе прислшrа первая страюща
• Фамилия доцента: Снетков В.М.
• Обратная отсылка :инициирована свойством
PostВackUr!

Со оki е-н або ры

Куки-набор ы являю тся еще одн и м р аспростра н е нн ым способом


хране ни я и н форма ц ии н а ЮlИе н те. Они, подоб н о состояни ю в и да ,
также ВЮlючают в себя текстовую и нформацию , н о хра н ят ее н е в
скр ытых полях НТМ L- докумен та , а в н еболь ши х файлах, хр анящихся на
Юlие нте в специальн ой време нн ой папке ( ... \Те mр orагу l пtе mеt Files\ ). В
зависимости от верс ии броузера для каждо го сай та у Юl и е н та таких
файлов может бы ть до 20 с размером до 4 Кб каждый. Кл и е н т может
даже и н е п одозревать , что при вза и моде й ств и и с сайтом его броузер
ав томат ически при н имает и отсылает связан н ы е с ним куки .

Одн ако Юl и е н т имеет возмож н ость удалить куки, отключ и ть в броузере


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

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

шифровать сохраняемую в них информацию. Иcnользо вание куков


опирается на два объекта-свойства страницы Request и Response,
каждый из которых имеет коллекцию (набор) Cook i es типа
HttpCoo ki eCol l ection . Постynившие от клиента куки нужно
извлекать из коллекции Reques t . Cooki es, а отправляемые на

клиента новые данные для их сохранения в куках необходимо добавлять


в коллекцию Response . Cook ie s .

Коллекции Cook i es состоят из отдельных объектов-эюемпляров


класса Ht tpCookie , каждый из которых является словарем. При
создании объекта-словаря в конструкторе Ht tpCookie(st ri ng)
задается имя кука, под которым он БУдет адресоваться в коллекции.
Перегруже нная версия конструктора Ht tpCookie(st ri ng ,
str i ng) позволяет при создании имени кука определять и его

единственное значение .

Важным свойством объекта cookie является Ex p ire s, которое


определяет срок хранения куки-файла на ЮlИенте. Если броуэер при
соединении с сайтом обнаружит связанный файл с просроченным
сроком хранения , то он его немедленно уничтожит. Если это свойство
не установлено, то cook i e БУдет храниться в памяти , пока
пользователь не закроет броуэер. Для немедленного удале ния cookie
на клиенте с длительным сроком хранения нужно перезаписать в него

просроченную дату

Упражнение 8

В качестве прим е ра разработаем страницу, на которой значения


некоторых интерфейсных элементов ynравления БУдем хранить в
cook ie s .

• IJ$Добавьте к проекту страницу без отделенного кода с им ен ем


Coo kiesP agel . asp x и назначьте ее стартовой

Никакие элементы в режиме проектирования мы на странице


размещать не БУдем, а все создадим и настроим динам ически , чтобы еще
раз подчеркнyrь возможности программирования. В итоге код нашей
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

страницы бу,цет выглядеть так

<%@ Page Lапguagе= "С#" ValidateRequest="false" %>

<script nmat="server''>

11 Вынесли как поле для видимости в обработчиках


11 Инициализировать необязательно, компилятор сам справится
TextВox txtN аmе;
Striпg result = "";
iпt count = О;

protected void Page_Load(object sender, EventArgs е)


(
this.Response.Write("<h1 style='color: Rеd ;'> Испытание Cookies<lhl>''J

Labellabel = new LаЬеЮ ;


label Text = ''Введите ФИО:&пЬsр ;&пЬsр ;";
10 nnl. С о пtrо Is.Add(1a Ье 1);

tXtN аmе = new TextВoxO;


txtName.Text = "С н етков В.М.";
fопnl.сопtrоls.Аdd(txtN аmе);

fопnl.Сопtrоls.Аdd(пеw НtmlGепегk:Сопtrоl( 'Ъ г''));

Button Ьuttоп = new ВuttопО;


Ьuttоп.Теxt = "О тправить ";
fo пnl. С о пtrо Is.Аdd(Ьuttоп);

Ьuttоп = new ButtonO;


Ьuttоп.Теxt = "Сохр анить ";
fo пnl. С о пtrо Is.Аdd(Ьuttоп);
Ьuttоп.Сliсk += btnSaveClick;

Ьuttоп = new ButtonO;


Ьuttоп.Теxt = ''Восстанови ть '';
fo пnl. С о пtrо Is.Аdd(Ьuttоп);
Ьuttоп.Сliсk += btnRestoreClk:k;

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

fо пnl .Сопtrоls.Аdd( пеw НtmlGепегk:Сопtrоl('Ъг''));

Ь uttо п = new ButtonO;


Ь uttо п .Теxt = ''Удалит ь '';
fo пnl . С о пtrо Is.Аdd(Ь uttо п) ;
Ь uttо п .Сliсk += btnDeleteClick;

fо пnl .Сопtrоls.Аdd( пеw НtmlGепегk:Сопtrоl('Ъг''));

НурегLiпk liпk = пеw Hyp erLinkO;


fo nnl .Controls.Add(link );
11 Определяем и мя ЮJасса т екуще й страницы и qюрмируем гиперсCl
S triпg nameCurrentPage = this.GetTypeO.Name;
11 Разбиваем строку на части
S triпg[] parts = паme Сuгге пtР аgе.S рlit('_ ');
11 С р ав нив аем п ервую часть без учета регистра
if(Striпg.Соmраге(раrts[О], "CookiesPagel ", true) == О)
liпk.NаvigаtеUгl = ''Coo kiesPage2'' + ".aspx";
else
liпk.NаvigаtеUгl:= ''Coo kiesPagel'' + ".aspx";
liпk.Техt = "П ере й ти к" + liпk.NаvigatеU гl;

11 ОТЮJючаем сохранение состояния в и да всех элементов стр аниць


Disab ledViewS tate( fo пnl . С о ntro Is );

11 Изв лекаем об щее число посещений


HttpCookie cookie = this.Rеquеst.Сооkies["соuпt"];
if(cookie != пull)
(
iпt.ТгуРагsе(сооkiе.Vаluе , out count);
}
СО Шlt++ ;

11 Адресуемся к ОТЮJику и сохраняем об щее ч и сло посещений


cookie = this .Rеs р о пsе . Соо kies["соuпt "];
cookie.Value = СОШlt.ТоStriпgО;
11 Устанав л и ваем срок хр ане ния на клиенте: от текущего 1 день
cookie.Expires = DateTmle.Now.AddDays(l);
11 Отображаем сообщение на странице пользователя
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

result:::: 'Текущий запрос: " + соuпt.тоStriпgО;


}

11 ОТЮIючаем механизм сохранения состояния вида для всех элемеНТI


vою DisabledViewState(ControlCollection controls)
(
foreach (Control си! iп controls)
(
11 ОТЮIючаем сохранение состояния вида элемента
if (ctrLEnableVIewS tate)
ctrLEnableViewState:::: false;

11 Продолжаем опрашивать рекурсивно , если есть дочерние элем


if(ctrLControls != null)
Disab ledVIewS ta te( ctrL С о ntro Is);
}
}

11 Переопределяем обработчик генерации НТМL-вывода страницы


protected override void Render(HtmrrextWriter output)
(
11 Центрируем динамически созданные элементы управления
output. Render ВеgiпТаg(Н tmlТe xtWriterTag. С enter);
base.Render(output);
output.Write("<hr 1>');
output. Write(result);
output.RenderEndTagO;
}

11 Сохраняем данные в куке "oldInfo"


vою btnSaveClk:k(object serкler, EventArgs е)
(
11 Создаем словарь и заполняем текущей информацией
HttpCookie cookie :::: new HttpCookie("oldInfo');
11 Кодировать необязательно, направляется в файл
сооkiе[ ' 'naше'1 :::: txtName.Text;
cookie["clk:ks"] = СОШlt.ТоStгiпgО;
11 При соединяем к ответу
11 Срок хранения - текущий сеанс
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

11 cookie.Expires = DateTune.Now.AddYears(l);
this. Respo nsе. С 00 k ies.Add (соо kie );
}

11 Изв лекаем данн ы е из кука "oldlnfo "


уою btnRestoreClick(obj ect sender, EventArgs е)
(
11 ПОДЮI юч аемся к кукам поступивше го запроса
HttpCookieCollectioncookies = this.Request. Cookies;
11 Изв лекаем н уж ный словарь
HttpCookie cookie = cookies["0Idlnfo'1;
if(cookie != null)
(
11 Изв лекаем значения словаря
striпg пате ,clk:ks;
пате = cookie["name"];
clicks = cookie["clicks"];

11 Альтер нат ивный с ин такс и с


11 паше = cookies["0Idlnfo'1[''name'1;
11 clicks = cookies["0Idlnfo'1["clicks"];
11 Если готовим к отправке, то мож но ...
11 cookies["ok:llnfo"].Expires = DаtеТпnе .N ow.AddYears(l);

11 Безопасно отображаем сохране нны е з начения,


11 кодируя интер пр ет ируемые броузером символы
пате = SеlVег.н tmlErк:оdе( пате);
clicks:= Server. HtmlEncode(clk:ks);
result = "Сохр аненное ФИО:" + пате;
result += "; сохраненный запрос: " + clicks;
}
e~e
{
result = ''Не ч е го восстанавливать! ";
result += 'Текущи й запрос: " + соuпt.ТоStгiпgО;
}
}

11 Удаляем кук "count"


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

vою btnDeleteClick(object sепdег, ЕvепtAгgs е)


(
11 Удаляем кук количества запросов, посылая пр осроче нную дату
tшs. Respo nsе. С 00 k ieS[ "С ОШlt'1. Ехр ires =
DateTnne.N ow.AddDays( -1);
}
</script>

<html xmlns=''httр ://www.wЗ.огgl 19 99/xhtml'' >


<head nmat="server">
< title > Uпtitled Page</tide>
<lhead>
<body>
< fо пn kl ="fо пn1 " ruпаt= "sеrvег''>
<div>

</div>
</foпn>
<!body>
<lhtml>

Листинг Код страницы CookiesPagel.aspx

Для то го, чтобы пр одемонстрировать, что куки сохр аняются и пр и


п ереходе к д ругим страницам, создадим еще одну стра ниц у, совершен но

и де н тичную первой .

• ~Создайте в п роекте копию страницы CookiesPage1 .aspx и


пр исвой те ей имя CookiesPage2 . азр х
• ~Запустите первую страницу CookiesPage1.aspx и испытайте ее
р аботу совместно со второй стра ниц ей

Вид ст р аницы н а клиен те будет таким

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

~ Untitled Page - Мicrоsоft Inteгnet Exploгeг


FМ€ Edit View Favorites Tools Help

!±I Favorites
http:/~осаlrюst: 1157 j\NebSite6x/CookiesPage2.aspx

Испытание Cookies
ВвеДFПе ФИО: ICHeTKOB В.М.

Отправить Сохранить Восстановить

Удалить I
Перейти к CookiesPage 1.аврх

Те~запрос: 20
Local in1Janet

Проверка поддержки cookies клиентом

Механизм cook i es является очень удобн ы м , но неустойчивым ,


п оскольку может либо не подце рживаться броузером, л и бо пользователь
может эту подцержку ОТЮlючить. На этот случай разработчик может
п риме ни ть други е схемы сохран ен ия данных при межстра ни ч ны х
отсылках. Но п режде в сего такую про блему нужно обна р ужи ть.

Инфор мация о функциональности броузера ав томатич ес ки поступает на


сервер с каждым запросом пользователя и записывается в объект тип а
System . Web . Ht tpBrowserCapabil i t i es , ссылка на который

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

находи тся в свойстве Page . Request . Bro wser объекта страницы.


Эта ин<lюрмация ВЮlючает в себя тип броузера , его версию , подце ржку
на стороне Юlиента сценариев, стилей , фрейлюв , cookie, таблиц и
другое.

к сожалению эта июlюрмация свидетельствует только о потенциальных


возм ож ностях броузера, но никак не о том, как сконфигурирован
(настроен) броузер в данный момент. В такой ситуации у разработчика
имеется два выхода: положиться на присланную июlюрмацию и
считать, что в броузере эта функционально сть не ОТЮlючена, либо
выполнить до полнительные проверЮ1.

Что касается сооkiе·наборов, то при первом запросе страницы после


того, как мы Удостоверимся , что такая функциональность у броузера
имеется , можно сделать пробный ОТЮlИК с посылкой сооkiе·набора с
помощью метода Response . Redi rect () , а затем в поступившем

запросе попытаться прочитать его. Есл и такая попытка не удастся ,


значит подце ржка сооkiеs·наборов недостynна и нужно переЮlючать
логику выполнение страницы на д ругие методы сохранения

межстраничной инqюрмации.

Упражнение 9

• r;:;'в качестве иллюстрации к сказанному создайте страницу с


именем I sCookiesSuppo r ted . asp x и заполните ее

следУЮЩИМ кодом

<%@ Page L апguagе="С#" C lassN ame='1sCookiesS upported" Enab!eViewS ta

<script nmat="server''>

Ьоо! Coo kiesSupportedFlag;


iпt clicks = 1;

protected void Page_Load(object sender, ЕveпtAгgs е)


(
11 Создаем объекты по льзовательского интерфейса
11 Текстовая метка заголовка

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Labellabel := new LаЬеЮ;


10 nnl. С о пtrо Is.Add(1a Ье 1);
label Text:= "<h2> Подцерживаются ли Cookies?<Ih2 >";

// Кнопка Submit
Button suЬшit = пеw ВинопО;
fo пnl . С о пtrо Is.Add( s uЬ шit);
submit.Text:= "О тправить ";

// Горизонтальная ли ния
fопnl.Сопtrоls.Аdd( пеw НtrnlGепегk:Сопtrоl( "hr"»;

// Текстовая метка результатов


label = пеw LаЬеЮ;
10 nnl .С о пtrо Is.Add(1a Ье 1);

if (!this. I sPostВack)
(
// Проверяем функциональность броузера на nодцержку Cookies
CookiesSupportedFlag:= this.Request.Browser. Cookies;
if (CookiesSupportedFlag)
(
// Для дополнительной проверки пробуем отправить cookie
this.Rеsропsе.Сооkiеs[''tшр''].Vаluе := S tгiпg.Еmрty;
)

// this .Rеsропsе .Redirect(Request. Url ТоStгiпg());// Зацикливает

// Дублируем сохранение в состоянии вида


this.ViewState["clicks"] := сliсks . ТоStгiпgО;;
label Text:= ' Пробный запрос страницы ";
return;
}
else if (this.Request.Cookies[''tmp'1 != null)
(
// Поднимаем флаг nодцержки cookies
CookiesSupportedFlag:= true ;
)
else

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

CookiesSupportedF lag = false;

11 При ни маем решен и е, отку,ца извлекать и где сохранять данные


if (CookiesSupportedFIag)
(
if (t:his.Request.Cookies["clicks'1 != null)
clicks = int.Parse(this.Request.Cookies["clicks"].Value) + 1;
t:his.Response. Cookies[ "clicks"]. Value = clicks.ToS tringO;
11 Устанав л ива ем срок хр ане ния
t:his. Resp о nsе. С 00 k ies[ "clicks "]. Ехр ires =
DateTnne.Now.AddMinutes(1.0);
}
e~e
(
clicks = Со пvе rt.тоIпtЗ2(this.ViewS tа tе[ "с liсks "]) + 1;
t:his.VJewState["clicks"] = clicks.ToS tringO;
}

11 По казываем поль зователю количество щелчков и механизм xpaHf


label Text = 'За прос страницы NQ "+ clicks.ToStringO;
if (CookiesSupportedFIag)
label Text += "< br 1> Хранение в cookies";
e~e
label Text += "< br 1> Хранение в ViewState ";
}
</script>

<html xm1ns =''httр ://www.wЗ.оrgl 19 99/xhtml'' >


<head nmat="server">
<title>Untitled Page</tide>
<lhead>
<body>
< fо пn id="form1 " runat="server''>
</foпn>
<!body>
<lhtml>

Листинг Код страницы IsCookiesSupported. aspx для проверхи


поддержки Cookies

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Сооkiе ~ набору можно назначить обл а сть видимо сти в пределах саЙта.
В этом случае броузер будет следить за тем , при работе с какими
страницами отправлять на ни х куки , а на какие не отправлять. Так,
например , если кук " с1 i сk s" при записи пометить

Response.Coo kies["clk:ks"]. Path = "~lМуFоldе г";

то кук буд ет достynен только страницам папки MyFok:ler. По умолчанию


кук достynен любым страницам домена , как и , например , при установке

Rеsро пsе . Соо k ies["сlk:ks"]. D оmaiп:= ''mysite.ru'';

Перейдите ко второй ча сти ...

/ (
Сохранение данных в состоянии сеанса

Любой пользователь при первом обращении к приложению получает


свой сеанс , который выражается в вы д елении н е ю:порого объ ема
памяти на стороне сервера для хранения данных любого типа. Достyn к
этим совместным данным осуществляется любой страниц е й через
прuсоедuн енный к ней объект- словарь Sess i o n. З а счет этого можно
сохранять информацию на одной странице , а получать к ней достyn с
д ругой страницы.

При постynл е нии п е рвого клиентского запроса на объект страницы


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

ASP.NET генерирует идентификатор сеанса размером 42 байта . Э тот


идентификатор сеанса включается в отклик сервера и является
уникальным в пределах приложения. Если ни одна из страниц
приложения , к которым обращается пользователь, не записывает в
объект Session да нные , то броузер н е возвращает его в запросе серверу
Вместо этого сервер при каждом запросе генерирует новый
идентификатор сеанса и ВЮIючает его в ОТЮIик. Стоит только странице
записать какие- ни будь данны е в объект Sess i on , идентификатор
сеанса сразу за поминается броузерам и начинается обратный процесс.
Теперь уже броузер с каждым запросом начинает по сылаться на сервер
сохраненный идентификатор сеа н са, даже если в дальнейшем мы
пол н остью очистим объект Sess i on .

Когда клиен т присылает идентификатор сеа н са, сервер по н ему


ав томатически извлекает и з места хранения данные сеанса и заполняет
ими объект Session созданной страницы . После чего данные сеанса
становятся доступ ными в коде этой страницы .

Идентификатор сеан са может п ересылаться серверу с запросом двумя


способами:

1. с помощью сооkiе-набора с именем ASP . NE T Sessionld


2. С помощью включения в URL для клиентов , не поддерживающих
сооkiе·наборы (использование измененных URL· адресов)

Идентификатор сеанса можно п олучить как значение

Response . Cook ~ es [" ASP . NET SesslonID " ] пр и

формирова нии первого ОТЮIика, или Sess i on . Sess i onI D . всегда .


Но конкретн ое его знач е ни е нас , как пр ав ило , не интересует, п оскольку
процесс распознавания выполняется автоматически.

Да нн ые сеанса MOгyr сохран яться ASP.NET в одном и з трех мест на


сервере, о п ределяемых свойством Mode объекта Sess i on :

1. В о п еративной п амяти сервера внугри пр о цесса - текущего


домена п риложения (режим IпРroс · уста н овлен по умолчанию)
2. В оперативной п амяти сервера вне процесса в специальной
службе Windows п од назва ни ем ASP.NET State Servk:e (режим
StateServer)
,ее
В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

з. Вне процесса на жестком диске в базе данных SQL Server (режим


SQLServer)

Состояние сеанса уграчивается в следующих случаях:

1. Пользователь закрывает и вновь запускает броуэер


2. Пользователь получает доступ к приложению через д ругой
броузер
з. Из~ за простоя сеанса больше определенного времени по причине
отсугствия запросов от клиента (по умолчанию 20 минуг)
4. Программист завершает сеанс методом Sess i оп . Abandon ()
s. Если сеанс создается внугри т е кущего домена , то при переходе
приложения в новый домен сеанс будет потерян

Сеанс является экземпляром класса

System . Web . SessionState . Ht tpSessionSta t e и может

частично управляться из кода. В таблице приведены некоторые


свойства и методы кла сса Ht tpSe зз ionSta te

Некоторые свойства и методы кла сса НttрSе ssiопStаtе

Член Описание

Количество элементов в коллекции текущего


Count
сеанса. Только для чтения

Булев флаг, показывающий способ хранения


IsCookieless и д ентификатора сеанса: в куках или в
модифицированном URL. Только для чтения

Булево значение, которое указывает, был ли сеанс


создан с текущим запросом. Если коллекция пуста
IsNewSession
или сеанс создан ранее , то возвращается false.
Только для чтения

Свойство (только для чтения) содержит одно из

значений перечисления SessionStateMode ,


указывающее способ хранения данных сеанса:

• о f f = О ~ сеанс не используется
• InProc = 1 ~данныесеансахранятсяв
памяти домена

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Mode • StateServer =2 - сеанс хранится в


специальной службе Windows под названием
ASP.NET State SelVice
• SQLServer = 3 - сеанс хранится в базе
данн ых SQL Server

• Custom = 4 - сеанс хранится на основе


н естандартного поставщика

Строка, содержащая уникальный идентификатор


SessionID
сеанса. Только для чтения

Максимальный срок простоя сеанса в минугах. Для


Timeout
чтения и записи

Abandon () Отменяет текущий сеанс

Add(str i ng Добавляет новый элемент в коллекцию сеанса.


па т е , objec t Допускается альтернативный синтаксис в виде
va l ue) индексатора

Clear() Очищает коллекцию сеанса

Re moveA l l ( ) Очищает коллекцию сеанса

Remove (з tr i ng Удаляет элемент данных из коллекции сеанса по


па т е) Юlючевому им е ни

Re moveAt (in t Удаляет элемент данных из коллекции сеанса по


index) Юlючевомуиндексу

Начал ь н ое состояние сеанса уста навлив ается в конфигурационном


файле web.config в секции <sessionState> . Настройки секции
<sess i onState> подцерживаются Юlассом

Sys tem . Web . Соn figura t i оп . Ses s i onSta teSe c t i on через


его свойства , но имена свойств в кофигурационном файле начинаются с
символа нижнего реrnстра. Вот некоторые наиболее важные и з них

Некоторые свойства SessionStateSecllon


Свойство Описание

Задает режим использования соо)

набора для пересылки


идентификатора сеанса.

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Определяется значениями
перечисления

Syste m. Web . HttpCookieMo

• UseU ri = О - никогда не
использовать сооkiе-наборь

включать идентификатор
сеанса в URL (в файле
wеЬ.сопfig допускаются
варианты синтаксиса:

cookieless= " UseUri "


или cookie l ess= "t rue

• UseCookies = 1 - всегд
использовать сооkiе-наборь

даже если броузер их н е


подцерживает или эта

функционально сть в нем


отключена. Этот режим
установлен по умолчанию.

Для неподцерживающих
сооkiе-наборы броузеров
Cookieless
да нные сеанса будуг теряты
по скол ьку идентификатор
сеанса возвращаться на cepl
н е будет
• AutoDetect = 2 -
наиболее надежный режим ,
котором сервер сам определ

возможности броузера по
подцержке куков и

автоматически применяет

нужной вариант п е ресылки


идентификатора сеанса
• UseDev i ceProfi l e
способ пересылки
идентификатора сеанса
основывается только на

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

потенциальной
функциональности броуэер(
п о п одцержке сооkiе- н аборс
но без учета возможн ости
фактического ОТЮJючения 31
функциональности
пользователем

Задает одн о из значений


перечислен и я

SessionStateMode.
указывающее способ хранения
данных сеанса:

• о f f = О - указывает, что
сеа н с не задействуется для
хранения данных. Такой pe>t
может существенно увеЛИЧ I

быстр одейств и е , ко гда


необходимости в сеансе нет
Mode • InProc = l -данныесеа
хранятся в памяти домена

• StateServer = 2- сеа l
хранится в специальной
службе Windows под назван ]

ASP.NET State Service


• SQLServer = 3 - сеанс
хранится в базе данных SQ I
Server
• Custom = 4 -сеа н с
хранится на основе

нестандартного постаВЩИКе

Устанавливают время простоя


Timeout
сеанса в м ин угах

Булева переменная , запрещающая


ASP.NET использовать постynиВl

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

от ЮIИента идентификатор сеанса


про с роченной меткой времени , а
генерирующая новый. Э ТО особеr
RegenerateExpiredSessionld важно при ВЮIюченном режиме

cookieles з= " true " , когда


и д ентификатор сеанса п е ресылае'
броузером в со ставе URL, КУда егс
может специально в строить

злонамеренный пользователь

Устанавливает имя идентификато


сеанса в соаkiе-наборе . По
CookieName
умолчанию используется имя

" ASP . NET Sess i onID "

При В ЮI юч е нном режиме cook ieless= "t rue " браузер


автоматичесЮ1 встр а ивает и дентификатор се а н са в URL всех
отно с ител ьных ссылок Э то же справ едливо и при автоматической
переадр есации на н о вую страниц у методом

Response . Red ~r ect ( " Относительны й адрес " ) с полным

ЦИЮlом. Для того, чтобы ука зать систем е, что идентификатор се а нс а


должен переда ваться секретным протоколом , нужно установить

Response . Cook ~ es [ " ASP . NET SesslonID " ] . Secu r e


t r ue ;

Прив едем пример использования сеанса.

Упражнение 10

• г;.:.=ОтредактирУЙте файл web.config приложения как показано


ниже

<?xml versio n="l .O" encoding= ''utf-8'?>


< со пfigш аоо n xmlns= ''http://schemas. microso ft.co m/. N etC о nfigшаtiо n/у2,
<system.web >
< соmрilatю п debug=''true'' />
<sessionState cookieless=''true '' regenerateExpiredSessionId=''true'' I
</system. web>

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</configuration>

Листинг Файл web. config с включенным режимом


Cookieless
• ~Добавьте страницу с именем Sess i o nCookieless . asp x
с совмеще нны м кодом, которую заполни те так

<%@ Page Language="C#" EnableViewState=''fulse'' %>

<script runat= "server''>

int clk:ks = 1;
const int тахСо!=2;
Htmrrable table;

protected void Page_Load(object sender, EventArgs е)


{
string[] headers = {
// Им ена свойств секции sessionS tate
"Cookieless",
' 'Моdе '',
'Tnneout",
''Regenera teExp ired S essio nId ",
"C ookieName ",
// Д опо л ни тельна я информация
"SеssiопID",
"numRequest",
"сuггепtТlП1е "

};

// Создаем объекты поль зовательского ин терфейса


// Текстовая метка заголовка
Lab e!labe! = пеw Label();
form!. С о ntгo ~. Add(labe 1);
LзЬеLТеxt := "< h2 > И с польз ование сеансов Session<Ih2>";

if (!IsPostВack)
{
// П олучаем всю информацию о параметрах конфигурации

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

5 ystem Сопfiguгаtioп.Сопfigшаtiоп соnfig;


сопfig =
5ystеmWеЬ . Сопfiguгаtiоп.WеЬСопfigша tionМаnagег.
О репWebC о пfigша tiоп( trus. Req uest.Ap р lica ПО ПР ath);

11 Объявляем ссылку на объект 5еssiопS tаtеSесtioп


5 ystem Web .Сопfiguгаtioп.SеssioпS tаtе5есtiоп sеssiопS tаtе;

11 Поиск элемента <session5tate> в элементе <system.web >


sеssioпStа tе = (5 ystem Web .Сопfigшаtiоп.SеssiопS tаtеSесtiоп)
со пfig. Get5 еспо п(@ "sуstеm.wеЬ!sеssiопS tаtе'');
IlsеssioпStаtе.Тпnеоut = ТпnеSрап.FгоmМiпutеs(l);

11 Формируем таблицу и сохраняем ее в сеансе


table = new Htm!ТableO;
taЫе.Вогdег := 1;
for (iпt i= О; i < hеаdеrs.Lепgth; i++)
(
11 Создаем строку
HtmrrableRow row = пеw HtmIГableRowO;
ta Ь Ie. Rows.Add( row);
11 Создаем ячейки в строке
for (iпt j = О; j < тaxCo l; j++)
(
HtmIГableCell co l = пеw HtmIГabIeCell();
гow.Cells.Add( col);
if U == 0)11 Левый столбец
{
coL lnnerHtml = headers[i] + ":&nbsp;";
coLAlign = ''right'';
coLBgColor = ''YeUow'';11 Цвет фона
}
else 11 Правый столбец
(
11 При меняем методику отражения типов
5ystemType type = typеоf(Systеm.WеЬ.Соnfigшаtiоп .
5essionS tatеSесtioп);
11 Извлекаем публичное свойство по его имени
5ystеmRеt1есtiоп . Ргореrtуlпfо property =

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

type .GetPro perty(headers[iJ);


if (property!= null)
{
coLlrmerHtml = "&nbsp;";
// Извлекаем з нач ение свойства из зюемпляра ЮI,
coLlrmerHtml += property.GetGetМethodO.
Invoke( sessio nState, null). ToStringO;
}
else
{
// Маркируем ячейку, чтобы по том н айти
coLID = headers[i];
}
coLBgColor = ''#CCFFFF'';// Цв ет фона
}
}
}

// Сохраняем информацию в сеансе при первом запросе


t:his.Session.Add(''table'', ыые;;
t:his.Session["clk:ks"] := clk:ks;
}
else
{
// Извл екаем информацию из сеанса при каждой обратной
table = (HunIГab!e)this.Se55ion('\ab!e"];
clicks:= (int)trus.Session["clicks'1;
// Сохраняем новое знач е ни е
t:his.Session["clk:ks"] := ++clicks;
)

// Добавляем таблицу на форму


югml.сопtгоkАdd(taые );

// Корректируем таблицу
«Н unIГab!eC е ll) Р age .F ind С о пtго ~"S е55 io nID')). 'пneгН tnnI =
"&nbsp;" + trus.Session.SessionID;
«Н unIГab!eC е ll) Р age .F ind С о пtго ~"numReq ue5t')). 'nлег Н tnnI =
"&nbsp;" + clicks.ToStringO;

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

((Н tmП'аЬ!еС е ll)P age .F ind С о ntro Ч"сurrепtТm1е ')). IппегНtml :=


"&nbsp; " + DateTnne.Now.ToLocafГnneO;

II Новая строка НТМL


HtmlGenericControl Ьг := new HtmlGenericCo ntrol();
Ьг.lпnегНtmI := "< Ьг 1>";
forml.Controls.Add(br);

II Кнопка Submit
Вuttоп submit := new ВuttопО;
forml. С о ntro Is. Add(sub mit);
submit.Text:= "О тправить ";
}
</script>

<html xmIns='huр://www.wЗ.or!j'1999/xhtml" >


<head runat:= "server''>
<tide > Untitled Page</tide>
<lhead>
<body>
<form id :="forml " nmat="server" stylе:=''tехt-аligп: center;">
</fоПll>
</body>
<lhtml>

Листинг. Код страницы SessionCookieless . aspx

К л и е н тский результат бу,цет таким


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

'!i LJntltled P.age - MICrosoft Internet Explorer - -....;...;

Использование сеансов Session


Cookieless: UseUri
Mode: InProc
Timeout: 00:20:00
IRegenerateExpiredSessionId: Тте

CookieName: ASP.NET SessionId


SessionID: 44vwbovkkdykyazyxi445png
пшnRеquеst: 7
cmтentTime: 11.04.2008 1:38:42

Отправить

ГГГ ~ LОС3IltПfiеt

Обратите внимание, что идентификатор сеанса встроен в URL при


знач ении пара метра Cookieless= " UseUri " . Отметьте также, что
ин терфейс ная часть страницы пустая - все создается динамичесЮ1.
Ча сть выводимой в табли ц у ин<lюрмации м ы доб ы л и и з объе кта класса
SessionStateSect i on , который создается по настр ойкам
конфuгурацuонного файла. Для более лаконичного кода мы прим е ни ли
методику отражения типов , позвол ившую опосредованно вызывать

свойства объекта. В сессиях можно сохранять объекты любого типа , а


н е только строЮ1. Но при извлечении и х нужно ЯВНО приводить К
соответствующему типу.

Сохранение данных в состоянии приложения

Состояние приложения - это область па м яти сервера, выделяемая при


за п уске прилож е ния для хранения глобал ьных данны х, достynны х с
любой страницы приложе ния . На эти да нные в каждой странице
ссылается объект- словарь Appl ica t i on тип а
System . Web . Ht tpApplica ti onState . Как и при состояниu
,ос
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

сеанса, состояние приложения хранит данные в виде объектов , поэтому


при их и звле чении н еобходимо явное преобрйзование типов.

Данные состояния прилож ения существуют в течение всего периода


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

Упражнение 11

в качестве примера п остроим две страницы, в которых подсчитыва ется


общее число посещений сайта с момента запуска при ложения .

• ~Добавьте к при ложе нию файл GlobaLasax и заполните его так

<%@ Аррliсаtюп Language="C#" %>

<script runat= "server''>

void Applk:ation_Start(obj ect se nd er, EventArgs е)


{
this.Applicatio n["clicks"] = (int)O ;
)
</script>

Листинг. Файл Global.asax


• ~Создайте страницу без отделенного кода с им ен ем
Appl i cat i onStatel . азр х , на знач ьте ее стартовой и
заполните так

<%@ Page Language="C#" %>

<script runat= "server''>


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

protected void Page_Load(object sепdег, ЕvепtAгgs е)


{
11 Читаем без проверки - инициализирована в g!obaLasax
iпt visit = (iпt)this.Аррliсаtiоп[ "сliсk s"] + 1;
11 Обновляем состояние nриложения с блокировкой
this.Application.LockO;
this.Application["clicks'1 = visit;
this.App lica Поп. UnLoc kO;

11 Создаем текстовую метку


Labe!labe! = пеw Label();
form!. С о ntгo ~. Add(labe 1);
IabeL Text = "Се годня вы посетили нас в "
+ visit.ТоS tгiпgО + " р аз ! < Ьг 1>";

11 Создаем гиnерссылку
НурегLiпk link = new HyperLinkO;
form!. С о ntгo ~. Add(link);
link.NavigateUr! = "~/AppticationState2.aspx";
link.Text := ' 'На другую ст р аницу. .. ";
}
</script>

<html xmIns =' huр ://www.wЗ.ог&,! 999/xhtml" >


<head runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="form1 " nшat="sе rvег ''>
</fопn>
</body>
<lhtml>

Листинг. Файл ApplicationStatel.aspx


• IJ$Создайте копию для страницы ApplicationS tate1 .aspx с именем
Appl i cationState2 . азрх и поменяйте в ней 2unерссылку
на App l icat i onS t a te 1 . азр х, чтобы страницы ссылались
друг на друга

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• ~Запусти те само приложе ни е н есколько раз и пощелкай те п о


сс ы лкам чтоб ы убедиться , что с ч ет чик количества визи тов
увели ч ивается

I 11 Untitled Page - Мicrоsоft Internet Explorer


Fie Edit View Favorites ТОols Help
*' Back т .. т Ii) @] &J I ~ seaгch t±I Favorites
Address http:/~ocalhost 1

Сегодня вы посеТИJШ нас в 7 раз!


На дрyryю страющу ...

гг Г ~ Loc" in1Ianet

• r;.:.=в п ан ели задач ни жн ей части экрана щелкн ите правой


кнопкой мы ши н а п икго грамме тестового сервера и остановите
е го командой Stop

• ~H OB b за п устит е стра ниц у Ар рlicаtiопS tа tе l .аsрх, чтобы


убеди ться, что счетч ик сброс и лся в н ач аль н ое з н аче ни е

Хранени е данны х в статич ески х п е р е м е нны х

приложения

Для увел ич е н ия масштабируемости приложе ни е загружается в п амять


сервера в в и де м н ожества копий (п ул а ). Каждый эюем п л яр масса
приложен ия имеет свой н абор да нн ых и только объект-ти п хр а н и т все
методы и стат и ч еСЮ1е да нны е в единстве нн ом эюем п ляре. Если в фа йле
GlobaLasax объявить об щедоступные ст а тические п оля, то в н их мож н о
хра нить да н н ые, котор ы е бу;цуг в и дим ы ч ерез и мя масса приложен ия из
любо й стра н и ц ы саЙ та. Но при э т ом нуж н о явно о п редел и ть в
директиве @ Appl i cation файла GlobaLasax параметр ClassName .
в котором указывается и мя кnacca приложения для последую щего

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

обращения из кода страниц.

При изм е н е нии в страницах глобальных данных класса приложения


механизм ав томатиче сюй блокировки отсугствует. Поэтому нужно
пользоваться встроенным в язык С# оператором 1 oc k. чтобы на время
позволить воздействовать на переменную толью со стороны одного
потока. Такой подход удобен тем , что мы можем обернугь сохраняемые
да нные в статические свойства и на з начить для них юнтролирующий
юд, преж.це ч ем сохранять их в памяти сервера. Мы можем объявлять
статические п е рем енные для хранения объектов любого типа и для
доступа к ним явных преоБРQ30ваний типа не потребуется.

Упражнение 12

Прив едем пример, в котором юличество ви з итов всех пользователей , а


также список файлов текущего физичесюго корневО20 каталога сервера
будем хр анить в ст атических переменных класса прuложения.

• г;.:.=ОтредактирУЙте код файла GlobaLasax следующим образом

<%@ Аррliсаtюп Language="C#" ClassName="MyAppClass" %>

<script runat= "server''>

// Список файлов
private static string[J fileList;// Базовое поле
// Общедоступное статичесюе свойство для обертки базового п
риыic static string[] FileList
{
get
{
// За пол нить список только при первом за пр осе
if (fileList == null)
(
fileList = System. IO .Directory.GetFiles(
Н ttpC onte xt. С urrent. Req uest. Р hysicalAp р licatio пР ath);
}
геtшп fileList;
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

}
}

// Число посещений
private static int visit = 1;// Базовое поле
// Общедоступное статическое свойство дл я обертки базового п
риыic static int Visit
{
get { return visit; }
set
{
lock (typeof(int))// Контейнер обеспечения синхронизации r
{
visit = value ;
}
}
}
</script>

Листинг. Код файла Global.asax со статическими членами

• ~Добавьте к п риложению ст р аницу без отделенно го кода с


име н ем AppClassstaticMembers . asp x и назначьте ее
стартовой
• r;:FЗаполните страницу AppClassStaticMembers.aspx следУЮЩИМ
КОДОМ

<%@ Page Language="C#" EnableViewState=' 'fulse '' %>

<script runat= "server''>

protected void Page_Load(object sender, EventArgs е)


(
// Заголовок
Label title = new Label();
form1. Controls.Add(tit1e );
title.Text = "< Ы style='text-align: center; color: Red'>"
+ ' Использование статических"
+ " полей класса приложения < Ih2>";

;О,
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

// Число посещений
Labe! visit = new Label();
form1. С о пtго ls. Add( vis it);
int clicks = MyAppClass.VlSit;
visit.Text = "< Ь >Количество посещений: "
+ clicks.ToStringO + "</Ь>";
MyAppClass.Visit = ++clicks;

// Горизонтальная черта
foгm1. С опtгоls.Аdd(пеw HtmlGenericContro~ ' 'hr ') );

// Извлекаем и готовим список файлов


// текущего каталога приложения
StringВuilder builder = new StringВuilderO;
builder.Append("<ol>";
// Счетчик дл я сокращения листинга
int count := О;
const int maХСОШlt := 5;
foreach (string file in MyAppClass.FileList)
{
if (++count > maХСОШlt)
break;

string str;
//int pos = file.LastIndexOf(@'\');
//str = file.Sub string(pos + 1);
// То же самое
str = System.IO.Path.GetFileName(file);
builder.Append("<li>" + str + "</li>');
}
build er. Ар pend("</o 1> ',;

// Готовим текстовую метку для отображения списка


Labe! fileInfo = new Label();
forml. C ontrokAdd(filelnfo );
fileInfo.Text = builder.ToStringO;

// Горизонтальная черта
foгm1. С опtгоls.Аdd(пеw HtmlGenericContro~ ' 'hr ') );
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

// Создаем дес криптор центрирования кнопки


HtmlGenericControl center = new НtmlGепегiсСопtroЧ "се пtег'') ;
forml. С о ntro Is. Add( center);

// Кнопка Submit добавляется в контейнер центрирования


Вuttоп button = пеw ВинопО;
button.Text = "Отправить ";
center. Controls.Add(button);
}

// Переопределяем обработчик рендеринга


protected оvепidе void Rerкler(HtmIГextWriter writer)
(
// Сгенерировать основное
base. Rerкler(writer);

// Добавить в конец еще НТМL-вывод


// Настроить атрибугы БУдущего дескриптора
wгitег.АddАttributе(НtmlТехtWгitегАttributе.Аligп, "Ce nter'');
writer.AddS tyleAttribute(H tmIГe xtWriterS tyle .С о Ior, "Blue '');
// Создать дескриптор
writer.RenderBeginTag(HtmlТextWriterTag.H2);
// Пи сать внугрь де скриптора
wгitег.Wгitе('ЩелкаЙте на кнопке и наблюдайте счетчик nocel
// Закрыть де скриптор
writer.RenderEndTagO;
}
</script>

<html xmIns =' huр ://www.wЗ. or!j'1999/xhtml" >


<head runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nmat="server''>
</fonn>
</body>
<lhtml>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Листинг. Код страницы AppClassStaticMembers.aspx


• ~3апустите страницу и убедитесь , что все работает и
объявленные в классе прилажения статичеСЮ1е члены сохраняют
свои значения даже при ОТЮlючении юшента от сервера до тех

пор , пока сервер остается запущенным

• ~ панели задач нижн е й части экрана щелкните правой


кнопкой мыши на пиктограмме тестового сервера и остановите
его командой Stop
@F
з,7N===~ЕС========~
1257

• ~HOBЬ запустите страницу AppClassStaticMembers.aspx, чтобы


убедиться, что память сервера очистилась и счетчик сбросился в
начальное значение

А сейчас мы убедимся, что при модификации любого файла


приложения , включая web.config, оно автоматически перекомпилируется
при первом запросе и загружается в новый домен.

• ~e нарушая кода, модифицируйте любой исходный файл


приложения , например , введите пробел после точки с запятой в
конце любой строки (или доб авьте п устую строку) и сохраните
изменения

• ~3апустите приложение и убедитесь, что счетчик сбросился за


счет загрузки прилож е ния в новый д омен

Интерфейс клиента для данного примера БУдет таким


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

11 Untitled Page - Мicrоsоft Internet Explorer


File Edit View Favorites ТОols Нф

Ad::tess f> Go

Использование статических
~

полеи класса приложеlПlЯ

Количество посещений: 7

1. IsCookiesSupported.aspx
2. ViewSta1eList.aspx
3. DisplayViewSta1e.aspx
4. GlоЬШ.asах
5. НiddenFieldTest.aspx

Отправить

Ще.тш:айте на КНОIШе и
наб.rnoдайте счетчик посещеlВlЙ
Local in1Y.rtet

Рассмотренные в данной теме способы хранения данных относятся, в


основном , к внугрипроцессным , так как со храняются в оп е ративной
памяти сервера или п ередаются по канал ам связи на ком пьютер клиента

для вр еме нного хранения. Другие методы хранения информации в


службах сервера, включая базы данных и файлы , являются
внепроцессными , поскольку не зависят от среды исполнения ASP.NET.
В.М. СН"",,,В

~T I@) ГJ I

С не т'0$ (
-
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Основы ADO.NET
Поставщики данны х. Класс Соnnесtloп. Строка соединения .
Подключение к БД и тестирование соединения . Организация пула
соединений. Классы Comrrnnd и DataReader. Метод
SqК::оmmaпd . ЕхесutеRеаdегО.Обработка одного результирующего набо р а
данных SqlDataReader. Обработка множественного результирующего
на бора данных SqlDataReader. Метод SqlCommand.ExecuteScalarO.MeToA
SqК::оmmaпd . ЕхесutеNопQuегу().Атаки на базу данных внедрением SQL.
Вызов хранимых проц едур. Тра н закции . Точки сохранения для отката
транзакции. Фабрики поставщиков.

Файлы к лекции Вы можете скачать здесь скачать:

http://o и. intШ . ruld epartment/intemet/p rasp net/ 11 / 11.пр

Базы данных - это хранилища структурированных данных, с которыми


удобно работать. СУБД - это программное приложение, извлекающее ,
отображающее в у,цобном виде и модифицирующее структурированные
данные . Чаще всего применяются реляционные базы данных .
Библиотека .NET Fгашеwогk включает свою собств е нную технологию
доступа к данным ADO .N Ет. В н ее включены массы ,
обеспечивающие соединение и обработку данных как в локальных, так
и в Web-приложениях. Причем код приложения остается почти
одинаковым .

Поставщики данных

Важное место в архитектуре ADO.NET занимают поставщики данных (


data ргоvЮег ). О ни являются универсальн ыми посредниками между
источником данных и приложением. В состав одно го поставщика входят
следующие массы ( используются обобщенные и мена ):

1. Connection используется для установки соединения с

источникам данных
2. Coтmand - используется для выполнения команд SQL и
хранимых процедур
з. DataReader - предоставляет быстрый доступ только для чтения
к извлеченным данным

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

4. OataAdap t e r - этот масс решает две задачи:


о наполнение DataSet ( набор данных) инф:Jрмацией ,
извлеченной из источника данных
о сохраняет изменения , выполненные в Da taSe t

ADO.NET содержит набор специализированных поставщиков дл я


различных источников данных. Каждый поставщик да нных имеет
специфическую реализацию массов Connect i on , Command.
Оа taReade r, Оа taAdap t e r, оптимизированных для конкретных баз
данных. Например , если нужно подмючиться к базе да нны х SQL SelVer,
то используется масс SqlConnect i on .

Библиотека .NET Framework содержит четыре типа готовых


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

1. SQL Server
Поставщик
2. OLE DB
Поставщик
з. Поставщик Oracle
4. Поставщик ODBC

Для других типов данных разработчики могуг либо создавать свои


поставщики , либо приобретать их у сторонних организаций. Выбирая
масс поставщика , нужно сначала попытаться найти р одного
поставщика для данного источника данных. Если это невозможно, то
можно воспользоваться поставщиком OLE DB при условии, что
существует д райвер OLE DB для этого источниКQ данных.

Технология OLE DB ADO, поэтому


существует уже много лет как часть
большинство распространенных источников данных ( SQL Server,
Oracle, Access, MySQL и т.д.) предусматривают драйверы OLE DB.
Наконец , можно использовать поставщик ODBC в сочетании с
драйвером ODBC, поскольку это самая старая технология доступа к
данным, но производительность такого подмючения может быть очень
низкой .

Примен ение специализированных поставщиков может потребовать


изменения кода приложения при переходе к д ругому типу базы да нны х .
Но эти изменения будуг незначительными , поскольку поставщики
различаются только до уровня набора данных DataSet, а далее код

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

обработки н е зависи т от типа источника данных . И то , если кодировать


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

П риложение .NET

\
I
Неизменяемый уровень

Код Обработки и интерфе йс а

I
1
f Н абор данн ых DataSet
I

I Поста вщ ик
SQL Server
Поставщ ик
OLEDB
Поста вщ ик
Oracle
I
П остав щи !\
ОDВС
I
~
- - - - - -- - -- - -I
Источник данных (БД)

Та бл и ца I Таблица I • • • Табл иц а

Кла сс ы ADO .NET группирую тся в н ескол ьки х простр анства х имен:

1. Sys t em . Оа ta - содержит Юlючевые контейнерные МЙССЫ ,


модели рующи е сами данн ы е. До полни тел ьно содержит Юlючевые
интерфейсы, реализуемые объектами да нны х, ос н ова нн ыми на
соединениях

2. Sys t em . Data . Common содерж ит баэовые МЙССЫ ,

наследУемые массами п оставщиков

з. Sys t em . Оа ta . OleDb - В Юlючаю т поставщиков дл я источников


данн ы х OLE DB
4. Sys te m . Data . SqlCl i ent ВЮlючают п оставщиков дл я
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

источников данных SQL Server


S. Sys t em . Data . Or acleCl i en t В ЮIюч ают постав щиков дл я

источников данных Oracle


б. Sys t em . Data . SqlTypes содержит структуры ,

соответствующие родным т ипам данны х SQ L Server. Э ти ЮIассы


не яв л яю тся необходимыми, но в силу их с пецифичн ости
оп тимизируют достyn К данны м SQL Server
7. Sys t em . Data . Odbc - ВЮIючают поставщиков для и сто чни ко в
данн ых оовс. Операцион на я система Windows имеет д райв еры
оовс для всех в и дов источ ни ков да нных, которые
кон фигурируются в панели ynравления ПускlНастройкаlПан ель
ynравления/АдминистрированиеlИсточниЮ1 да нны х (оовс)

("1 ООВС Data воигсе АdmlПlstгаtог

User DSN I Sys1em DSN I File DSN Drivers ITrscing l iXmnection Pooling I Мои1 1
ОD8С Drivвrs Ihal ше inslalled оп уош syз1ет

Yersion Сот м
Driver da Microsoft рага arqurvos te:.1o ("'М; " .csv) 4.00.6200.00 Мiсrоsоft Corporali ,
Driver do Microsoft Ассезз ("'.mdb) 4.00.6200.00 Microsoft Corporati,
Driver do Microsoft d8 ase ("'.dbf) 4.00.6200.00 Microsoft Corporali ,
Driver do Microsoft Exc:el("'.xls) 4.00.6200.00 Microsoft Corporali ,
Driver do Microsoft Paradox r,db) 4,00,6200,00 Microsoft Corporati ,
Driver рша о Microsoft Yisusl FoxPro 6.01.8630.01 Microsoft Corporali ,
Microsoft Access Driver (".mdb) 4,00,6200,00 Microsoft Corporati ,
Microsoft Access-Treiber (".mdb) 4.006200.00 Microsoft Corporali ,
Microsoft dB~se Driver (*,db~ 4,00,6200,00 Microsoft Corporati ,
Microsoft dBase YFP Drrver (".db~ 6.01.8630.01
'" '~ ~ ~"" O ~ ~~T .~;h~ ."'rJ ,"," AnnC'-'"n ~ ~::~~~~~ ~~~~i11

Аn ОDВС driver allows ODBC-еп аbIе d programs to get inlorma1ion Irom
ОDВС data зошсез. То install пе .... drivers, use the drivers setup program

ОК Отм ена Принен и т Справка

Класс Connection

ЭТОТ ЮIасс устанав л ива ет соеди н ени е с и сточником данных, к которому


мы хоти м ПОДЮIючиться, чтобы выполнить с данными каЮ1е-то
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

действия. Свои основные свойства и методы КIlacc Connec ti on


реализует от наследуемого интерфейса IDbConnection .

Строка соединения

При установке соединения требуется строка соединения , которая


представляет собой список пар имя =з начение , разделенных точкой с
запятой. За ИСЮlючением небольших различий, ст рока соединения
содержит несколько атрибугов, необходимых почти всегда (порядок
следования атрибугов значения не имеет):

1. Сер вер , на котором находится база данных. При выполнении


упражнений мы будем обоснованно полагать , что наши
приложения ASP.NET и сервер базы данных находятся на одном и
том же компьютере, по этому вместо имени компьютера будем
использовать nceBdOHUMl ocalhost
2. База данных, к которой надо ПОДЮlючиться. Мы будем
использовать готовую учебную БД No r thw i nd , которая
инсталируется по умолчанию с установкой SQ L Server 2005
з. Атрибуг ауг е нтификации (1оgin). Мы не БУдем использовать имя и
пароль, а будем ПОДЮlючаться к БД как текущий пользователь
системы

Ниже представлены примеры строки соединения для ПОДЮlючения к БД


Northwind на текущем компьютере

При меры строки соединения

Источник данных Строка соединения

SQLServerс string connectionSt ring = " Data


использованием Source=localhos t ; In i ti аl
интегрированной Са talog=Northwind ;" + " In tegra ted
безопасности Secur i ty=SSPI ";
SQL Server с
использованием
string connectionSt ring = " Data
учетной записи (
Source=localhost ; Initial
id=sa -
Catalog=Northwind ;" + " user

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

system Catalog:Northwind ;" + " user


admin i s tra tor i d:sa ; pas sword:xxx " ;
)

Используется
п оставщик O LE
DВдля
П ОДЮlюче ни я к БД
string connectionSt ring = " Da t а
Sa l es типа
Source=localhost ; Initial
O racle ч ерез
Catalog:Sales ;" + " user
драйвер MS DAORA
i d=sa ; password= ; Provider=MSDAORA ";
OLE DB с

п равам и

адм и нистратора и

п устым п аролем

П ОДЮlюч е н ие к БД
Access . С и мвол string connectionSt ring =
"@" требуетот " Prov i der=Microsoft . Je t.OLEDB.4 . 0 ;"
ком пи лятора @" Data
интер п рет и ровать Source=C : \DataSources\Northwind . mdb "
строку буквал ьн о

Строку соединения можно указать в конструкторе п ри создании объекта


Connection ил и в методе Connection . Ореп () . Строку
соединения можн о п оместить н е в код страни ц ы, а в конфи2урационный
файл wеЬ.сопfig

<?xml vеrsЮ п="l .О'?>


< сопfigшаtioп>
< соrmес tiопStгings >
<add name="N orthwind" сопnесtiопString= ' 'Dаtа Sошсе=loсаlhоst;
lпitial Catalog=Northwind; Integrated Security=SSP I" />
</сопnесtiопStгings >
<system.web>
</system. web>
</сопfigшаtioп>

Листинг Страха соединения в lCонфигурационном файле


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

в любое вр ем я в коде стра н иц ы можн о и звлечь эту строку соединения


по ID - имен и из коллекции следую щим образом

striпg connectionString = WеЬ Со пfigurа tЮпМапа gе г. Со nnес tioпS tгings [ ''N orthw

Листинг Код извлечения строки соединения из

конфигурационного файла

П одключ ени е к БД и тестиро вани е со ед инения

П осле установки
SQL Server 2005 н ужн о убед ит ься , что служба
SQLServerAgent ВЮlюч ен а в р ежим Auto . ЭТО мож н о сделат ь ч ерез Пускl
НастройкаlПан ель управле ни я/Адми н истр и рова н ие/Службы

с Пуск
" ••
См ,.. Вру'fffЮ LOCi
пауgа Работает Вру'fffЮ LOCi
Re" Р азре шае" Вру'fffЮ LOCi
Е. 5зvе::; ilst, , Вру о..ную Сос<
Работает Аюо Сос<

В се зада си Зld Play У граВ!lЯЕ', , Работает Авто


RSYP Обес:neчи,. Вруо..ную LOCi
06 н.::еить Server (5Q" P roYi ~
s., Работает Авт о LOCi
Server АсЬ " ЕпюЬ il" ОТКЛЮ чeн:J LOCi
Свойства Se rveг Ат " 5Lpp1es о" Вру'fffЮ LOCi
Server вro .. P roYi~ 5" ОТКЛЮ чeн:J LOCi
Сгра ЕКа
Server Int, .. ProYi des , Работает Аюо Сос<
S€rver Re." LOCi

I
:E:~~:sru~cIo О,. Pl!
ProYi~ Вру 'fffЮ LOCi
d"
tFCfm 5,. Работает Авто LOCi
rnt;jpr I
~
с вой ств

Пр и ведем простой п ример установки соединения с БД N o r t hw i nd.

С п особ 1

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• IJ$Создайте командой Website/Add New Item новую страницу


TestConnection.aspx без отдельного файла п оМ ержЮ1
::;;_ _ _ __
А<1<1 ",",VJ Itpm - c'\Ch~" R()nk\WFА\дSP NFT? 0\7) OcHORh' ДГЮ.I\FТ\W"hSitр7 - .1J~

I...-rpl""'"
[;; о:::


lImIiIIIII
D
м.,,:е- ""9"
[!j]
_ с_

CCn'rol
~
КТf.1.. ""9"
!jj]
W еЬS.п~е
~
С",,,
t!JI
stj i< SCe" t

~
C~,

"«J I Ea~ ",


-
~
crn~gJ a ~I ",
~
xм.F, '" хм.
illJ
Scho tm
~
То" Fil>
3'Ji
R 0ЮU1:0 ;01..

;.
ij
SQ.- о..:..Ь=

IНJ
-~, i.I\I I[!r" ~ ~
lf.jJ
Dазset 5Im M~ M:tJl:e I'JOO \1\5(r"" Не е _,
J5Cf\J~ ""
I-I.rde.. '.т

[j::l"
Iд form for Wob 4F\'ЬЖn'
~
-"'" ~. ~ ф1 jjJ

,"w IT.ЫC""""",,trn <ьр'


L~ : IVisrnlС, iJ г ~lace с сОэ n "'1R ае fi.,
Г Select rrвster IВ'J"

• ~ ереведите стра ниц у в режим Design и добавьте из ВЮJaДЮ1


- =<:eI I
I

Standard элемент Label с именем lbl 1 n fo


• ~ режиме Design двойным щелчком н а клиентской области
страницы создайте обработчик Pag e Load () в блоке скриптов ,
который зап олните так, чтобы общий код страницы был
следУЮЩИМ

<%@ Page Language="C#" %>

<script runat= "server''>

protected void Page_Load(object sender, EventArgs е)


(
string соппесtString = System WеЬ.Сопfigшаtioп.WеЬСоnfigшаtiопr
СО nnectionS triпgs["N о rthwind "] . С о nnесtio nS tring;
SystemData.SqlClient.SqlCo nnection соп =
new S ystem.Data. SqlC lient. SqlConnection( connectS tring);

try

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

{
с оп.О р епО;
IblInfo.Text = "< Ь > Верс и я cepBepa:<Ib> "+ con.ServerVersion;
IblInfo.Text += "< Ь г />< Ь > Соедин е ни е: < Ib> "+ con.State.ToS t
}
catch(Exception е гг)
{
IblInfo.Text = "< Ь > О ши бка чтен и я базы данн ы х.<Ib >";
IblInfo.Text += err.M essage;
}
finа Пу
{
con.CloseO;
IblInfo.Text += "< Ь г />< Ь > Тепе р ь соедине ни е: < Ib> ";
IblInfo.Text += con.State.ToS tringO;
}
}
</script>

<html xmIns=' huр://www.wЗ.or&,1 999/xhtml" >


<head runat= "server''>
<tide>Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nшa t="sе rvег''>
<div>
<asp:Label ID="lb lInfo" runat="server" Text=''Label''> </asp:Label> <
</fonn>
</body>
<lhtml>

Листинг. Код страницы TestCo nnection.aspx


• u;..rп оместите в файл web.config строку соединения следУЮЩИМ
об р азом

<?xml versio n=''l .O'?>


<сопfigша tiо п>
<co nnectionStrings>
<add name=''N orthwind" connectionS tring =

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

''Data Sошсе=lосаlhоst;
Iпitia l Саtаlоg=Nоrthwiпd;
user id=sa; password=;" 1>
</соппесtioп S triпgs >
<system.web >
<compilation debug=''true''l>
</system. web >
</со nfigшаtiоп>

Листинг. Страха соединения в файле web.config


Теперь мы БУдем только извлекать в коде эту строку соединения в
наших дальнейших примерах, поэтому не заб ыв ай те , что она
существует и как выглядит!!!
• ~ыполните страницу, сделав ее ста ртовой , результат должен
быть прим ерно следУЮЩИМ
Версия сервера: 07.00.0623
Соединение: Ореп
Теперь соединение: Closed

Соедин е ни е как объект занимает опред еленные ресурсы, поэтому


открывать соединение нужно как можно позже, и освобождать как
можно быстрее. В прим ере предусмотрен блок f i nally на тот случай,
чт о даже при возникновении ИСЮJючения соединение все р авно будет
закрыто. Есл и это н е предУсмотреть, то в случае н еобработан ного
ИСЮJючения соединение останется открытым до тех пор, пока сборщик
м усора не уничтожит объект соп тип а Sql Connect i on .

С по соб 2

Другой подход гарантированного закрытия соединения - использовать


блок using . Оператор us i ng деЮJарирует, что мы используем
уничтожаемый объект в те ч ение краткого периода времени. Как только
выполнение блока us in g завершится, среда выполнения немедленно
освобод ит соответствующий объект, вызвав метод Di spose () . Вызов
этого метода эквивалентен вызову метода С1оs е () дл я объекта
Connection .

• IJ$Создайте копию страницы TestCormection.aspx и назначьте ей


;о,
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

имя ТеstСоппес ti оп l. аsр х

• Г;;:;=Н азначьте новую ст р ани ц у стартовой и зап олните ее


следующим кодом

<%@ Page Language="C#" %>

<script runat= "server''>

protected void Page_Load(object sender, EventArgs е)


(
string соппесtString = System WеЬ.Сопfigшаtloп.WеЬСоnfigшаtiопr
СО nnectio nS trings['N о rthwind '1. С о nnесtlo nS tring;
SystemData.SqlClient.SqlCo nnection соп =
new 5 ystem.Data. SqlC lient. SqlConnection( connectS tring);

using (соп)
{
соп.ОрепО;
IblInfo.Text = "< Ь > Версия сервера: < /Ь > "+ con.ServerVersion;
IblInfo.Text += "< Ьг />< Ь > Соеди н е ни е: < /Ь> " + con.State.ToSt
}

IblInfo.Text += "< Ьг />< Ь > Теnерь соединение: < /Ь> ";


IblInfo.Text += con.State.ToStringO;
}
</script>

<html xmIns='huр ://www.wЗ .or!j'1999/xhtml" >


<head runat= "server''>
<tide > Untitled Page</tide>
<lhead>
<body>
<form id="forml" nmat="server''>
<div>
<asp:Label ID="lblInfo " runat="server" Text=''Label' '> </asp:Label> <
</fоПll>
</body>
<lhtml>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Листинг. Код страницы TestConnectionl.aspx


• ~ыполните ст р аницу, результат должен бы ть прежним
Версия с ервера: 07.00.0623
Со единени е : Ореп
Теп е рь со единение: Closed

О рганизация пула соединений

При запросе любой ст р аницы, использующей БД, соеди н е н ие будет


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

Пул соеди н е н ий - это практика хранения приложением постоянного


набора открытых соединений, разделяемых междУ сеансами п ри
использован ии одно го и то го же источника данных . ЭТО позволяет
избежать бесконечно го создания и уничтожения соеди не н ий. При
организации пула вызов юшентом метода Оре n () обслуживается
непосредственно из доступно го пула без пов торно го откры тия
соединения. Когда юш ент освобождает соединение методом Close ()
или Dispose (), о н о н е закрывается, а возв р ащается в пул, чтобы
обслужить следУЮЩИЙ запрос.

Пулы автомати чесЮ1 ор ганизуются самими поставщиками данных


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

Пулы соедин е ни й SQL SelVer и Oracle используют механизм


пол н отекстового срав н е ни я. ЭТО значи т, что любое м и нимальное
изменение в строке соединении нарушает пул, даже если в ней просто
изменяется порядок па р аметров или добавляется п ростой пробел .
Поэтому лучше не п омещать строку соединении в код установЮ1
соединения, а сохранять в файле web.config, как это мы сделали в
при мере .

Пулы соедин е ни й можно настраи вать , добавляя соответствующие


В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

атрибугы в строку соединений. Параметры настройки пулов


соединений приведе ны в таблице

Парам етр ы настройки пулов в строке соединений

Параметр Описание

Максимальное количество соединений, разрешенных


для хранения в пуле (по умолчанию 100). Если
достигается этот максимальный размер пула , любые
Ма х Рооl
последУЮщи е попытки соединения становятся в
Si z e
очередь. Если время жизни соединения , установленное
параметром Connec t ion . Ti meout , истечет раньше,

чем ПОДО Шllа очередь в пуле , возникает ИСЮIючение.

Минимальное количество соединений , которое должно


Min Рооl оставаться в п уле (по умолчанию О). Это число
Si z e соединений будет создано в пуле при открытии первого
соединения.

По умолчанию t r ue . При значении false


Pooling
ОТЮIючается механизм пула

. Устанавливает время хранения соединения в пул е (в


Connec tl On
.f . секундах). По умолчанию значение О устанавливает
Ll etlme
неограниченное время жизни

Некоторые поставщики имеют методы очистки п ула соединений.


Наприм ер, по ставщикSqlConnect i on имеет статические методы
Sql Connect i on . ClearPool (connec t i onS t r ing) очистка

пула конкретного соединения и

SqlConnect i on . ClearAl l Pools () о чист ка пулов всех

соединений в т екущем до.мене приложенuя. Э ти методы не удаляют


соединения физически, а помечают на Удаление для бредущего сзади
сборщика мусора.

Класс Command и DataReader

Класс Command позволяет выполнить любо й SQL·эапро с к открытому


соединению базы данных. Для того , чтобы использовать команду,
нужно выбрать ее тип , установить ее т екст и привязать к открытому
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

соединению. Эту работу можно выполнить, уста новив значения


свойств CommandType , CommandTe x t и Connect i on , либо
передать необходимую информацию в аргументах конструктора масса
Command.

Текстом команды может быть SQ L -о ператор , хранимая процедура (


stored procedure ) или имя таблицы. Э то определяется
з н ач ени ем пер е числ е ния
Command T ype , присваиваемого свойству
Command . CommandType.

Значения перечисл е ния CommandType


Значение Опис

Требование вь
SQL-оператор
свойстве
System . Data . CommandType . Te x t Command . Co
Установлено п
в свойстве MG
Command . Co
Требование вь
хранимую про!
System . Data . CommandType . StoredProcedure
указанную в СЕ

Command . Co
Требование из
записи из табл
указанной в св
Command . Co
System . Data . CommandType . TableDi re c t
Не подцеРЖИВ i
поставщиком 1-
Server

Ра с ширим наш пример , чтобы применить код создания объекта


Command .

• ~Создайте из копии файла TestConnectionl.aspx файл с им ен ем


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Tes t ConCo mmand . asp x и установите е го стартовым


• Г;;:;-Доп олните код страницы TestConCommand.aspx так

<%@ Page Language="C#" % >

<script runat= "server''>

protected void Page_Load(object sender, EventArgs е)


(
// ИзвлеюlИ строку соединения из web.config
string соппесtString = System WеЬ.Сопfigшаtloп.WеЬСоnfigшаtiопr
Со nnectio nS trings['N о rthwind '1. С о nnесtlo nS tring;

// Установили минимальный размер пула соединения равны,


connectString += "Min Роо! Size=10;";

// Создали объект соединения


SystemData.SqlClient.SqlCo nnection соп =
new 5 ystem.Data. SqlC lient. SqlConnection( connectS tring);

using (соп)
{
// Получить соединение из пула (если есть)
// или создать пул с 10 соединениями (если нет)
соп.ОрепО;
IblInfo.Text = "< Ь > Соединение: < /Ь > " + con.State.ToStringO;

// Создали объект Сопuna пd


SystemData.SqIClient.SqlCommand спx:l =
new System.Data. SqlClient.S qlCommandO;

// Настроили объект Command


cmd.Connection:= соп;
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "SELECT * FRQM Employees";
}

// Вернугь соединение в пул


IblInfo.Text += "< Ьг />< Ь > Соедин е ни е: < /Ь > ";
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

IblIпfо.Техt += con.State.ToStrmgO;
}
</script>

<html xmIns='huр ://www.wЗ .or!j'1999/xhtml" >


<head runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nmat="server''>
<div>
<asp:Label ID:="lblInfo " nmat:="server" Text=''Label''> </asp:Label> <
</fonn>
</body>
<lhtml>

Листинг Страница TestConCommand.aspx создания

объектов соединения и команды

• ~ сполните стра ниц у, чтобы получи ть такой результат

Соединение: Ореп
Соединение: Closed

Учитывая, что по умолчанию установлен о CommandType


CommandType . Te x t , кома н ду можно с р азу указать в п е регруженном

конструкторе п ри создании объекта команд. Например , код

// Создали объект Comma nd


Systе m.Dаtа.SqlСliе пt .SqlСоmma пd cmd :=
пеw Systеm.Dаta.SqIСliепt.SqIСоmmaпdО;

// Настр оили объект Commarкl


cmd.Connection = соп;
cmd.CommandType:= Sуs tеm. Dаtа. СоmmaпdТуре .Теxt;
cmd.CommandText = ''SELECT * FROM Emp loyees";

можно замени ть кодом

// Создали и настроили объект Соmma пd


Systе m.Dаtа.SqlСliе пt .SqlСо mmапd cmd :=
В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

new System.Data.Sq IClient.Sq ICommand("SELECT * FROM Emp loyees", с

в да нн ом п римере мы просто на строили , но н е выполнили объект


масса Coттand. поэтому никакой выборки данных из БД не получили .
Объект Coттand и меет три метода вы п ол н ен ия команды ,
п ривед е нные в таблице на примере масса SqlCommand

Методы выполн е ния объекта Command


Метод

System . Data . SqlClient . SqlCommand . Ex ecuteNonQuery(

System . Data . SqlClient . SqlCommand . Ex ecuteScalar()

ш
в.м. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

System . Data . SqlClient . SqlCommand . Ex ecuteReader()

Метод SqlCommand.ExecuteReaderO

Объект масса Dа t aReade r представляет собой резул ьтирующий


набор данных только для чтения и является самым простым и быстрым
средством доступа к данным. Он является выборкой дан ны х по запросу
SQ L · КOMaHAbI SELECT и состоит ИЗ строк и колонок, которые можно
ан ализировать и отображать. Но в н ем нет во змож ностей сортировЮ1 ,
как в более развитых об ъектах. Ниже прив еде ны несколько методов
DataReade r на примере масса
System . Data . SqlC l ient . SqlDataReader

Методы КIlaccй DataReader


Метод Описание

Перемещает курсор строки


следУЮЩУЮ строку в nOTOI
нужно также вызывать пеl

после создания объекта


Dа taReade r, поскольку
Sq l DataReader . Read() начальный курсор
позиционируется перед л(

строкой. Возвращает fa l ~
чтении последней строки

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

да нны х

Чита ет значение поля теку


Sq l DataReader . Ge t Value( i nt) строки по указанному ин д

(индекс н ачинается с н уля:

Сохраняет значение т екуш


строки в массиве. Количе(

сохраняемых полей заВИСl


размера массива, п ередаю
Sq l DataReader . Ge t Values(objec t [
этому методу Чтобы сохра
] )
поля текущей строки, н уж ]

создать массив размерное,

определяемой свойством
SqlDataReader . Fiel
Возвращает значение поля
Sq l DаtаRеаdеr . Gе t Iп t З2( i пt)
типа п о индексу столбца

Возвращает значение поля


Sq l DataReader . Ge t Da t eTi me(int)
даты по индексу столбца

Если команда , которая


сгенерировала Оа taReac

возвратила более одного


Sq l DataReader . NextResult() результирующего набора с
этот метод пер емещает Te~

курсор данн ых на первую

следУЮщего набора

Sq l DataReader . Cl ose() Закрыва ет МодУль чтения

Обработка одного результирующего набора данных


SqlDataReader

Прив едем пример , в котором создается и выполняется пр остая команда


запроса для выборки всех за писе й из таблицы Employees учебной
базы да нных Northw i nd . Мы п ом ним , что строка соедине н ия была
нами задана ранее в конфигурационном файле .

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• IJ$Создайте копию стра ницы TestConCommarкl.aspx с им ен ем


Tes t DataReade r. aspx
• ~3ап ол ни те страницу приведе нны м кодом

<%@ Page Language="C#" %>

<script runat= "server''>

protected void Page_Load(object sender, EventArgs е)


(
// ИзвлеюlИ строку соединения из web.config
string соппесtString = System WеЬ.Со пfigшаtloп.WеЬСоnfigшаtiопr
СО nnectio nS trings['N о rthwind '1. С о nnесtlo nS tring;

// Создали объект соединения


SystemData.SqlClient.SqlCo nnection соп =
new 5 ystem.Data. SqlC lient. SqlConnection( connectS tring);

// Создали объект Command


SystemData.SqlClient.SqlCommand cmd =
new System.Data.SqlClient. SqlCommandO;

// Настроили объект Command


cmd.Connection:= соп;
cmd.CommandType := System.Data.CommandType.Text;
cmd.CommandText = "SELECT * FRQM Employees";

// Создаем ссылку на вспомогательную строку


System Text . StringВuilder htmlStr:= new StringBuilder("'');

using (со п)
{
// Открыли соединение
со п.ОрепО;

// Выполняем командУ и получаем результирующий набор ,


SystemData.Sq IClient.SqlDataReader reader =
cmd .Execute ReaderO;
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

// Перебираем все записи результ и рующего набора


// и стр оим НТМL-строку
while (reader.Read())
{
htmlStг. Аррепd("< li>СлужащиИ '');
htmlS tr. Ар pend (read ег[ ' Тit1eO fC о шtеs у" ]);
hunlStr.Append(" < Ь >");
htmlS tr. Ар pend (read ег. GetS tring( 1 ));
hunlStr.Append("<!b>, '');
htmlStr. Append(reader.GetString(2));
htmlStr. Append(" - работает с'');
htmlS tr. Ар pend (read ег. GetDate Тпnе( 6) .То S tring("d ''));
hunlS tr. Ар pend ("<Ili> '');
}

// Закрываем набор данных


reader.CloseO;
}

// Выдаем результаты запроса


Ibllnfo.Text = hunlStr.тоStringО;
}
</script>

<html xmIns='Ъttр:l/www.wЗ.or&,1 999/xhtml" >


<head runat= "server''>
<tide > Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nшat="sеrvег''>
<div>
<asp:Label ID="lb Unfo" nшat="sе rvег" Text=''Label''> </asp:Label> <
</fonn>
</body>
<lhtml>

Листинг. Код страницы TestDataReader.aspx с чтением из


базы Northwind
• ~ с п ол ни те стра ниц у TestDataReader.as px, долже н п олуч и ться

ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

такой клиентский результат

• Служащий Ms. Oavolio, Nancy - работает с 01.05.1992


• Служащий Ог. Fuller, Andrew - работает с 14.08.1992
• Служащий Ms. Leverling, Janet - работает с 01.04.1992
• Служащий Mrs. Peacock, Margaret - работает с 03.05.1993
• Служащий Мг. Вuсhапап, Steven - работает с 17.10.1993
• Служащий Мг. Suyama, Michael - работает с 17.10.1993
• Служащий Мг. Кiпg, Robert - работает с 02.01 .1994
• Служащий Ms. Callahan, Lаша - работает с 05.03. 1994
• Служащий Ms. Oodsworth, Аппе - работает с 15.11.1994

в этом примере объект класса StringBuilder существен но


увеличивает пр оизводительность за счет вы деления буфера памяти дл я
символов. Есл и использовать объект класса St ri ng , то при каждой
операции сложения строк БУдет создаваться новый объект с
копированием результатов из старого объекта , что значительно
медленнее.

в большинстве случаев на м такой способ выборки инф:Jрмации из базы


в будущем не понадобится , по скольку существуют библиотечные
элементы управления для визуализации и работы с данными.

Обработка множественного результирующего набора


данных SqlDataReader

Команда SqlCommand . E x ecuteReade r () может возвращать

множественный результирующий набор да нных в двух случаях:

1. Если вызывается хранимая процедура, содержащая несколько


операторов SELECT
2. Если выполняется строка SQL-запроса, содержащая несколько
SQL-кома Н А , раздел енных точкой с запятой

Вот пример строки SQL-запроса, содержащей три команды SELECT :

strшg sq l = ''SELECT ТО Р 5 * FRQM Еmрю уееs;"


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

+ ''SELECT то р 5 * FROM Customers;"


+ "SELECT то р 5 * FROM Supptiers";

Приведенная строка содержит три запроса , каждый из которых


возвращает в результирующий набор да нных по пять п ервых записей из
тр ех таблиц базы Northwind . Ниж е приведен код стран ицы , в
котор ом выполняется последовательная выборка данных из
множественно го результирующего набора. Пере ход на новый
результирующий набор выполняется методом Ne x t Resul t () ,
которы й возврати т false , когда больше не останется результирующих
наборов .

• Г;;:;=Создайте копию страницы TestDataReader.aspx с им ен ем


Тез tM ul t i Da taReade r . азр х и о пр еделите ее стартовой
• Г;;:;=Заполните страницу приведенным кодом

<%@ Page Language="C#" % >

<script runat= "server''>

protected void Page_Load(object sепdег, ЕvепtAгgs е)


(
// ИзвлеюlИ строку соединения из wеЬ.со пfig
stгiпg сопneсtStriпg = System. WеЬ.Сопfigшаtloп.WеЬСопfigurаtiоШ
СО ппесtio пS triпgs[ ' N о rthwiпd '1. С о пnесtlo пS tring;

// Создал и объект соединения


Systеm.Dа tа .SqlСlieпt.SqlСо пnесtiоп соп =
пеw 5 ystem.Data. Sq lC lie пt. SqlСоппесtioп( сопnес tS tгiпg);

// Создал и объект Соmma пd


Systеm.Dа tа .SqlСlieпt.SqlСоmma пd cmd =
пе w Sуs tеm.Dаtа. S qlСlie пt.SqlСо mmaпdО ;

// Настроили объект Соmmaпd


сmd.Сопnесtiоп = соп;
сmd.СоmmaпdТуре = Systеm.Dа tа.СоmmaпdТуре.Техt;
сmd.СоmmaпdТеxt = "SELECT тор 5 FROM Employees;"
>1<

+ "SELECT ТОР 5 * FROM Customers; "


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

+ "SELECT тор 5 • FROM Suppliers";

System Теxt.Striпg8uildег htmlStr = пеw StriпgВuildег('''');


iпti=О;

usiпg (соп)
{
11 Открыли соединение
соп.ОрепО;

11 Выполняем командУ и получаем результирующий набор ,


SystemData.SqIClient.SqlDataReader reader =
cmd. Execute ReaderO;

11 Перебираем частные наборы в результирующем наборе /J


do
(
htmlStг.Аррепd("< h2>Набор: '');11 Заголовок h2 НТМL
hunlStr.Append(L ToString());
hunlS tr. Ар pend ("<1h2 > ',;
htmlStr.Append("<ul>''); 11 Начало маркированного списка

11 Перебираем все записи текущего набора


11 (их должно по команде быть 5 первых)
11 в результирующем наборе и строим НТМL-строку
while (reader.Read())
{
htmlStr.Append("< ~>'');11 Строка списка НТМL
11 Перебираем все поля строки набора
for (iпt field = О; field < геаdег.FiеIdСОШlt; field+ +)
{
if (fiek:l >= З) 11 Ограничимся тремя первыми полями
сопtiпuе;
hunlS tr.Append("<b> ");
htmlS tr.Append(reader.GetN ame(field). ТоStriпgО);11 Имя
hunlStr.Append(": < !Ь>',;
htmlS tr. Ар pend (reader. Get Value( fie ld). То S tгiпgО) ;I1 3 н ач
htmlS tr. Ар pend (' '&пЬsр ;&nbsp; &nbsp ;&пЬsр ;&пЬsр; '') ;1,
}
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

hunlS tr.Append("<1li> ');


}

htmlStr.Append("</ul>') ; // Конец мар кированного списка


i++ ;

} while (reader.N extResult()) ;

// З акрыва ем набор данны х


reader.CloseO;
}

// Показыва ем пол ьз ователю результаты запроса


Ibllnfo.Text = hunlStrToStringO;
}
</script>

<html xmIns='huр ://www.wЗ.or!j'1 999/xhtml" >


<head runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nmat="server''>
<div>
<asp:Label ID="lb Unfo " runat= "server" Text=''Label' '> </asp:Label> <
</fоПll>
</body>
<lhtml>

Листинг Код страницы TestмultiDataReader.aspx для


нес~оль~их таблиц базы Northwind
• ~ сполните стра ниц у, долже н п олучи ться такой результат
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET
Н або р : О

• Emp loyeelD 1 L .stName D""ct~ Fi rsШ .m е : Nar.:y


• Emp loye elD 2 LaМN8m e Fule r Flr$!N8me: мао :....
• Emp loyeelD 3 L •• tNam . Le"",, ri ng FirstN. me: J",et
• Emp loye elD..j LэstN8m е Р оососк Fiгзt N аm е : Marwel
• Emp loy •• 1D 5 L • • tNam . Bucha ",", FirstN. m.: Steven

Н абор: 1
• CU$!omerlD : ALFKI Co mpanyN 8me: Arreds FLltO!1<:i 5te Cont8ctName: Мo'"i a м ооГ5
• Cu ~tom.,ID : ANAТP Сотр.nyN~т .: А па TГ\Jj lo Е Гl1J "' ООаООБУ
h&lados ContactN. m.: А п а Tr Lj iro
• CU$tomerlD : A NТW Са тр~ny Н~те : A rtoГlo MDrooO Taql eгJ ~ Co nt~ctN eme: At1m o ИJгеm
• CU$!amtrlD : AROUT Camp anyNamt : 1110000 100 HDrn Cantac!Namt: Th:xnas Наа/
• CU$tomerlD: Ef:RGS Co mp8nyN8me : 8е гфnJs snabbkYp Cont. ctN8me : Cm stl na 8e г~

Н абор: 2
• Suppli. ,ID: СотрanуН.т. : Emt i~ L i ~ i ds ContactN. m.: Ch " lot1e CDOpe ,
• Suppl ierlD : 2 Со тР8nYН8те : New Orleaгrs C~JJ n De\ g гt5Co nt8ctN8me : Sh "" ',,,~ ВJ ri<",
• Suppllt ,lD: 3 Co mpanyNamt: (.(a гкtrl a K~ Ц > НоГГЮS I~аd Cant~ctNam t: R8<;ina ИJ ГР ho.'
• Suppl ierlD:.4 Co mp8nyN8me : т щ.о Т гм"" C on l~c tN8m e : YOsh l Na gase
• Suppll t rlD : 5 Co mpanyNamt : Co orx>r31iva de OU 8 W S 'Las С Ю 8 G ' С опt ас!Nаm t : M lon io dol VE> :o S аж EXtа

Мы искусствен н о ограничили кол и чество отображаемых полей тремя .


Есл и этот о п ератор убрат ь , то на пользователя об р уши тся поток
информации. Нам н а да нном этапе важ е н сам принцип извл е чения
ин формации из Ед.

Если нам напл е вать на пользователя и мы хотим показать ему


извлеченные данные как они есть, без дополни тельной обработки и
форматирования, то можно вос п ользоваться элеме н том уп р авления
Gr id Vi ew. В этом случае необходимую страниц у можн о получит ь так:

• Г;;:;=С оздайте коп ию страницы ТеstМuhЮаtаRеаdеr.аsрх с им ен ем


GridViewDataReader . asp x и определи те ее стартовой
• r;;:;=п оместите на страницу элеме н т управления Gr i dVi ew из
вкrыдки Data панели Toolbox
• ~3аполните страниц у приведе нн ым кодом

<%@ Page Language="C#" %>

<script runat= "server''>

protected void Page_Load(object sепdеr, Еvе пtArgs е)


{
// Извлеюш строку соединения из wеЬ.со пfig
striпg соппесtStriпg = System WеЬ.Со пfigшаtloп.WеЬСопfigшаtiопr
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

СО ппесtio пS triпgs[ ' N о rthwiпd '1. С о nпесtio nS tгiпg;

// Создал и объект соединения


SystеmDаtа .SqlСlieпt.SqlСо nпесtiоп соп =
пеw 5 ystem.Data. SqlC lient. SqlСоппесtioп( co rmectS tгiпg) ;

// С о здал и объект Command


Systе mDаtа .sqlСlieпt.sqlсоmma пd cmd =
пеw System.Data. SqlClient.SqlCommandO;

// Н астрои л и объект Соmma пd


сmd.Сопnесtiоп = соп;
сmd.СоmmaпdТуре = Systе m.Dаtа.Соmma пdТур е.Техt;
сmd.СоmmaпdТеxt = "SELECT тор 5 >1< FROM Suppliers";

us iпg (соп)
{
// Открыли соединение
соп.ОрепО;

// Выполняем командУ и получ а ем результирующий на бор ,


SystemData.SqIClient.SqlDataReader reader =
cmd. Execute ReaderO;

// П одключа ем элемент управл е ния GridView


// к полученному результирующему на бору
GгidView l . D аtа Sошсе = reader;

// Н аполн яем элеме н т управления GridView


// всеми извлеченными записями DataReader
GгidViewl.DаtаВiпdО;

// З а крыв а ем набор данны х


геаdег.СЮsеО;
}
}
</script>

<html XmInS= ' huр ://www.wЗ.or&,1 999/xhtml' '>


ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<head id =' 'Не а dl '' runat="server''>


<tide > Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nmat= "selVer''>
<div>
<asp:GridView ID="GridView l " runat="selVer">
</asp:GridView>
</div>
</fOmI>
<lbody>
<lhtml>

Листинг Код стра ницы GridViewDataReader. aspx с


нефорнатир ованным проснотром

• ~ сполните стра ниц у, долже н получиться такой результат

SupplierlD CompanyName ContactName Contact1ide Address City R!

1 ЕxotK. L lQ' uid s Charlotte


Соорег
Ршсhasing
Manager
49 Gilbert
5t.
Lo ndo n

New Ог1еаns Order р.о. Бох New и


2 SheUey Вшkе
Cajun Delights Administrator 78934 Огlеапs

Grandma
Rеgiпa Sales 707 Апп
з КеПу" М
Мшр hу Representative Oxford Rd. АгЬ о г
Homestead
9-8
Marketing Sekimai
4 Tokyo Traders Yoshi. N agase М
anager М usas hin0- Tokyo
shi
Cooperativa de А пtоniо deJ
Export СаПе del
5 Quesos 'Las Valle Oviedo k
Administrator Rosal4
Cabras' Saaved ra

Метод SqlCommand.ExecuteScalarO
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Этот метод объекта Command возвращает скалярную величину тип а


Object , которая является результатом р аботы агрегатных функций
врод е COUNT () и ли SИМ () SQL-запро са. Чтобы получить конкретное
знач ени е, к возвращенному объекту нужно применить явное
преобразо вание типов .

• ~С оздайте копию страницы TestConCommarкl.aspx с именем


Tes t E x ecuteScalar . asp x и сделайте ее стартовой
• ~Скорректи руйте страницу TestExecuteScalar.aspx так

<%@ Page Language="C#" %>

<script runat= "server''>

protected void Page_Load(object sender, EventArgs е)


(
// ИзвлеюlИ стр оку соединения из web.config
string соппесtString = System WеЬ.Со пfigшаtloп.Wе Ь Соnfigшаtiопr
Со nnectionS trings["N о rthwind "]. С о nnесtlo nS tring;

// Создали объект соединен и я


SystemData.SqlClient.SqlConnection соп =
new S ystem.Data.SqlC lient. SqlConnection( connectS tring);

// Создали объект Command


SystemData.SqlCtient.SqlCommand cmd =
new S ystem.Data. SqlC lient. SqlCommandO;

// Настроили объект Command


cmd.Connection:= соп;
cmd.CommandType := System.Data.CommandType.Text;
cmd.CommandText = "S ELECT COUNT(*) FROM Employees";

using (со п)
{
// Открыли соединение
со п.ОрепО;

// Выполнили командУ п одс ч ета записей таблицы Employe(


ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

// с применением явного преобразования тип а


iпt recordCount == (iпt)спx:l.ЕхесutеSса1згО;

IblInfo.Text == "< Ь > Колич ество за пи се й :</Ь > "+ recordCount."


)
}
</script>

<html xmIns= ' huр ://www.wЗ.or!j'1 999/xhtml" >


<head runat== "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id =="forml " nmat="server''>
<div>
<asp:Label ID="lb lInfo " runat="server" Text=''Label' '> </asp:Label> <
</fопn>
</body>
<lhtml>

Листинг. Страница TestExecuteScalar . aspx


• Г;:;n остройте стран и цу, р езультат бу,цет таЮ1М
Количество записей: 9

Метод SqlCommand.ExecuteNonQu eryO

Этот метод на п оминает конс ольн ую уг и л и ту, кото р а я работает в


пакетном реж и ме, в ыполняет каЮ1е-либо действ и я, н о н е возв р а ща ет
результатов. Метод E x ecuteNonQuery () в ып ол н яет таЮ1е SQ L-
кома н ды, как INSERT, DELETE , U PDATE , а возв р ащает только число ,

равное количеству об р абота нн ых за пи се й .

в качест ве пр и мера пр иведем код стран и ц ы , удаляю щий за п ись с


о п ределенн ы м знач ением п оля Emp l oyeeID в табл иц е Employees
БД Northwind . П оскол ьку эта база учеб н ая, н е будем ее п орти ть и
задади м заведомо н есуществующее з н аче ни е п оля Етр 1 о уее 1 о.

<%@ Page Language="C#" % >


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<script nmat="server''>

protected void Page_Load(object sender, EventArgs е)


(
11 Формируем соединение
string connectString = S ystem. Web.Configuration. WebConfiguratlonМanagE
С о nnесоо nS trings[''N orthwind 11]. С onnectio nS tring;
System.Data.SqIClient.SqIConnection соп :=
new S ystem. Data.Sq IClient.Sq IConnection(connectString);

11 Формируем командУ в конструкторе класса


int empID:= 111 ; 11 Заведомо несуществующее значение
string sql:= ''DELEТE FROM Employees WHERE EmployeeID:= "+ етр
System.Data.SqIClient.SqICommand cmd =
new System.Data.SqIClient.SqICommarкl(sqL соп);

try
(
соп.ОрепО;
int геССОШlt = сmd.ЕхеcutеNопQuеry();
Ibllnfo.Text = string.Format("<b> Удалено записей:<!Ь > {О} ", гесСоun
}
catch(S ystem.Data. SqlC lient. SqlException еп)
{
Ibllnfo.Text = string.Format("< Ь>Ошибка удаления: < !Ь> {О}", еп.Ме~
}
finally
{
con.CloseO;
}
}
</script>

<html xmIns=''http://www.wЗ.orgl1999/xhtml'' >


<head nmat="server">
< title >Uпtitled Page</tide>
<lhead >
<body>
ш
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

< fопn id="forml " runat="server''>


<div>
<asp :Labe! ID="lb lInfo" runat="server" Text= '1.abe!"> </asp:Labe!></div>
</foпn>
<!body>
<lhtml>

Листинг Код страницы DeleteUtility.aspx

Атаки на базу данных внедрением SQL

Очень часто возникает необходимо сть дать поль зователю возможно сть
самом у сформировать строку S QL-запроса в поле ввода. Если строка
запроса соде р жит ошибки , правильную обработку которых разработчик
не пр едусмотр ел, то система реагирует вы дачей сообщения с
ПРОСТОд.УШНо- доверительным анализом ошибки , из которого можно
узнат ь сведения о структуре и содержании дан ны х. Эт им пользуются
злоумышленники , которые на мере нно вносят в S QL-запрос хитрые
некорректности , что бы попытаться уз нать о да нных больше, чем
планирует разраб отчик.

Ра с смотрим это на прим ере .

• г;;;?Сделайте копию с именем Use r SqlG ri d Da t a . asp x из


файла GridViewDataReader.aspx и назначьте ее стартовой
• u;.;rp азмест ите выше элемента Gri dView текстовое поле
Te xt Bo x и кнопку Button , чтобы пользовательский инт е рфей с
на этапе проектuровйнuя был таким
В.М. СН"""'
г.:';-:==ОС=С""'7."'7==~;- _ _ _ _ _ _---'П""'
='''
'"=
~="''-
i Nu,,"аASР.NЕТ
serSqIGridData.aspx*

Введите Ш поль.зователя:

P\LFKI ш Получить

'ColumnO Columnl Column2


аЬс аЬс аЬс
аЬс аЬс аЬс
аЬс аЬс аЬс
аЬс аЬс аЬс
аЬс аЬс аЬс

• Г;:;=ОткорректируИте дескрипторный и встроенный коды


страницы так

<%@ Page Language="C#" % >

<script runat:= "server',>

protected void Page_Load(object sender, EventArgs е)


(
// ИзвлеюlИ строку соединения из web.config
string соппесtString:= System WеЬ.Сопfigшаtloп.WеЬСоnfigшаtiопr
Со nnectionS trings["N о rthwind "]. С о nnесtlo nS tring;

// Создали объект соединения


SystemData.SqlClient.SqlCo nnection сап:=
new 5 ystem.Data. SqlC lient. SqlConnection( cannectS tring);

// Создали строку SQL-запроса


string sql :=
"SELECT Ordeгs.CustamerID, Ordeгs.OrderID , COUNT(UnitP
+ "SUM(UnitPrice ... Quantity) AS Tatal FROM Orders "
+ '1NNER JOIN[Oгdeг Details] "
+ "ON Ordeгs.OrderID = [Order Details].OrderID "
+ 'WHERE Ordeгs.CustomerID:= '" + TextВox l.Text + ,. "
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

+ "GROUP ВУ Orders.OrderID, Orders.CustomerID";

// Создали объект Command


SystemData.SqlClient.SqlCommand cmd =
new System.Data. SqlClient.SqlCommand(sql, сап);

using (соп)
{
// Открыли соединение
соп.ОрепО;

// Выполняем командУ и получаем результирующий набор ,


SystemData.SqlClient.SqlDataReader reader =
cmd. Execute ReaderO;

// Подключаем элемент ynравления GridView


// к полученному результирующему набору
GгidViewl.Dа tа Sошсе = reader;

// Наполняем элемент ynравления GridView


// всеми извлеченными записями DataReader
GridViewl.DataBind O;

// Закрываем набор данных


reader.CloseO;
}
}
</script>

<html XmInS= 'huр ://www.wЗ.or&,1999/xhtml' '>


<head id=''Неаdl'' runat="server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id="forml" runat="selVer''>
<div>
Введите ID пользователя: < Ьг />
< asp:TextВox ID='TextВoxl" runat="selVer" Width=''248px'' Роп
<asp:Button ID =''Вuttопl '' runat= "selVer" Техt=''Получить '' />< Ь
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

< Ьг 1>
<asp:GridView ID="GridViewl " runat="server">
</asp:GridView>
</div>
</fопn>
<!body>
<lhtml>

Листинг. Код страницы UserSqlGridData . aspx


• r;:;'и с полните стра ницу и долже н получ иться такой результат

Введите ID ПОПЬЗ0ватеПR:
IALFKI I ПО"!,"ТЬ

CustomerID OrderID Items Tota/


ALFКI 10643 3 1086,0000
ALFКI 10692 1 878,0000
ALFКI 10702 2 330,0000
ALFКI 10835 2 851,0000
ALFКI 10952 2 491 ,2 000
ALFКI 11011 2 960,0000

При значен ии текстового п оля ALFKI вычи сле нный SQL-опе р атор
будет иметь тако й вид:

string sq l =
"SELECT Orders.CustomerID, Orders.OrderID, COUNT(UnitPrice) AS Itel
+ "SUМ(UnitPrice * Quantity) AS Total FROM Orders "
+ '1NNER JOIN[Oгdeг Details] "
+ "ON Orders.OrderID = [Order Details].OrderID"
+ 'WHERE Orders.CustomerID = 'ALFKI ' "
+ "GROUP ВУ Orders.OrderID, Orders.CustomerID";
Листинг . Строка SQL-запроса с учетом планируемого значения

текстового поля

Злоум ьши ен ник может п опы тать ся подделать оператор SQ L . Глав н ой


ц елью тако й атаки является получе ни е сообщения об ошибке. Если

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

о ши бка не обрабатывается правильно, то злоумьшmе нн ик п олучи т


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

Предп оложим, что злоумьшие н н и к введет в текстовое п оле следую щи й


текст

ALFКI' OR '1' = '1

в этом случае строка за прос а будет та кой

striпgsq l =
"SELECT Orders.CustomerID, Orders.OrderID, COUNT(UnitPrice) AS Itel
+ "SUМ(U nitPrice * Quantity) AS Total FROM Orders "
+ '1NNER Ю!N[Огdег Detai!s] "
+ "ON Orders.OrderID = [Order Details].OrderID "
+ 'WHERE Orders.CustomerID = 'ALFKI ' OR '1' = '1'"
+ "GROUP ВУ Orders.OrderID, Orders.CustomerID";
Листинг . Строка SQL - запроса с учетом фактического значения

текстового поля

Этот о п ератор в е р нет все за пи с и о заказа х, п оскольку усло в ие 1=1


истин н о дл я всех стр ок

• ~ с п ол ни те стр а н ицу UserSqlGridData.aspx и в ведите как


злоумыllен ник K в текстовое поле строку

ALFK!' OR '1' = '1

Долже н п олучитьс я результат, малая ч асть которого п р и веде на н и же

Введите ID ПОПЬЗ0ватеПR:
IALFKI" О П "1" - "1 ПОЛ\,,4L1ТЬ

Нач альн ая ч асть резул ьтата ,


в оз в ра ще нн о го п о искаженной
строке запроса

CustomerID O rderID Items Tota /

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

VINET 10248 3 440,0000


TOMSP 10249 2 1863,4000
HANAR 10250 3 1813,0000
VI CТE 10251 3 670,8000
SUPRD 10252 3 3730,0000
HANAR 10253 3 1444,8000
CHOPS 10254 3 625,2000
RICSU 10255 4 2490,5000
WELLI 10256 2 517,8000
НI LAA 10257 3 1119,9000
ERNSH 10258 3 2018,6000
CENTC 10259 2 100,8000

в результате злоумьшие н нику передается вся инф:J р мац и я о сделанных


заказах. Есл и ин ф:Jрмация содержи т номера кредитн ых карточек,
карто ч ек социальн ого ст р ахова н ия и ли дату рождения заказчиков, то

ре п уга ц ия тако го сайта будет с треском п ровалена и ни кто пользоваться


им не будет.

Возможны и более сложн ые атаки. На п ример, злонамеренный


пользователь может просто закоммен тировать остаток опе р ато р а SQL,
добавив два тире (--). Эта атака специфична
SQ L SelVer, но дЛЯ
аналогичная атака возможн а и в MySQL, если использоват ь с и мвол #, и
в O racle, если задействовать точку с запятой (;).

3лоумьшиен ник может приме н ить пакетную команду, ч тобы выполни ть


произвольный оператор SQ L. При ис п ользова н ии поставщика данных
SQL Server достато ч но просто добав и ть то ч ку с за п ятой, за которой
передать до п ол н ительную кома н ду. Таким образом можно, например ,
удалить содержимое другой таблицы, или даже вызвать систем н ую
хранимую процедуру SQ L SelVer хр cmdshel l , чтобы за п усти ть
произвольную программу и з кома н дной строки.

Вот ч то злоумыllенникK может ввести в текстовое п оле, чтобы


осуществи ть более изошренную атаку в н едре н ием SQL, удалив все
строки из таблицы Cus tome r s :
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

ALFKI'; DELEТE * FROM Customers--

Не делайте этого с на шей учеб н ой базой!!!

Для то го, чтобы противо стоять атаке в н едре ни ем , следует п омни ть


несколько правил:

1. И с п ользовать свойство T e x tBo x . Ma x Length , чтобы


пр едотв р ат и ть дли нный ввод, ко гда в этом нет необходимости
2. Обрабатывать ошибки самом)'; чт обы огр ани ч ить информацию
стандартного исключения Ex ception . Message
з. Выявлять и удалать из строки ввода специальные символы ,

например , заменят ь оди но ч ную кавы ч ку п арой одиночных


кавы ч ек

string ID = ТехtВох1.Теxt . RерLзсеС"", '.");

4. И с п ользовать пар аметризованные команды или хранимые

процедуры , котор ы е предУсматр ивают собстве нную защиту от

атак внед рением SQ L


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

Прим енение п араметризованных команд

Парамеmрuэованная команда, это обы ч ная кома н да SQ L, и с пользующая


спец ификаторы , обоз нача ющие место , в которое бу,цуг динамически
подставлены объекту Command определе нны е пар аметры-заполнители
SQL через коллекц и ю Parameters . Параметры -за полнители
прописываются отдел ьно и автомати чески кодируются.

С инта ксис параметрuзова н ных команд сле гка отл и чается у разных
поставщиков данных . Так, поставщик SQ L SelVer пр едусматривает
именованные заполнители с уникальными им е н ами. У поставщика OLE
DB спецификаторы являются вопросами, а п орядок следования

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

заполнителей должен соответствовать кон тексту следования

спецификаторов .

Приведем п ример , использующий п араметризованную команд.у, в


котор ом И СЮlюче н а возможность атаки в н ед рением SQL .

• ~Сделайте из страницы UserSq!GridData .aspx коп ию с им ен ем


Use r SqlParamCommand . азр х и на з начьте ее стартовой
• ~Откорректируйте страницу UsеrSqlPаrаmСоmmaпd.аsрх, чтобы
она имела следУЮ ЩИЙ код

<%@ Page Lапguаgе:="С#" %>

<script ruпаt:= "server''>

protected void Page_Load(object sепdеr, ЕvепtArgs е)


(
// ИЗБл еюlИ строку соединения из wеЬ.со пfig
striпg соппесtStriпg:= System WеЬ.Сопfigшаtloп.WеЬСопfigшаtiопr
Со ппесtio nS triпgs[ ' N о rthwiпd '1. С о пnесtlo пS tring;

// Создал и объект соединения


SystеmDа tа .Sq!Сlieпt.Sq!Со пnесtiоп соп:=
new S ystem.Data.Sq!C lie пt. Sq!Соппесtioп( сопnес tS tring);

// Создал и строку SQL-запроса


striпg sq! :=
"SELECT Orders.CustomerID, Orders.OrderID, COUNT(UnitP
+ ''SUM(UnitPrice ... Quапtitу) AS Tota! FROM Orders "
+ '1NNER JO I N[Oгdeг Details] "
+ "ON Orders.OrderID := [Order Details].OrderID "
+ 'WHERE Orders.CustomerID := @CustomID "
+ "GROUP ВУ Orders.OrderID, Orders.CustomerID";

// Создал и объект Соmma пd


SystеmDа tа .Sq!Сlieпt.Sq!Соmmaпd cmd :=
new Sуs tеm.Dаtа.Sq!Сlieпt . Sq!Соmmaпd(sql, соп);

// Дополн и л и коллекцию Parameters


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

cmd.Parameters.Add("@CustomID", TextBoxl.Text);

using (сап)
{
II Открыли соединение
соп.ОрепО;

II Выполняем командУ и получаем результирующий набор ,


SystemData.SqIClient.SqlDataReader reader ==
cmd. Execute ReaderO;

II Подключаем элемент ynравления GridView


II к полученному результирующему набору
GгidViewl.DаtаSошсе = reader;

II Наполняем элемент ynравления GridView


II всеми извлеченными записями DataReader
GridViewl.DataBindO;

II Закрываем набор данных


геаdег.СЮsеО;
}
}
</script>

<html XmInS= ' huр ://www.wЗ.or!j'1999/xhtml' '>


<head id=''Неаdl'' runat="server''>
<tide> Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nmat="selVer''>
<div>
Введите ID пользователя:<Ьг 1>
< asp:TextВox ID= 'TextВoxl " nmat="selVer" Width=''248px'' Роп
<asp:Button ID =''Вuttопl '' nmat="selVer" Техt='Получить" I>< b
< Ьг 1>
<asp:GridView ID="GridViewl " runat="selVer">
</asp:GridView>
</div>
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

</fonn>
</body>
<lhtml>

Листинг. Код страницы UserSqlParamCommand.aspx

Код страницы остался почти таким же, за ИСЮlючением двух строк,


вводя щи х команду с именованным параметром @СизtоmI D .

• ~ опробуйте исполнить атаку внедрением с содержимым поля


eBoda ALFKI ' OR ' 1' '1

Мы ви дим, что страница не возвращает никаких данных, поскольку ни


одна запись таблицы Orders в поле Сизtо m еr I D не имеет значение ,
равное введенной строке ALFKI ' OR ' 1 ' , 1. Таким простым

способом мы защитили данные от злоумыuиенного внед рения SQ L.

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

Хранимые процедуры представляют собой пакет из одного или


нескольких операторов SQ L, хранимых в базе данн ых. ЭТО самый
действенный спо соб от внедрения SQ L. Хранимые процедуры похожи
на функции тем , что они им еют свою отлаженную лотку и принимают
данные ч е рез входные параметры, а возвращают да нные через
выходные параметры или результирующие наборы.

Хранимые процедуры им е ют множество достоинств:

1. И х легко сопровождать. Например , можно и зме нять команды в


хранимой процедУРе без п е рекомпиляции приложения ,
использующего эту процедуру

2. Они позволяют реализо вать более безопасный доступ к базе


данн ых. Например , можно по з волить учетной зап иси Windows,
запускающей наш код ASP.NET, испо льзо вать определенные
хранимые процедуры , но ограничить доступ к лежащим в их
основе таблицам
з. Они могуг повысить производительность. По скол ьку хр анимы е
процедуры упаковывают вм есте множество SQ L -о п е раторов ,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

можно выполнить огр ом ный объем работы за одно обращение к


серверу базы дан ных, особе нно , е сли база р ас положе на н а другом
компьютере

Ра ссм отрим пример SQ L - кода , необходимого при создании хранимой


процедуры дл я вставки отдельной за пи си в таблиц у Employees . Э той
хранимой процедуры изначально нет в БД Northwind . Хранимая
процедура должна ре ал изовывать следующий код

CREATE PROCEDURE I nseгtEmployee


@1ideOfCourtesy varchar(25),
@ LаstNаше varchar(20),
@ FirstNаше varchar(10),
@EmployeelD int OUТPUТ
AS
INSERT INTO Employees
(1itleОfCошtеsу, LastName, FirstName, HireDate)
VАLUЕS(@1itleОfCошtеsу, @LastName, @ FirstName,GETDAТE());
SET@EmployeelD = @@ lDE NTIТY

Эту хранимую процедуру можно добавить на этапе проектирования


через п а нель Server ЕХРloгег оболочки , пр едвари тельно
при соединившись к базе данных No r dhw ind . Но я не смог это сделать ,
п оскольку оболочка не видит эту базу из-за неправильн о
установле нн ого п акета SQ L Server 200 5 (или потом у, что У меня руки
кривые). Чтобы как-то выв е рнугься, в приведе нном ниж е коде мы
добавим ее прогр амм н о.

• ~Создайте новую страницу с им ен ем


Tes ts to r edProcedure . asp x и на з начьте ее стартовой
• ~ оместите на страницу и з вкrщцки Standard элементы
управления согласно дескрипторном у коду, приведен н ому ниже

(устал писать , да и СТУдент З иборов ругается , но зато все


р аб отает !)
• ~ астройте код ст р а ницы , чтобы в итоге о н был таким

<%@ Page Language="C#" %>

<script nшat= "sе rvег ''>


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

protected void Page_Load(object sender, EventArgs е)


(
11 И звлекли строку соедине ни я из web.co nfig
string connectString = S ystem. Web.Configuration. WebCo nfiguratlonМa nagE
С о nnеспо nS trings[''N orthwind "]. С onnectio nS tring;

11 Создал и объект соединения


System.Data.SqIClient.SqIConnection со п ::::
new S ystem. Data.Sq IClient.Sq 'Соnnеспо п( connectString);

try
(
string sq l ==
"CREAТE PROCEDURE InsertEmployee"
+ "@Tn:.leOfCourtesy varchar(25),"
+ "@ LastName varchar(20),"
+ "@FirstName varchar(10),"
+ "@Emp loyeeID int OUТPUT"
+ "AS"
+ '1NSERT INTO Emp loyees "
+ "(1ideOfCourtesy, LastName, FirstName, Hh"eDate) "
+ 'VALUES(@1ideOfCourtesy, @ LastName, @FirstNаше, GEmAT
+ "SET@Employee ID = @@IDENТIТY";
Systеm D а tа.Sqk:liепt.Sq!Соmma пd cmd::::
new System.Data.Sqk: lient.Sq ICommaOO(sqL соп);
со п .Оре пО;
сmd .ЕхеcutеNопQuеry();
}
catch (Systе m.Dа tа.Sq!Сliепt .SqlEхсер tiоп епо г)
(
)
finally
(
con.CloseO;
)
}

protected void AddEmployee_ Click(object sender, Eve ntArgs е)


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

(
11 Извлекли строку соединения из web.config
striпg соnnесtStгiпg = S ystem. WеЬ.СопfigurаtЮп. WebConfigurationМanagE
С о nnеспо nS tгiпgs[''N оrthwiпd "]. С onnectio nS tгiпg;

11 Создали объект соединения


System.Data.SqIClient.SqICormection соп ::::
new S ystem. Data.Sq IClient.Sq IConnecllon(соnnесtStriпg);

11 Создать и настроить объект Commarкl


11 для вызова хранимой процедуры InsertEmployee
System.Data.SqIClient.SqICommand cmd ::::
new S ystem. Data.Sq IClient.Sq ICommarкl('1nsertEmployee", соп);
cmd.CommandType:::: System.Data.CommarкlType.StoredProcedure;

11 Добавить входные параметры хранимой процедуры


11 в коллекцию параметров Command.Parameters
11 Добавляем первый входной параметр
cmd. Р arameters. Add( new S ystem. Data. 5 q IC lient. 5 q IP arameter(
"@ТItleOfCourtesy", S ystem. Data.Sq IDbType.NVarChar, 25));
cmd.P агаmetеrs["@1it1eОfCошtеsу"].Vаluе = title. Text;
11 Добавляем второй входной параметр
cmd.Parameters.Add(new System.Data.SqIClient.SqlParameter(
"@LastName", System.Data.SqlDbType .NVarChar, 20));
cmd.P arameters["@LastName"].Value :::: IastN ате. Text;
11 Добавляем третий входной параметр
cmd. Р arameters. Add( new S ystem. Data. 5 q IC lient. 5 q IP arameter(
"@FirstName", System.Data.SqlDbType.NVarChar, 10));
cmd.Parameters["@FirstName"].Value :::: firstN ame.Text;

11 Добавить выходной параметр хранимой процедУРЫ


11 в коллекцию параметров Command .Parameters
cmd. Р arameters. Add( new S ystem. Data. 5 q IC lient. 5 q IP arameter(
"@EmployeeID", System.Data.SqIDbType.lnt, 4));
cmd.P arameters["@EmployeeID"].Direction = SystemData.ParameterDire

usiпg (соп)
(
11 Открыли соединение
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

соп.ОрепО;

11 Выполняем команду
int геССОШlt = cmd.ExecuteNonQuery();
1b1Info.Text = string.Format("< Ь>Вставлено записей:<!Ь > { О} < Ьг 1>",
11 Получить вновь сгенерированный идентификатор
int empID = (int)сшd.Рагаmetеrs["@ЕmplоуееID"].Vаluе;
1b1Info.Text += ''Новый и де нтификатор: " + empID.ToStringO;
)
11 Соед инение закрыл ось автоматически
}
</script>

<html xmlns="httр://www.wЗ.огgl1999/xhtml">
<head id=''Неаdl'' nmat="server">
<title>Untitled Page</tide >
<lhead >
<body>
< fопn ю="fопnl" runat="server''>
Введите титул:< аsр:ТехtВох ID=''tide'' runat= "server">cTYAeHT</asp:Tex
Введите имя: < аsр:ТеxtВох ID="firstName" ruпаt="sеrvег' '> Иван </аsр:Т(
Введите фамилию: < аsр:ТеxtВох ID=''1astName'' runаt="sеrvег"> Петров
<asp:Label ID= "lb lInfo" runat= "server" 1>
<br 1>
<br 1>
<aspButton ID="AddEmp loyee" runat= "server" Теxt="Добавить служащ
OnClick="AddEmployee_Click" 1>
<asp:LinkButton ID='Ъ tnRеsuh" runat="server"
PostBac k U rl="~ fГestDa ta Reader.asp х''> П о казать сп и сок< 1asp :LinkB l
</foпn>
<!body>
<lhtml>

Листинг Итоговый ход страницы TestStoredProcedure.aspx

Ин терфейс стра ниц ы БУдет таким

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Введите ти1уп ст\"дент


г'-''''----,-'
Введите иМR: "и"В:='-':
Н =____--"_-,
Введите фам иПию: LП"'--'Тр,,о"'В_____-'

Дo6~BHTb служащего Покаэать СПисОК

• ~Добавьте служащего щелчком по кнопке, после чего выведите


список. Результат бу,цет примерно таким

• Служащий Ms. ОаvоlЮ, Nancy - работает с 01.05.1992


• Служащий Ог. Fuller, Andrew - р аботает с 14.08.1992
• Служащий Ms. Leverling, Janet - работает с 01.04.1992
• Служащий Mrs. Peacock, Margaret - работает с 03.05.1993
• Служащий Мг. Buchanan, Steven - работает с 17.10.1993
• Служащий Мг. Suyama, Micrnel- работает с 17.10.1993
• Служащий Мг. King, Robert - работает с 02.01 .1994
• Служащий Ms. Callahan, Lаша - работает с 05.03.1994
• Служащий Ms. Oodsworth, Аппе - р аботает с 15.11.1994
• Служащий СТУдент Петров, Иван - работает с 25.04.2007

в обработчике Page Load () мы намеренно примени ли п устой блок


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

Транзакции

Транзакция , это набор операций SQL, которые либо должны бы ть


успе llllЮ выполнены все , либо должны быть все отменены , если хоть
одна опера ци я дала сбой . Такой механизм гарантирует, что данные
всегда находятся в корректном состоянии.

Поставщики данных ВЮlючают подцержку тран закций , которые

начинаются при вызове метода

Connection . BeginTransaction() . Принимается транзакция


методом Transact i on . Comm i t () , а отменяется, если ВОЗНИЮlо

ИСЮlючение , методом Transac ti оп . Rollba ck ( ) .


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Прив едем прим е р , в Ю)тором в табл иц у Employees БД No r dhw i nd


до бавляется две за писи чер ез механизм контроля т р анзакций . Э ти
записи можно было бы добавить и обычным способом , но в
критических случая х делать это нужно под Ю)н трол ем тра н за кций .

• ~Сделайте из стр аниц ы Те stS tогеd Ргосе dше.аs рх Ю)пию с


и ме н ем TestTransact i on . asp x и определите ее стартовой
• ~3ап олните страницу следующим кодом

<%@ Page Language="C#" %>

<script runat= "server''>

// Объявляем п ереме нны е-сс ы лки как чле ны класса страницы


stringsql1 = '1NSERT INTO Emp loyees (LastName, FirstName, Hirel
+ 'VALUES ('Зиборов', 'Алексей', GЕШАТЕ())";
stringsql2 = '1NSERT INTO Emp loyees (LastName, FirstName, Hirel
+ 'VALUES ('Погодаева', 'Татьяна', GEmAТE())";
System Data.Sq IС ~ent.Sq IСоnnесооп соп;
SystemData.SqIClient.SqICommand cmdl , cmd2;
SystemData.SqIC~ent.Sqrrransaction иа п := null;

/**** Для отладки ****/


string sqlЗ:= ''DELEТE FROM Employees WHERE Emp loyeeID > 9";
SystemData.SqIClient.SqICommand сmdЗ;
/* ** ****************** /

protected void Page_Load(object sender, EventArgs е)


(
// Извлеч ь строку соединения из web.config
string соппесtString:= System WеЬ.Со пfigшаtioп.WеЬСоnfigшаtiопr
Со ппесtюпS trings[''N о rthwind "]. С о nnесtio nS tring;

// Создать объект соединения


со п := new Sys tеm. Dаtа. SqIСlie пt. SqIСоппесtЮп(соnnесtString);

// С оздать объекты Ю)манд


cmdl := new SystemData.Sq IC ~e nt.S qICommand(sq l1 , соп);
cmd2 := new SystemData.SqIC~ent.SqICommand(sq12, соп);
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

/**** Для отладки ****/


сmdЗ = new Systеm.Dаta.SqIСliепt.sqlсоmmaпd(sqlЗ, соп);
/* ******************** /
}

protected void AddEmployee_Click(object sender, EventArgs е)


{
try // Попытка
(
// Открыть соединение
соп.ОрепО;

/**** Для отладки ****/


сmdЗ.ЕхесutеNопQuегу(); // Удалить последние записи
/********************* /

// Начать транзакцию
иап = con.BeginTransactionO;

// Пометить команды ВЮJюченными в транзакцию


cmdl.Transaction = иап;
cmd2.Transaction = иап;

// Выполнить обе команды


// Должны выполняться только команды транзакции!!!
cmdl.ExecuteN onQuery();
cmd2. Execute N onQ uery();

// И скусственная генерация ИСЮIючения


// для тестирования отмены транзакции
//throw new AppticationExceptionO;

// Подтвердить и закончить транзакцию


tran.Commit();

// Посчитать количество записей таблицы


// Теперь можно выполнять другие команды
cmdl.CommandText = ''SELECT COUNT(*) FROM Employee,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

string recCount = спкIl.ЕхеcutеSсаlaгО.ТоStringО;

II Выдать результат
IblInfo.Text = "Д обавлены д ве записи!<Ьг 1>";
IblInfo.Text += "Общее число записей " + recCount;
}
catch II Откат при любом ИСЮIючении
{
IblInfo.Text = ' Транзакция отменена!";
tran.RollbackO;
}
finally II Обязательное завершение
{
II Закрыть соединение по · любому
con.CloseO;
}
}
</script>

<html XmInS= ' huр ://www.wЗ.or!j'1999/xhtml''>


<head id =' 'Неаdl '' runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nmat="server''>
<asp:Label ID="lblInfo " nmat="server" 1>
< Ьг 1>
< Ьг 1>
<asp:Button ID="AddEmployee " runat="server"
Теxt=''Вы полнить транзакцию "
ОпСlick= "АddЕmрlоуее_Сlick " />
<asp:LinkButton ID ='ЪtnRеsu!t" runat="server"
Po stВack U rl="~ ffestDataReader. aspx''>
Показать список</а sр:LinkВuttоп>
</fопn>
</body>
<lhtml>

Листинг . Код страницы TestTransaction азрх


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• ~ сполните страницу и получите следующий отклик при


выполнении транзакци и

Добавпены две записи!


Общее число записей 11

Выполнить транзэкцию Показ8ТЬ список

• ~ росмотрите таблицу Emp l oyees БД Nordhwind по


2иперссЬ/лке , резул ьтат выполнения транзакции будет примерно
таким

• Служащий Ms. Oavo lio, Nancy - работает с 01.0 5. 1992


• Служащий Ог. Fuller, Andrew - р аботает с 14.08.1992
• Служащий Ms. Leverling, Janet - работает с 01.04.1992
• Служащий Mrs . Peacock, Margaret - работает с 03.05. 1993
• Служащий Мг. Buchanan, Steven - работает с 17. 10.1993
• Служащий Мг. Suyama, Michael - р аботает с 17. 10.1993
• Служащий Мг. King, Robert - р а ботает с 02.01.1994
• Служащий Ms. Callahan, Lаша - работает с 05.03. 1994
• Служащий Ms. Oodsworth, Аппе - р аботает с 15. 11.1994
• Служащий 3 и боров , Ал ексей - р аботает с 25.04.2007
• Служащий Погодаева , Татьяна - р аботает с 25.04.2007

Обратите внимание , что по ка тран закция н аход ит ся в процессе работы ,


до лжны выполняться только коман д ы транзакции. Область работы
транзакции определяется операторнЬ/ми скобками
сап . BeginTransaction () ; tran . Commi t () ;

Чтобы протестиров ат ь свойство отката (отменЬ/) транзакции, можно


встави ть н е по средственно перед вы зовом метода t r an . Comm i t ()
стр оку ген ерации исключ е ни я

throw new AppocationExceptionO;

Точки сохранения ДЛЯ откша транзакции

Иногда может ВО З НИlснугь необходимость откатить не всю

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

транзакцию, а только ее часть. В этом случае н уж н о расста вить в коде


метки отката, а в методе частичного отката указать, до какой метки
н ужно отменить тран за кцию. При этом н ужно им еть вви ду, что пр и
частичном откате до точки сохран ения все метки частично го отката ,

опр еделе нны е по сле данной, теряются и их нужно восстанавливать


за нов о.

Н ем ного изменим пред ы дущий при мер , введя возможность частичного


отката.

• Г;;:;=Скопируйте стра ниц у TestTransaction.aspx в

TestTransactionSave.aspx и на зн ачьте ее стартовой


• ~ зме ните код новой ст р а ницы , чтобы о н был таким

<%@ Page Language="C#" %>

<script runat= "server''>

// Объявляем п ереме нны е-ссылки как члены класса страницы


string sql1 = '1NSERT INTO Employees (LastName, FirstName, Hirel
+ 'VALUES ('Зиборов', 'Алексей', GЕШАТЕ())";
string sql2 = '1NSERT INTO Employees (LastName, FirstName, Hirel
+ 'VALUES ('Погодаева', 'Татьян а', GEmAТE())";
System Data.Sq IClient. Sq IСоnnеспоп соп;
SystemData.SqIClient.SqICommand cmdl , cmd2;
SystemData .SqIC~ent.Sqrrransaction иап:= null;

/**** Для отладки ****/


string sqlЗ:= "DELEТE FROM Employees WHERE EmployeeID > 9";
SystemData.SqIClient.SqICommand сmdЗ;
/* ** ****************** /

protected void Page_Load(object sепdег, ЕvепtAгgs е)


{
// Извлечь строку соединения из web.config
string соппесtString:= System WеЬ.Сопfigшаtioп.WеЬСоnfigшаtiопr
Со ппесtioпS trings["N о rthwind "]. С о nnесtio nS tring;

// Создать объект соединения


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

соп = new Systеm.Dаtа.SqlСlieпt.SqlСоппесtioп(соnnесtStriпg);

// Создать объекты команд


cmdl = new System.Data.SqlClient.SqlCommand(sql1, соп);
cmd2 = new System.Data.SqIClient.SqlCommand(sql2, соп);

/**** Для отладки ****/


сmdЗ = new Systеm.Dаta.SqIСliепt.sqlсоmmaпd(sqlЗ, соп);
/* ******************** /
}

protected void AddEmployee_Click(object sender, EventArgs е)


{
try // Попытка
(
// Открыть соединение
соп.ОрепО;

/**** Для отладки ****/


сmdЗ.ЕхесutеNопQuегу(); // Удалить последние записи
/********************* /

// Начать транзакцию
tran = соп.ВеgiпТгапsасtioпО;

// Пометить команды ВЮJюченными в транзакцию


cmdl.Transaction = tran;
cmd2.Transaction = tran;

// Выполнить первую командУ транзакции


cmdl.ExecuteN onQuery();
// Пометить точку отката
tran.Save( "Ziborov'');

// Выполнить вторую командУ транзакции


cmd2.ExecuteN onQuery();
// Выбросить ИСЮJючение
throw new ApplicationExceptionO;
}
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

catch // Откат
(
// Откатить частично
tr ап. Ro lIback("Ziborov'');

// Подтвердить и закончи ть транзакцию


tran.CommitO;

IblInfo.Text = ' Транзакция частично отменена!";

// Посчитать количество зап ис ей таблицы


cmdl. CommandText = ''SELECT C OUNT(*) FROM Employee,
string recCount = спкIl.ЕхеcutеSсаlaгО.ТоStringО;

// Выдать результат
IblInfo.Text = "Д обавлена одна заnись!<Ьг />";
IblInfo.Text += "Общее число записей " + recCount;
}
finally // Обязательное завершение
{
// Закрыть соединение nо · любому
con.CloseO;
}
}
</script>

<html XmInS= ' huр ://www.wЗ.or!j'1999/xhtml''>


<head id =' 'Неаdl '' runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="forml " runat="server''>
<asp:Label ID="lblInfo " runat:::::"server" />
< Ьг />
< Ьг />
<asp:Button ID="AddEmployee " runat="server"
Теxt=''Вы nолнить транзакцию "
OnClick="AddEmployee_Click " />
<asp:LinkButton ID ='ЪtnRеsu!t" runat="server"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Po stВ ac k U rl="~ ffes tDataReader. aspx''>


Пока зать списо к< /а sр:LinkВuttоп>
</fоПll>
<lbody>
<lhtml>

Листинг Код страницы TestTransactionSave.aspx


частичного отката транзакции

• r;:;'выполните страницу и убедитесь, что откат вы п олн яется


только до точки сохранения, а п ринимается только результат

вы п ол н е н ия предыдущей команды (ил и блока команд) транзакции

Фабрики поставщиков

Классы поставщиков о п ти мизированы под конкретный ти п источника


данных. Производители , разрабатывающие новую структуру и сточника
данных , должны заботиться и о р азработке соответствующего типа
п оставщика, чтобы эти м источником данных могли пользоваться
п рограмм и сты (мы с вами) в своих приложениях. Но традиционный
п ереход на н овый тип п оставщика требует существенной переделки кода
п риложения , что н е всегда у,цобно для про граммистов. Поэтому в
ASP.NET 2.0 п редусмотрены с п ециальные классы , которые позволяют
''подкругить '' настройки только в одном месте , общедоступном для всех
страни ц п риложения или группы стра н иц без необходимости
и зменения кода в каждой ст р анице, использующей поставщик. Такой
механизм называется фабриками поставщиков.

Основная идея модели фабр и к замючается в том, что можно


и спользовать единствен ный объект-фабрику для создания всех прочих
н еобходимых для ко н кретного поставщика объектов. Но это МОЖНО
выполни ть и созданием конкретных объектов поставщика . Самое
главное у,цобство замючается в том, что ко н кретную фабрику
п оставщика можно создавать из обобще нн ого масса фабрик
System . Data . Соттоп . DbP r oviderFactories прогрйЛ1Л1НЫЛ1

спо собом: , используя ин формацию , заложенную в файлы web .config (в


маСllПабах конкретного приложения) или тасhinе.соnfig (в маСllПабах
конкретн ого компьютера-серве р а)

<?xml vеrsЮ п="l . О '?>


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

< сопfigшаtioп>
<connectionStrmgs>
<add name=''Northwind '' connectionString= ''Data Sошсе= lо саllюst;
Initial Catalog=Northwind ; user id=sa; password= ;"/>
</cormectionStrings>
<system.data>
<DbProviderFactories>
<add name= ''S qIC~ent Data Provider" invariant= "System.Data.S qIClient"
type="System Data.Sq IС Iient.Sq IС IientF actory" />
<add name= "Odbc Data Provider" invariant= "System.Data.Odbc"
typ e="SystemData.Odbc.OdbcFactory" />
<add name= "OleDb Data Provider" invariant= "SystemData.01eDb "
typ e="SystemData.OleDb.OleDbFactory" />
<add name=' 'OracleClient Data РгоvЮег" invariant="System.Data.OracleC
typ e="SystemData.Orac leClient.Orac1eClientFactory" />
<lDbProviderFactories>
</system.data>
<system.web >
<compilatio n debug= ''true''/>
</system. web>
</сопfigшаtioп>

Листинг Пример регистрации фабрики в файле web.config

Этот шаг реrn.страции идентифицирует коллекцию фабрик с


идентификатором пате, значение которого у,цоб но принять подобным
и ме ни п оставщика. Конкр ет ную фабрику мож но прочи та ть и з кода по ее
ид е нтификатор у.

Обобщенный кл асс

System . Data . Common . DbP r oviderFactories имеет

ст атич еский метод GetFactory(string) , который возвращает


объект конкретной фабрики , указанной в строке аргумента. Н а прим ер,
для случая явного указания в коде конкретной фабрики это будет
вы глядеть так

string fuctory = ''SystemData.SqIClient'';


System.Data.Common.DbProviderFactory provider =
5 ystem. Da ta. С о mmo п. D Ь Р roviderF actories.GetF actory( fucto гу);

'"
в.м. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

Получив конкретную фабрику из строки аргум е нта и ли


конфигурационного файла далее с ко н кретным поставщиком можно
работать ч е рез объ е кт p r ovide r одн оименн ой фабрики , уста навливая
соеди нение с БД и посылая в нее SQ L-за просы. Для создания объектов
Connection и Command иcnо л ьзуются методы объекта (например ,
p r ovide r ) фабрики CreateXXX () , которые возвращают эти
объекты

System.Data,Commoo ,DbProvt1erFact ~ D • СгеаtеСоmm ю::J О


$ CreateComm zn::&.i:1er O
$ СгеаtеССП1еСЬ:xl О
$ СгеаtеССП1еСЬ:xlStrГф.jder О
$ CreateDataAclvterO
$ CreateDataSc:uceEru meratcr O
• CreatePif"a meterO
v: DbPrС'С"С~Wk·mе"осЮ,crС'у'оlуremsкu ,~".,",>~,с.,",уrnс""') 1
'!!f! Cif"lCreateDataSc:uceEru meratcr

Для создания незав и симо го от поставщика ун ив ерсальн ого кода мы


должны исходить из то го, что не знаем зара н ее тип поставщика.

По этому взаимодействовать с источником данных нужно то лько через


методы объекта фабрики , возвращающие специфич ны е объекты
Connection , Command. Parameter , DataAdapter базовых
классов DbConnec ti on , DbCommand , DbPa r ameter.
DbDa t aAdapte r .

Пример независимого от поставщика кода с

использованием фабрик

Чтобы лучше понять, как все вышесказанное работает, р ассмотрим


при мер SQL -запроса, реализованно го на странице TestDataReader.aspx.
Первый шаг - настроить в файле web.config строку соединения, и мя
по ставщика и текст SQL-запроса.

• ~Откорректируйте файл web.config, чтобы он окончательно


выглядел следУЮЩИМ образом

<?xml version= ''l .O'?>

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

< сопfigшапоп>
< соnпеспопStrings >
<add name=''N orthwiпd" соnпеспопStгiпg="Dа tа Sошсе=lоса:
Iпitial Саtаlоg=Nоrthwiпd; user id=sa; password=;"/>
</соппесtioпS triпgs >
< аррSеttiпgs >
<add key= "factory" Vallle="System.Data. SqIClient" />
<add key= "employeeQllery" vallle= ''SELECT >1< FROM Emplo
</аррSеttiпgs >
<system.web >
<compilation debllg=''true''/>
</system. web >
</соnfigшапоп>

Листинг Дополнение файла web. config для применения

обобщенного хода

• ~Создайте из копии TestDataReader.aspx новую страниц у с


име н ем Tes t Factory . азр х, назначьте ее стартовой и
заполни те следующим кодом

<%@ Page Language="C#" %>

<script ruпаt= "server''>

protected уою Page_Load(object sепdег, ЕvепtAгgs е)


(
// Получить по Юlючу фабрику из файла web .config
stгiпg factory = System.Web.Configuration.
WеЬсо пfigurаПоnМапаgег.А рр Sеttiпgs["fасtо гу"];
SystеmDаtа.Соmпюп.DЬРгоvidегFасtогу provider =
5 ystem Data. С опurю п. Db ProviderF acto ries. GetF acto ry( fa ctory);

// Использовать фабрику для получения объекта соединения


// и извлечь строку соединения из файла wеЬ.сопfig
SystеmDаtа.Соmпюп.DЬСо nпесПоп соп =
ргоvidег. С геаtе Со nпесtiопО;
соп.СоnпесПопStгiпg = System Web. C onfiguration.
WebC опбgша по nм anager. С оnпесtio nS triпgs[ "N о rthwind "]. С о пn
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

// Создать базовый объект DЬСоmmaпd. Для е го настройки


// и извлечь по ЮIючу команду из файла wеЬ.сопfig
SystеmDаtа.Соmпюп.DЬСоmmaпd cmd = provider.CreateComma
сmd.Соппесtiоп:= соп;
сmd.СоmmaпdТуре := Systеm.Dаtа.СоmmaпdТуре.Техt;
сmd.СоmmaпdТехt = Sуs tеm.WеЬ.СопfigurаtЮп.
WеЬСо пfigurаtiопМапаgеr.А рр Sеttiпgs["еmр lо уееQllеry'1;

// Создаем ссылку на вспомогательную строку


System Теxt.Striпg8uildеr htmlStr:= пеw StriпgВuildеr("'');

usiпg (сап)
{
// Открыли соединение
соп.ОрепО;

// Выполняем обобщенную командУ и получаем результиру


SystеmDаtа.Соmпюп.DЬDаtaRеаdеr reader =
cmd. Execllte ReaderO;

// Перебираем все записи результирующего набора


// и строим НТМL-строку
while (reader.Read())
(
htmlStr.Аррепd("< li> СлужащиЙ '');
htmlS tr. Ар pend (read er[ 'Тit1eO fC о шtеs у"]);
hunlStr.Append(" < Ь > ");
htmlS tr. Ар pend (read er. GetS triпg( 1));
hunlStr.Append("<!b>, '');
htmlStr.Аррепd(rеаdеr.GеtStriпg(2));
htmlStr.Append(" - работает с ' ');
htmlS tr. Ар pend (read er. GetDate Тnnе( 6) .То S triпg("d ''));
hunlS tr. Ар pend ("<Ili> ',;
)

// Закрываем набор данных


reader.CloseO;
}

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

// Выдаем результаты запроса


IbllпfО.Техt = hunlStr.тоStriпgО;
}
</script>

<html xmIпs= ' huр ://www. wЗ.or&,1999/xhtml" >


<head runat="server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="form1" nшat= "sе rvег ''>
<div>
<asp:Label ID="lb Unfo " nшat="sе rvег" Text=''Label''> </asp:Label> <
</fonn>
</body>
<lhtml>

Листинг Страница TestFactory.aspx для реализации


независимого от поставщика хода

• ~ыплнитеe страницу TestFactory.aspx. Должен получиться


такой же результат, что и на странице TestDataReader.aspx, а
именно

• Служащий Ms. Oavo lio, Nancy - работает с 01.05.1992


• Служащий Ог. Fuller, Andrew - работает с 14.08.1992
• Служащий Ms. Leverling, Janet - работает с 01.04.1992
• Служащий Mrs. Peacock, Margaret - работает с 03.05. 1993
• Служащий Мг. Buchanan, Steven - работает с 17.10.1993
• Служащий Мг. Suyama, Micrnel- работает с 17.10.1993
• Служащий Мг. King, Robert - работает с 02.01.1994
• Служащий Ms. СаПашп, Lаша - работает с 05.03. 1994
• Служащий Ms. Oodsworth, Аппе - работает с 15.11.1994
• Служащий 3 иборов , Алексей - работает с 07.05.2007

Чтобы убедиться, что код получился действительно универсальным и


настройка на конкретного поставщика осуществляется только в файле
web.config, пом еняем поставщика в этом файле без изменения кода
самой страницы.
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• 1J$0ткорректируйте файл web.config, чтобы он окончательно


выглядел следУЮЩИМ образом

<?xml version= "l.O'?>


< сопfigшаtiоп>
<connectionStrings>
<add name=''N orthwind" connectionString= "Provider=SQ LO L
ln.itial Catalog=No rthwind; user id=sa; passwo rd=;"I>
</connectionS trings >
<appSettings>
<add key= "factory" value= "System.Data.OleDb" 1>
<add key="emp loyeeQuery" value="SELECT >1< FROM Emplo
</appSettings>
<system.web >
<compilation debug=''true''l>
</system. web>
</соnfigшаtiоп>

Листинг Изменение поставщика в файле web. confiq для

проверки обобщенного хода

• ~ сполните страницу TestFactory.aspx для нового поставщика ,


указанного в файле web.config, и убедитесь, что прежний код
страницы ге н е рирует тот же самый результат, но уже с новым
поставщиком

Механизм примен е ния фабрик поставщиков не решает всех проблем ,


связанных с разработкой независимого от поставщика кода. Например ,
не существует обобщенных объектов ИСЮlючений базы данных, а только
специфичные для конкретных поставщиков. Поставщики MOryr
различаться некоторыми специфическими параметрами или
поддерживать специальные средства, недоступные для общих базовых
классов. Тем не менее , продемо нстрированных возможностей в
большинстве практических случаев может быть достаточно для
написания независимого кода страниц.
В.М. СН"",,,В

~T I@) ГJ I

С не т'0$ (
-

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Компоненты данных ADO.NET


Построение компо н е н та доступа к данным . Созда ни е страницы для
одноразовой зап иси хранимых процедУР. Добавление класса-оболочки
для доступа к полям да нны х. Добавле ни е масса-оболочки для
операций с данными. Библиотечный класс DataSet и автономные
данные . Класс DbDataAdapter. Работа с м н ожествен ны ми таблицами и
отношен и ями в и звлечен ны х автономных данных. Поиск определенных
строк в извлеченных авто н омных данных. Знакомство с механизмом
при вязки извлекаемых автономных данных . Сортир овка извлеченных
автономных данных с п омощью DataView. Фильтрация извлеченных
автономных данных с п омощью DataView. Фильтрация извлеченных
автономных да нны х в DataView с установкой отношений. Добавление к
автономным да нны м вычисляемых столбцов. Добавле ни е к
автономным данным вычисляемых столбцов для связанных таблиц.

Файлы к лекции Вы можете скачать здесь скачать:

httр :l/оkl . iпtШ . ruld е р аrtmeпtliпtеmеtlр rasp netl 12/12 .пр .

Как правило, в практических при ложениях создание соединения и


доступ к да нны м оqюрмляется в виде отдельного класса , который
назы вают компонентом данных. В н его также вмючают класс
Da taSet , который загружает данные и играет роль источника данных
даже после закры тия соединения с базой данных. Объект Da taSet не
является обязательным для страниц ASP.NET, однако он предоставляет
большую гибкость в работе с да нны ми, вмючая навигацию , фильтрацию
и сортировку.

Компонент дан ных как класс должен содержать все необходимые


методы и свойства для работы с данными . Чтобы выполнить операц ию
базы данных, на странице создается экземпляр этого класса-компонента
данных и вызываются соответствующие методы. Рассмотрим сп особы
создан ия этого вспомогательного п ользовательско го масса .

Построение компонента доступа к данным

При созда нии хорошо спроектирова нн ого масса-компоне н та данных


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

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

1. Быстрое открытие и закрытие соединения. Соеди н е ния никогда


не должны Уде рживаться открытыми и клиент никогда не должен

ими ynравлять. Удерживаемое открытым соединение за нимает


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

4. Запрет для клиента указывать пар аметры строки соединения. Э Т О


нарушает безопасность и ослабляет использова ни е пулов
соединений, которые тр ебуют точных совпадений в повторных
соединениях.

s. Исключение во змож ности соединения под кrJИентским


идентификатором ПОЛЬЗ0вателя. Ауген тификацию и
ограничение прав пользо в ателя нужно выяв лять отдельно и

заранее, а зат ем подключ аться к базе данных от своего имени с


п оследую щим формированием нужного SQL-запроса. Э ТО
исключит возможность вариации параметров в строке

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


быстрее, чем попытка выполнения запроса от имени

некорректной учетной записи с ожиданием ошибки.


б. Ограничение количества информации, пр едоставляемой
пользов ателю за оди н запрос. Ка ждый за пр ос пользователя
долже н благоразумно выбирать л ишь ту информацию , которая ему
действитель но нужна . Необходимо инте нсивно использовать в
SQ L -за про сах конструкцию WHE RE или ТОР, ограничивающие
диапазон выборки данных . ЭТО р азгрузи т как саму базу да нны х,
так и сеть передачи данных клиенту.
7. По -возможно ст и использовать отдельный класс для каждой
таб ли цы базы данных или ло гиче ски связан ной rpynnbI таблиц.
8. Запросы к базе данных выполнять через соответствующие
тщат ельно р азработан ные и отлаженные хранимые процедуры.
Это обеспечит долж ную безопасность и быстродействие.

На следУЮщем рисунке пока за н рекомендуемый многослойный дизайн

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

работы с базой данных.

Приложение ASP.NET База данных


1"-
Сп е Цi-1фИЧ НЫЙ
ПОЛЬЭОВ<lтел ьсl. ~Й
Д ЛЯ табли цы
~ нтеfФe~(.
(\'Ve Ь-с:тра 1'1'" Ц8) f=: по nьэоваiе льс~",й
кла сс Аа нн ых
хран има я
процед ура
=:: Табnица
да нны  x

'-......
Реализуем этот простой диза йн в непростом примере . Разработаем
страницу, в которой БУдем работать с таблицей Emp l oyees учеб н ой
базы данных Northwind .

• ~Создайте новый сайт командой FilelNewlWeb Site с именем


WebS i te8
==:-----.11~
Т""'pJ""" Гi! ;O;:

~ ~ ~ ~
A'Pi'ET~ дSP , OET ~ Pe<x", II'J eb Errpty Web
S ii> s....t. S i.. st;o:", к< S i.,

Se:>fchOn l re

Iд bI ...... ASP. fEТ I'!оь '"'"


Loca oo : СIFIС
,~о,с.оо
=":---iJ:lI '\I'JEВIA'Р I\ET 2 fJVЗ) K~HTЫ ~_, i>OO,f.E~ iJ 8"0\01"'" ,

I v~u" CI

Мы хотим создать структурированный код в ви де ком п онента да нны х,


который будет состоять из ЮJaсса-оболочЮ1 доступа к полям таб лиц ы и
масса обработЮ1 зап исей таблицы. Хранимые процедуры записываются
в базу да нн ых один раз на этапе проектированuя, но мы создадим
отдельную страницу, через которую за пишем хранимые процедуры
п рограммно , выполнив ее только один раз.

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Создание страницы для одноразовой записи хранимых


процедур

Прежде чем начать кодировать лоrnку доступа к таблице Emp l oyees,


создадим и запишем в базу данных набор хранимых процедур SQL·
запросов , необходимых для извлечения , вставки и обновления
информации. Хранимые процедуры· это ничто иное, как именованные
SQL·КOMaHAbI, хранящиеся прямо в базе да нны х . Удобство хранимых
процедур в их гибкости и безопасности· они принимают фактические
значения параметров SQL·запроса и недоступны вне кода приложения.

• IJ$Добавьте к приложению Ю)мандой Website/Add Еxistiпg ltem


страницу TestStoredProcedure.aspx из каталога WebSite7 и
п е реименуйте ее в Saves t o r edProcedure . aspx
• r;;,;:rАналоrnчным образом добавьте к прилож ению файл
Web.Config из каталога WebSite7 с готовой СТРОЮ)Й соединения и
отЮ)рректируйте его так

<?xml version= "l.O'?>


< сопfigшаtiоп>
<connectionStrings>
<add name=''N orthwind " connectionS tring="Data Source=!oca:
lпitia! Cata!o g=Northwind ; user id=sa; password=;" 1>
</соппесtioпS trings >
<system.web >
<compilation debug=''true''l>
</system. web>
</configuration>

Листинг. Файл Web.Config


• Г;:;=Откорректируйте страницу 5 а veS to red Р rocedure .asp х
следУЮЩИМ образом

<%@ Page Lапguаgе="С#" %>

<script ruпаt= "server''>

11 Объявления хранимых проц едур


11 Вставка записи
'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

string sq 11 =
"CREAТE PRO CEDURE I пsегtEшр юуее "
+ "@ ЕшрюуееID int ОUТPИТ,"
+ "@ FirstNаше varchar(10),"
+ "@ LastName varchar(20),"
+ "@ ТrtlеОfCоuпеsу varchar(25) "
+ "AS "
+ '1NSERT INTO Ешрlоуее s"
+ "(ТitleOfCourtesy, LastName, FirstNа ше, HireDate)"
+ ' VALUES(@ ТitleOfCourtesy, @ Lа stNа ше, @ FirstNаше, GЕШД
+ ''SET @ EmployeeID = @@ IDE NТlТY";

// Удале ни е за писи
string sq 12 =
"CREAТE PRO CEDURE DeleteEmployee "
+ "@ ЕшрюуееID int "
+ "AS "
+ ' 'DELEТE FROM Ешрloуееs WHERE Ешр lоуее ID = @ Employee

// Обновление за писи
string sq IЗ =
"C REAТE PRO CEDURE Uр dаtеЕшрlоуее "
+ "@ ЕшрloуееID int, "
+ "@ FirstNа ше varchar(10),"
+ "@ LastName varchar(20),"
+ "@ ТrtlеОfCоuпе sу УагсЬаг(25) "
+ "AS "
+ 'UPDAТE Ешрlоуееs "
+ ''SET ''
+ ''FirstName = @FirstName,"
+ ' 1.а stNа ше = @ LastName,"
+ ' ТitleОfCошtеsу = @ ТitleOfCourtesy "
+ 'W HERE ЕшрlоуееID = @ЕшрloуееID ";

// Выбрать все
string sq 14 =
"C REAТE PRO CEDURE GetAllEmployees "
+ "AS "
+ ''SELECT ЕшрloуееID, FirstName, LаstNаше, ТitlеОfCоuпеsу"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

+ ''FROM Employees";

// П одс читать число записей


string sq 15 =
"CREAТE PRO CEDURE СоuпtЕmр lоуееs "
+ "AS "
+ "SELECT COUNT(EmployeeID) "
+ ''FROM Employees";

// Выбрать запись
string sq 16 =
"CREAТE PRO CEDURE GetEmployee "
+ "@ EmployeeID int "
+ "AS "
+ ''SELECT EmployeeID, FirstName, LаstNаше, 1itleOfCourtesy "
+ ''FROM Employees "
+ 'W HERE EmployeeID = @EmployeeID";

protected void Page_Load(object sепdег, ЕvепtAгgs е)


(
// ИЗБлеюlИ строку соединения из wеЬ.со пfig
string соппесtString = System WеЬ.Сопfigшаtloп.WеЬСоnfigшаtiопr
СО ппесtio nS trings['N о rthwind '1.С о nnесtlo nS tring;

// Создал и объект соед ин е ния


SystemData.SqIClient.SqICo nnection соп =
new 5 ystem.Data. SqlC lient. SqlСоппесtioп( co nnectS tring);

// Создал и объект Command


SystemData.SqIClient.SqICommand cmd =
new System.Data. SqIClient.SqICommandO;

// Н астрои л и объект Command


cmd.Connection = соп;
cmd.CommandType = SystemData.CommandType.Text;

IblIпfо.Техt = "";

// Открываем соединение Б безопасном режиме


ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

try
{
со п.ОрепО;
}
catch
{
co n.CloseO;
геtшп;

// Вblполняем командЬ! в безопасном режиме


// Удаляем процедУРbI на случай повторного запуска этой стр
try
{
cmd .CommandText = ''DROP PROCEDURE InsertEmployee";
cmd .ExecuteN onQueryO;
Ibllnfo.Text += 'nроlШlИ \''DROP PROCEDURE I nsеrtEmрюуеЕ
}
catch { }
try
{
cmd .CommandText = ''DROP PROCEDURE DeleteEmp loyee";
cmd .ExecuteN onQueryO;
Ibllnfo.Text += 'nроlШlИ \''DROP PROC De leteEmployee\"<br ;:
}
catch { }
try
{
cmd .CommandText = ''DROP PROCEDURE UpdateEmployee";
cmd .ExecuteN onQueryO;
Ibllnfo.Text += 'nроlШlИ \''DROP PROCEDURE UpdateEmp loj
}
catch { }
try
{
cmd .CommandText = ''DROP PROCEDURE GetAllEmployees";
cmd .ExecuteN onQueryO;
Ibllnfo.Text += 'nРОlШJи \''DROP PROCEDURE GetAllEmploy€
}

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

catch { }
try
{
cmd .CommandText = ''DROP PROCEDURE СОШltEmр loуееs";
cmd .ExecuteN onQueryO;
IblInfo.Text += 'nРОlШJи \''DROP PROCEDURE СОШltЕmрlоуе
}
catch { }
try
{
cmd .CommandText = ''DROP PROCEDURE GetEmployee";
cmd .ExecuteN onQueryO;
IblInfo.Text += 'nРОlШJи \''DROP PROCEDURE GetEmp loyee\'
}
catch { }

// Выполняем команды в безопасном режиме


// Добавляем в базу данных хранимые процедУРЫ
try
{
cmd .CommandText = sql1;
cmd .ExecuteN onQueryO;
IblInfo.Text += 'nРОlШJи \"CREAТE PROCEDURE InsertEmplo
}
catch { }
try
{
cmd .CommandText = sql2;
cmd .ExecuteN onQueryO;
IblInfo.Text += 'nРОlШJи \"CREAТE PROCEDURE De leteEmpl<
}
catch { }
try
{
cmd .CommandText = sqlЗ;
cmd .ExecuteN onQueryO;
IblInfo.Text += 'nРОlШJи \"CREAТE PROCEDURE UpdateEmp
}
catch { }
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

try
{
cmd.CommandText = sq14;
cmd. ExecuteN onQueryO;
IblInfo.Text += ' nроlШlИ \"CREAТE PRO CEDURE GetAllEmp!<
}
catch { }
try
{
cmd.CommandText = sql5;
cmd. ExecuteN onQueryO;
IblInfo.Text += ' nроlШlИ \"CREAТE PRO CEDURE CountEmplc
}
catch { }
try
{
cmd.CommandText = sq!6;
cmd. ExecuteN onQueryO;
IblInfo.Text += ' nроlШlИ \"CREAТE PRO CEDURE GetEmp!oye

}
catch { }
finаПу
{
con.CloseO;
}
}
</script>

<html XmInS= ' huр ://www. wЗ.or&,1999/xhtml' '>


<head ю =' 'Неаdl '' runat= "server''>
<tide > Untitled Page</tide>
<lhead>
<body>
<form id ="forml " runat="selVer''>
<asp:Labe! ID="lb lInfo " runat="selVer" />
</fonn>
</body>
<lhtml>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Листинг Код страницы SaveStoredProcedure.aspx


одноразовой записи хранимых процедур

• ~ыполните страницу SаvеStогеdРroсеdше.аsрх, чтобы


добавить в базу хранимые процедуры, которые мы далее будем
использовать при раз р аботке примера

Добавление класса-оболочки для доступа к п олям


данн ых

Для облегчения доступа к да нн ым таблицы Етр 1 о уе е s учебной базы


данных Nor t hwind создадим ЮJaсс · оболочку с имен ем
Emp l oyeeDetai l s , который представ и т нужные нам поля в виде

одноименных открытых свойств .

• ~ ерез контекстн ое меню корня Web-дерева создайте каталог с


п редопределен ным именем Арр Code
SOOGC<1 Exple<er - С:\ .\WebS,te8\ ... -i=' Х

. r:." Арр _Data iili BuikJ Web ~te


I!Ш Save5toгedPгoceduгe,as Publsh Web Site
,..... ~ Web.Config
~ Add New Item."
§... Md Ex istilg Item" .
New FoIder

Bin I Add ASP.NEТ Folder ~I


App_Cod€
I Add Refererкe."

Арр _GlobalResollГces Add Web Reference


Арр _LocalResollГces Щ View Class Diagram
App_WebReferences
~ Сору Web Site
Арр _BroVfsers sшtорооns ...

_те
~ View in Browser

ш
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• ~ызовите контекстное меню для созданного каталога


Арр Code и вы п олните командУ Add New Item, чтобы добавить
класс С# с именем EmployeeDeta i ls в прилож ение
аа. . . . . .~.ш~ ..=m=ШDDвm~~~ ri! о:::


T""l""»>

~ !;]J ..;
[!jJ ~
IШII Тех! fi le D<Ot1oS,t

"- е:,,, D"Ч , m

Iдn " "l'1:f [~" doc l..-,Iirn


N3w IE "l'''J''~~ ' ''
iJ г PI..:ec d~ I sepdГ& lIе
Г ... юm't?rr""J"

Сд'<:eI I1

• ~3ап ол ни те созданную оболочкой заготовку класса следУЮЩИМ


КОДОМ

using System;

риыic class ЕmрюуееDеtails


(
// Общий конструктор
риыic EmployeeDetails(int еmpюуееID , strmg firstName,
string IastName, string titleOfCourtesy)
{
trus.employeeID = employee ID;
trus.firstName := firstName;
trus.lastName = Lз stNа mе ;
trus.tit1eOfCourtesy = titleOfCourtesy;
}

// Конструктор по умолчанию обязателен ,

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

// если создали общий конструктор


риыic EmployeeDetailsO
{
}

// Добавляем свойства масса


private int employee ID;
риыic int EmployeeID
{
get { геturп employee ID; }
set { employeeID := value; }
}
private string firstN аmе;
риыic string FirstN аmе
{
get { геturп firstN аmе; }
set { firstName := value; }
}
private string IastName;
риыic string LastName
{
get { геturп IastName; }
set { IastName := value; }
}
private string tit1eOfCourtesy;
риыic string 1itleOfCourtesy
{
get { геturп tit1eOfCourtesy; }
set { titleOfCourtesy:= уаluе; }
}
}

Ли с тинг . Ко д х л а с са Empl oyeeDetail s . cs

Добавление класса- оболочки для о п ераций с данны ми

С о зд адим ма с с, кото рый в свои х методах испол ьзует зап иса нн ы е н ами
ран ее хранимы е пр о цедур ы S Q L -запро сов к та блиц е Employees
уч еб н о й базы да нных No r thw i nd . Вос п ол ьзуемс я н о вым с ред ством

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

частичных массов ( partial ) версии языка С#2 . 0 и размести м масс


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

• Г;;:;=Вызовите контекстное меню для созданного каталога


App_Code и выполните команду Add New ltещ чтобы добав и ть в
пр иложе ни е масс С# с и менем EmployeeDB в файле
Emp!oyeeDB.cs
• ~ з объявлений пространств имен using , автоматически
с генер ир ованных оболочкой, оставьте только us i ng Sys tem ; и
добав ьте в заголовок объявле ни я масса мючевое слово
ра r t i а 1 (частичный) , чтобы дать указание ком пи лятору считать
одноимен ны е массы в отдельных файла х единым массом (нам
так удобнее р азместить код отдельных методов)
• ~Сделайте в каталоге App_Code шесть копий файла
Emp!oyeeDB.cs с именами
1. I nse r tEmployeeDB . cs
2. Dele t eEmployeeDB . cs
з . Upda t eEmployeeDB . cs
4. GetAI I EmployeeDB . cs
5. Coun t Emp l oyeeDB . cs
6 . GetEmployeeDB . cs
• Г;:;==Заполните первую часть заготовки масса EmployeeDB в
файле Emp!oyeeDB.cs следующим кодом

using System;

using Sуstеm.WеЬ.Сопfiguгаtiоп;

public рапia! class EmployeeDB


{
private string соnnесtiопStгing;
риыic EmployeeDBO
{
// Извлечь из файла wеЬ.со пfig стр оку соеди н е ния по умол чан
соnnесtiопString = WеЬ С опfigшаtionМапаgег.
Со ппесtюпS trings[''N о rthwind "]. С о nnectio пS tring;
}
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

риыic ЕmplоуееDВ(stгing со nnесtiопS tгingС ustom)


{
// Извлечь из файла wеЬ.со пfig другую строку соеди н е ния
соnnесtiопString = WеЬСопfigшаtio nМ апаgе г.
Со ппесtio nS trings [ со nnес оо пS tringC usto m]. С onnectio nS tring;
}
}

Листинг. Часть хласса EmployeeDB в файле EmployeeDB.cs

Обратите внимание , что мы п о ходу дела доб авляем к коду необходимые


п ространства имен инструкцией us in g .

в п е рвой части масса EmployeeDB мы п редусмотрели два


конструктора дл я и звле ч е ния строки соединения и з кофигурационного
файла. В других частях масса Employ eeD B мы ре ализуем методы для
выполнения операций с таблицей через соответствующую хр анимую
nроцедуру, в каждой части по одному метод.у. Вот око нч ател ьный код
этих частей масса , в каждой из которых мы используем безопасный к
исмючениям подход

using System;
using System.Data;

using System.Data.SqlClient;

public partial class EmployeeDB


(
public int InsertEmp loyee(EmployeeDetails еmp)
(
SqlСо nnесtiоп соп = пеw SqlConnection(connectionString);
SqlСоmmaпd спx:l = new SqlCommand('1nsertEmployee", соп) ;
сmd. С оmmaпdТуре = соmmaпdТуре.StoгеdРгосеdше;
cmd.Parameters .Add(new SqIParameter("@FirstName", SqlDbType.NVar
cmd.Parameters["@FirstName"].Value = emp.FirstName;
cmd.Parameters .Add(new SqIParameter("@LastName", SqIDbType.NVal"1
cmd.Parameters["@ LastName"]. Value = emp .LastName;
cmd.P arameters .Add(new SqlP arameter("@ TltleOfCourtesy", Sq IDbType.:

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

cmd.P агаmetеrs[ "@ 1it1eОfCошtеsу" ].Vаluе = еmp. Trt1eO fCourtesy;


cmd.P arameters.Add(new SqlP arameter("@ EmployeeID ", SqIDbType .Int,
cmd. Р arameters ["@EmployeeID"]. Direction = Р arameterDirectio п. О utp ut;

try
(
соп.Оре пО ;
cmd.ExecuteNonQuery();
геtшп (int)cmd.Parameters["@EmployeeID"].Value;
)
catch
(
throw new АррlicаtiоnEхсерtioп("Ошибка данных.');
}
fiпаlly
(
con.CloseO;
)
}
}

Листинг
InsertEmployeeDB.cs
Часть ICласса EmployeeDB • файле

using System;
using System.Data;

using System.Data.SqlClient;

public partial class EmployeeDB


(
public void DeleteEmployee(int emp loyeeID)
(
SqlConnection соп = new SqlConnection(connectionString);
SqlCommand сшd = new SqlCommand(''DeleteEmployee'', соп);
cmd.CommandType = соmmaпdТуре.StогеdРгосеdше;
cmd.P arameters.Add(new SqlP arameter("@ EmployeeID", SqIDbType .Int,
cmd.Parameters["@EmployeeID"].Value = employeelD;

try
'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

(
со п.Ор е пО ;
cmd.ExecuteNonQuery();
}
catch
(
throw new АрросаtiоnEхсерtloп("Ошибка данных.'');
}
finally
(
con.CloseO;
)
}
}

Листинг
DeleteEmployeeDB.cs
Часть ICласса EmployeeDB • файле

using System;
using System.Data;

using System.Data.SqIClient;

public partial class EmployeeDB


(
public void UpdateEmployee(int employeeID, string firstName,
string IastName, string tideOfCourtesy)
(
SqlConnection соп = new SqIConnectlon(connectlonString);
SqlCommand спx:l = new SqICommand(''UpdateEmployee'', соп);
cmd.CommandType = соmmaпdТуре.StогеdРгосеdше;
cmd.P arameters.Add(new SqlP arameter("@EmployeeID", SqlDbType .Int,
cmd.Parameters["@EmployeeID"].Value = employeelD;
cmd.Parameters.Add(new SqlParameter("@FirstName", SqlDbType.NVar
cmd.Parameters["@FirstName"].Value = firstN аmе;
cmd.Parameters.Add(new SqlParameter("@LastName", SqlDbType.NVaf"1
cmd.Parameters["@LastName"]. Value = IastName;
cmd.P arameters.Add(new SqlP arameter("@TJtleOfCourtesy", Sq lDbType.:
cmd.P агаmetеrs["@1it1eОfCошtеsу"].Vаluе = titleO fCourtesy;
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

try
(
со п.Ор е пО ;
cmd.ExecuteNonQuery();
}
catch
(
throw new Ар росаtiоnEхсе рtloп( "О ши бка да нных.'');
}
fiпаlly
(
con.CloseO;
)
}
}

Листинг
UpdateEmployeeDB.cs
Часть ICласса EmployeeDB • файле

using System;
using System.Data;

using System.Data.SqlClient;
using System. Collectlons.Generic;

public partial class EmployeeDB


(
public List<EmployeeDetails> GetAllEmployeesO
(
SqlCo nnection соп = new SqlConnection(connectlonString);
SqlCommand сшd = new SqlCommand("GetAllEmployees", соп);
cmd. CommandType = соmmaпdТуре.StогеdРгосеdше;

11 Создать коллекцию для всех за пи сей


List < Ешрloуе еDе tаils> ешрloуееs = пеw List< ЕшрloуееDеtails > О;

try
(
со п .Оре пО ;
SqlDataReader reader = cmd.ExecuteReaderO;
'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

while (reader.ReadO)
(
EmployeeDetails еmр = пеw ЕmрюуееDеtаils(
(iпt)геаdег[''ЕmplоуееID'1,
(striпg)геаd er[''F irstN аmе "],
(striпg)геаd er[ '1.astN аmе "],
(striпg)геаd er[ ''Iit1eO fC о шtеs у"]);
employees.Add(emp);
}
геаdег.СЮsеО;
геtшп employees;
}
catch
(
thraw пеw Ар рlicаtiопЕхсе рtloп( "О ши бка да нных.'');
}
fiпаlly
(
со п. СlosеО;
)
}
}

Листинг
GetAIIEmployeesDB.cs
Часть ICласса EmployeeDB • файле

usiпg System;
usiпg System.Data;

usiпg Systеm.D а tа.SqlCliе пt;

public partial class EmployeeDB


(
public iпt Со uпtEmрю уееsО
(
SqlСо nnесtiоп сап = пеw SqIСоnnесtloп(саnnесtloпStгiпg);
SqlСоmmaпd спx:l = new SqIСоmmaпd("СоuпtEmрlоуееs", соп);
cmd. CammandType = соmmaпdТуре.Sto геdРгосеdше;

try
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

(
со п.Ор е пО ;
return (int)cmd.ExecuteScalarO;
)
catch
(
throw пеw АрросаtiопЕхсерtloп("Ошибка данных.'');
}
finally
(
con.CloseO;
)
}
}

Листинг Часть класса EmployeeDB в файле CountEmployeeDB.cs

using System;
using System.Data;

using System.Data.SqIClient;

public partial class EmployeeDB


(
public EmployeeDetails GetEmployee(int employeeID)
(
SqlСо пnесtiоп соп = new SqIСопnесtioп(сопnесtloпStгing);
SqlCommand спx:l = new SqICommand("GetEmployee", сап);
сmd.Соmma пdТур е = соmmaпdТуре.StогеdРгосеdurе;
cmd.P arameters.Add(new SqlP arameter("@ EmployeeID", SqlDbType .Int,
cmd.Parameters["@EmployeeID"].Value = employeeID;

try
(
соп.Оре пО ;
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.Single:
11 Получить п ервую строку
reader.ReadO;
EmployeeDetails еmр = new EmployeeDetails(
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

(int)reader[''Employee ID'1,
(string)read ег [ ''F irstN аmе "],
(string)read ег[ '1.astN а mе "],
(string)read ег [ ''Iit1eO fC о шtеs у" ]) ;
reader.C loseO;
геtшп е mр ;

}
catch
(
throw new АррlicаtiоnEхс е рtloп("О ши б ка да нны х.'');
}
fiпа lly
(
con.C loseO;
)
}
}

Листинг Часть класса EmployeeDB в файле GetEmployeeDB.cs

Вот такой большой , но зато универсальный получился код нашего


компонента, представлен ного двумя классами-оболочками , один из
которых р азбит на части в отдельных файлах из соображений Удобства
программирования. Мы всегда должны помнить, что КОД нужно делать
обозримым, р азбивая на отдельные част и. ЭТО один из при емов снизить
вероятность ошибок, которые, к сожалению, н е и збежны в силу
несовершенства ч еловеческого ума. Обратите внимание на однообразие
структуры методов - эта типизация также снижает ошибки.

Мы видим, что каждый метод сам открывает и закрывает соединение с


базой данных . Все тонкос ти работы с данными скрыты внугри методов.
Наша задача те п ерь , в нужном месте создать эюемпляр класса
Emp l oyeeD B и прави льно вызывать его методы, соблюдая
установленный в них интерфейс. Раз создав это т класс, его можно
применять мно гократно по мере необходимости , не заботя сь об
инкапсулированных в н ем то нкостях программирования. Мы же не
знаем (да и н е хотим знать), как реализованы библиотечные классы
. NET Fr aтe w ork . Мы увере ны , что они БУдУГ работать как надо ,
если прави льно их использовать. Вот это и есть преимущество
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

объектно-ориентированного про гр аммирования во всей его красе:


обращайся прави л ьно к интерфе йсу класса - и все будет р аботать.

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


к данным

Весь код класса-оболочки, который мы разработали выше, теперь нужно


испытать на т естовой странице.

• ~Добавьте к проекту (в корень Web-Аерева) новую страницу с


р азделяемым кодом и именем Tes t Component . asp x

• ~Добавьте на страницу компонент Label и дай те ему имя


lbllnfo
• ~Откройте на редактирование файл подцержки
TestComponent.aspx.cs и наполните его следУЮЩИМ кодом

using System;

using System.Text;
using System.Collecllo ns.Generic;

риыic рапia! class TestComponent: System.Web.uI.Page


(
// Создат ь компонент базы данных
private EmployeeDB db = new ЕmРloуееОВО;

protected void Page_Load(object sender, EventArgs е)


(
lblInfo.Text = "< h2 > Исходная таблица < Ih2 >";
WriteEmployeesList();

in! еmpШ = db.lnsertEmployee(


new EmployeeDetails(O, "Але ксей ", "З иборов ", "С т. ') );
lblInfo.Text += "< h2 > Вставлена 1 запись . < Ih2 >";
WriteEmployeesList();

db. Ое lete Етр 'о уее( етр 1О) ;


lblInfo.Text += "< h2 > Удалена 1 запись. < Ih2 >";

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

WriteEmployeesList();
}

private vою WriteEmployeesListO


(
StringВuilder htmlStr = пеw StringВuilder('"');

List<EmployeeOetails> emp loyees = db.GetAllEmployeesO;


foreach (EmployeeDetails етр in employees)
(
hunlStr.Append("< ~> ');
hunlS tr. Ар pend (етр . Етр 10 уее Ш);
hunlStr.Append(" ');
htmlS tr. Ар репd (еmр .1ideO fC ourtesy);
hunlStr.Append(" < Ь >' );
htmlStг.Аррепd( еmр . FirstN ате);
hunlStr.Append("<!b>, ');
htmlStг.Аррепd( еmр . LastN ате);
hunlS tr. Ар pend ("<Ili> ');
}

int пШ11Еmрlоуее s = dЬ.СоuпtЕmplоуееsО;


htmlStг.Аррепd("< hr /> Число записей: < Ь >' ');
htmlS tr. Аррепd (пшnEmр loyees.ToS tringO);
htmlStг.Аррепd("< /Ь> < Ьг />< Ьг />'');
lblIпfо.Техt += htmlStr.ToStringO;
}
)

Листинг Файл поддер*~и TestComponent.aspx.cs тестовой


страницы TestComponent.aspx
• ~ азначьте страницу Теs tСоmропепt.аs р х стартовой и исполни те
ее. Долже н получи ться примерно такой результат

Исходная таблица

• 1 Ms. N arк:y, Oavo tio


• 2 Ог. A ndrew, Fuller
• 3 Ms. Janet, Leverling
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• 4 Mrs. Margaret, Peacock


• 5 М г. 5 tеvе п, Вuсhапа п
• 6 М г. Mk:hael, Suyama
• 7 М г. Robert, К iпg
• 8 Ms. Lа ша , Callahan
• 9 Ms. Аппе , Dodsworth

Число за пи сей: 9

Вставлена 1 за п ись .

• 1 Ms. N arк:y, Oavo tio


• 2 Ог. Andrew, Fuller
• 3 Ms. Janet, Lеvегliпg
• 4 Mrs. Margaret, Peacock
• 5 М г. 5 tеvе п, Вuсhапа п
• 6 М г. Mk:hael, Suyama
• 7 М г. Robert, К iпg
• 8 Ms. Lа ша , Callahan
• 9 Ms. Аппе, Oodsworth
• 99 С т. Алексе й , З и боров

Число за пи сей: 10

Удале н а 1 за п ись .

• 1 Ms. N arк:y, Oavo tio


• 2 О г. Andrew, Fuller
• 3 Ms. Janet, Lеvегliпg
• 4 Mrs. Margaret, Peacock
• 5 М г. 5 tеvе п, Вuсhапа п
• 6 М г. Mk:hael, Suyama
• 7 М г. Robert, К iпg
• 8 Ms. Lа ша , Callahan
• 9 Ms. Аппе, Dodsworth

Число за пи сей: 9

Мы видим, что все работает как н адо . Об р ат и те в н имание, что значение


;о,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

поля EmployeeID при растает на 1 при повторных запусках тестовой


страницы . ЭТО значит, что физически запись не удаляется, а только
помечается на Удаление SQL-запросом DE LE TE, а поле имеет установку

дЛЯ СУБД SQL Server, которая является посредни ком в нашем коде
доступа к данным, автоматичесЮ1 увеличивать значение счетчика.

Библиотечный класс DataSet и авто номны е данные

До сих п ор мы рассматривали код, который работает непосредственно с


физичесЮ1МИ да нн ыми, хранящимися в базе данных, удерживая
соединение на весь п ериод обработЮ1. Такой режим называется
прuсоединенныЛ1. Но более практичесЮ1М БУдет подход , когда
пользователь работает с данными в отсоеди н е нн ом режиме ,
кратковременно ПОДЮlючаясь к базе только для загрузки или выгрузЮ1
данных .

Для таких целей применяется объект Da taSet, который н а п олняется


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

Da taSet имеет методы , которые мо гуг читать и писать данные и

схемы XML, методы для быстрой очистЮ1 И дублирования данных .


Некоторые из этих методов п риведены в таблице .

Некоторые методы DataSet


Метод Описание

Очищает все данны е таблиц , н о не трогает


Clear()
инqюрмацию о схеме и отношен иях

Возвращает точный дубликат Da taSet с тем


Сору 11
же на бором таблиц, данных и отношений

Возвращает Da taSet с той же структурой


Clone()
(таблицами и отн ошениями), но без данных

Принимает н а входе д р угой DataSet и


объединяет его с текущим Da taSe t , добавляя
Merge ()

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Merge () новые таблицы и объединяя данные в


существующих

Возвращают строку данных в ф:Jрмате XML


или инф:Jрмацию схемы для Da taSet .
GetXml() , Инф:Jрмация схемы - это структурированная
GetXmlSchema() инф:Jрмация наподобие количества таблиц , их
имен , столбцов, типов данных и
установленных отношении

Создают таблицы в Da taSet на основе


ReadXml (), существующего докумен та ХМLили докумен та
ReadXmlSchema () схемы XML. Источником XML может быть
файл или другой поток

WriteXml() , Сохраняют данные и схемы Da taSet в файле


Wr i teXmlSchema () или потоке ф:Jрмата XML

Класс Da taSet является сердцем автономного достynа к да нны м. Он


содержит в себе в виде массов-свойств коллекцию из нуля или более
таблиц и коллекцию из нуля или более отношений между таблицами .
Базовая структура Da taSet приведена на рисунке.

'"
в м С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Класс System.Data.DataSet

Коллекция TabIes Колле кция Relations


I I
Класс DataTabIe
Коллекци;; Rows
14J Кла сс DataRelation

~
I Коллекция ParentRelatlons
DataRow
I I
Колле",ц~ Соlumпs

I
14J Кла сс DataRelation

~
I

D..taColumn
I Коллекция ChildRelations
I
Коллекция Constr2llnts

14J
~
I I
Класс DataRelation

- Constralnt
I
I Класс DefaultView
I
Каждая запись Da taSe t пр едставлена как объект Dаt a Row .
DataRow - это контейнер для действительных значений полей. К
полям записи можно обращаться через объект Da t a Row как к
ассоциативному массиву, используя в качестве Юlюча имена полей ,
напри мер , myRow [ " F i eldNaтe " ] .

Все версии измененных строк при редактировании со хр аняются в


Da taSet дл я возможности отката. Удален ны е или добавленные
строки также помечаются соответствующим образом. Следует помнить ,
что информация в физическом источнике данных н е затрагивается
вообще при раб оте с Da taSet , а все изменения производятся в
виртуальном источнике оперативной памяти.

Класс DbDataAdapter

Da taSet никогда н е оставляет открытым соединение с базой данных и


ш
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

закрывает его автоматически сразу после пересылки данных. Он даже


не связывается с источником данных напрямую, а только через
про межугочный объект
Sys tem . Dа t a . Соттоп . DЬDа taAdapter .
Класс DЬDа taAdapte r служит по средником между одним
DataTable в DataSet и источником данных . DbDa t aAdapter
наследует от базового масса
System . Data . Соттоп . DataAdapter и предоставляет три

ЮJючевых метода , прив еденные в таблице

Некоторые методы SystemData.Common.DbDataAdapter


Метод Описание

Заполняет данны м и Da ta Se t за счет выполнения


запроса в свойстве SelectCo mmand . Если запрос
возвращает множественные результирующие наборы,
Fi 11 ( ) то этот метод добавит множество объектов
DataTable за одно обращение. Его можно также
использовать для за пол н е ния данными одного

существующего объекта DataTable


Заполняет Da t а Se t информацией о структуре
Fi l lSchema()
таблицы или м ножества табл иц

Обновляет данные из Da taSet в источник данных


Update ()
(базу данных)

Чтобы позволить DbDataAdapte r изменять данные в источнике ,

н ужно специфицировать объекты


System . Data . Соттоп . DbCommand для свойств
Upda t eCo mmand , InsertCommand, DeleteCommand объекта
DbDa t aAdapte r . Чтобы использовать DbDataAdapter для
напол н ен ия Da taSe t, п отребуется устан овить свойство
SelectCommand .

Класс Sys t em . Dа ta . Соттоп . DbCommand является базовым для


более специализированных ЮJассов

• Sys t em . Data . SqlCl i ent . SqlDataAdapter


• Sys t em . Data . Odbc . OdbcDataAdapter
• Sys t em . Data . OleDb . OleDbDataAdap t e r

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• Sys t em . Data . Or acleClient . Or acle DataAdap t e r

которые в ко н ечном итоге мы и должны и сп ользоват ь в своих

при ложениях .

Прим ер использования DataAdapter и DataSet для


извлечения автономных данны х

Продемонстрируем на п ростом при мере извлечения данных в


результирующий н абор Da taSe t через Оа taAdap t e r . Да нны е будем
и з вл екать из таблицы
Employees учебной базы да нны х No r thwind ,
п одде рживаемой SQL Server. При этом Da taSe t автоматически
создаст соединение , добавит в свою коллекц и ю Data Ta bl es объект
DataTable , в котором каж.цую за пи сь разместит в отдельном объекте
DataRow коллекции DataRows . После это го соединение с базой
да нных будет автоматически ра зо р ва н о.

• r;:;='Добавьте к корневому узлу приложения страницу


TestDataSet.aspx с р азделяемым кодом и сделай те ее стартовой
• ~ омест и те на страниц у элеме н т управлени я Labe l с им ен ем
lbllnfo
• ~Откройте файл подцержки TestDataSet. aspx.cs и н а п олните его
следую щи м кодом

usiпg System;
usiпg System.Data;

usiпg System. WеЬ.Сопfigшаtiоп;


usiпg System.Data.SqIClient;
usiпg System.Text;

public partial class TestDataSet: System.Web.UI.Page


(
protected void Page_Load(object sender, EventArgs е)
{
11 Изв лекаем строку соединения с им ен ем Nо rthwiпd из файла web.c
striпg соnnесtiопStгiпg = WеЬСоnfigшаtioпМапаgег.
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

С о nnеспо nS trings[''N orthwind "]. С оnnеспо nS tring;

11 Формируем строку SQL дЛЯ выборки всех да нных таблицы Emplc


string сопunaпdString:::: "SELECT * FROM Employees";

11 Создаем и настраиваем эюемпляр масса SqlDataAdapter


SqlDataAdapter adapter::::
new SqlDataAdapter(commandString, connectionString);

11 Создаем объект DataSet результирующего набора данных


DataSet dataset := new DataSet();

11 Безопасно заполняем да нными объект DataTable с произвольным


11 именем, например ''Emp loyeesResult'', созданного объекта DataSet
try
(
adapter.Fill(dataset, ''EmployeesResuh'');
}
catch
(
throw new АррlicаuопЕхсерtioп("Ошибка данных.'');
}

11 Перебираем все объекты DataRow с полученным записами


StringВuilder hunlStr = new StringВuilder(''');
foreach (DataRow dr in dаtаsеt.Таblеs[''ЕmрЮуееsRеsult''].Rоws)
(
htmlS tr.Append("< li> ');
htmlS tr.Append( dr[ ''ПdеО fC о urtes у"]. ToS tringO);
htmlStr.Append(" < Ь>');
htmlS tr.Append( dr[ ''F iгstN ате "]. ToS tringO);
htmlStr.Append("<Ib>, ');
htmlS tr.Append( dr[ ''LastN ате '1 .То 5 tringO);
htmlStr.Append("<!Ii>');
}

11 Отображаем полученные данные


lbllnfo.Text:::: "<h2>Список СОТРУдников < Ih2>";
lbllnfo.Text += htmlStr.ToStringO;
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

}
}

Листинг Код файла TestDataSet.aspx.cs

Строка

adapter.Fill(dataset, ''EmployeesResult'');

выполняет строку запроса и помещает результат в н овый именованный


объект OataTable коллекци и OataTables объекта dataset класса
Da taSet . Мы указали явно имя создаваемого объекта Оа t aTable,
которое выбрали п роизвольно. Если этого не сделать, автоматически
будет назначе н о имя по умолчанию.

При заполнении метода adapter . F i 11 () соединение открывается и


закрывается автоматически . Именно его мы заключили в операторы
безопасного кода, перехватывающие возможны е ИСЮlючения. Но можно
открывать и закрывать соединение вручную. Если соединение открыто ,
то OataAdapter только использует его и не будет закрывать по
окончании работы . Э ТО удобно, когда нужно выполнить несколько
последовательных операций с источником данных, используя
OataAdapter . Только нужно не забыть закрыть соединение, когда оно
не ста н ет нужным.

На последнем этапе нашего кода мы опрашиваем коллекцию строк


результирующего набора да нн ых и выводим их в текстовую метку
l bl Inf o . Такой подход к отображению да нны х редко применяется.
Более удобной является техника привязки данных к элементу
управления, отображающему да нн ые. Но эту технику мы рассмотрим
позднее.

• ~ сполните страницу TestDataSet.aspx и получите такой


результат

С пи сок СОТРУдников

• Ms . Nancy, Оауооо
• Ог. Arкlrew, Fuller
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• Ms . Janet, Leverling
• Mгs. Margaret, Peacock
• Мг. Steven, ВисЬапап
• Мг. Michael, Suyama
• Мг. Robert, King
• Ms . Lаша, Callahan
• Ms . Аппе , Dodsworth

Следует пом н ить, что объекты п олученных данных существуют только


на время жиз н и стран и цы. При следующем запросе всю р аботу п о
uэвлечению данных системы ASP.NET и ADO.NET бу,цуг п овторять
заново. Если вы п ол н е н ие запроса трудоемко, а данные ис п ользуются в
нескольких ст р аницах, то их нужно сохранять либо в объекте Sessi оп ,
либо в объекте Cache .

Работа с множественными таблицами и отношениями в


извлече нн ых авто н омных данных

Рассмотрим пример, в котором демонстрируется более и н тересное


приме н е н ие Da taSet , которое в доп олнение к представлен и ю

автономных данных исп ользует отн ошения таблиц. Э тот п ример


показывает, как извлекать некоторые записи из табли ц Са tego r i ез и
Produc t s базы да нн ых No r thw i nd . В н ем также п оказано, как
создавать отношения междУ таблицами для орга н изации простой
навигации от за пи си о категории к ее дочерн и м за п исям о продуктах,

чтобы создать п ростой отчет.

• ~Добавьте к корневому узлу п риложения страницу


DataSetRelationSrups.aspx с разделяемым кодом и сделайте ее
стартовой
• ~ оместите на страницу элеме н т управлен ия Labe l с имен ем
lbllnfo
• г;.:.=ОткроЙте файл подцержки DataSetRelationSrups.aspx.cs и
наполните его следующим кодом

using System;
using System.Data;
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

usiпg System. WеЬ.Сопfigшаtiоп;


usiпg System.Data.Sq IClient;
usiпg System.Text;

public partial class DаtаSеtRеlatiопShips : System.Web.UI .Page


(
protected void Page_Load(object sender, EventArgs е)
(
11 Изв лекаем строку соединения с им ен ем Nо rthwiпd из фай ла web.c
striпg соnnесtiопStriпg = WеЬСоnfigшаtioпМапаgеr.
С о nnесЙО nS triпgs [ ''N оrthwiпd "]. С оnnесйо nS triпg;

11 С оздаем объект соединения


Sq lС оnnес tiоп соп = пеw SqIСоnnесtioп(соnnесtioпStriпg);

11 Формируем строки SQ L -запросов


striпg sqlCategories = "SELECT CategoryID, CategoryName FROM Cate
striпg sqlP roducts := "SELECT ProductName, CategoryID FROM Producl

11С оздаем объект DataAdapter


SqlDataAdapter adapter:= пеw SqlDataAdapter(sqICategories, соп);

11 Создаем п устой объектDataSet на бо р а данных


DataSet dataset := new DataSet();

11 Выполняем два за пр оса к БД с открытием


11 и закр ыти ем соединения вручную.
11 Возможные исключения не обрабатываем, а просто подавля ем
try
(
со п.Ор е пО ;
11 Напо лн и т ь DataSet данн ы м и из табли цы Categories
11 с именованной меткой CatTable
adapter.FiII(dataset, "CatTable'');
11 Сме ни ть команду и доб ави т ь в DataSet данные
11 с именованной меткой ProdTable из та бл ицы Products
аdарtеr.SеleсtСоmmaпd.СОП1П1апdТехt:= sq lProd ucts ;
adapter.FiII(dataset, ''P rodTable'');
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

}
finally
(
con.CloseO;
)

11 Определе ние отношения между извлеченными в DataSet


11 именованными данными CatTabIe и ProdTable
DataRelation re lation = new DataRelation(
"C atProd", 11 Имя отношения
dataset.Tables["C atTable"].Columns["C ategoryID 'l, 11 Родительская т
dataset.Tables["ProdTable "].C olumns["C ategoryID"] 11 Дочерняя таБJ
);
11 Добавление отношения в коллекцию отношений DataSet
dataset. Re Iaпо ns .Add(ге lation);

11 Перебираем все извлеченные категории продуктов


11 и для кажд ой ИЗ них собираем сопоставленные продукты
StriпgВuildегhunlStr = пеw StriпgВuildег('");
foreach (DataRow row in dataset.Tables["C atTable"].Rows)
(
htmlStr.Аррепd( "< Ь >' );
htmlS tr.Append( row["C а te go ryN ате "]. То S tringO); 11 Имя поля
htmlS tr.Аррепd( "</Ь> ');

11 Со бираем дочерние записи из ProdTabIe для


11 текущего значения родителя CatTable в массив
DataRow[] childRows = row.GetC hildRows(relation);
htmlStr.Append("< ul>''); 11 Открыли маркированный список НТМL
foreach (DataRow childRow in childRows)
(
htmlStr.Append("< li>''); 11 Э лемент маркированного списка НТМ
htmlStr.Append(childRow("ProductName "].ToString()); 11 Имя по л я
htmlStr.Аррепd( "< IIi>' );
}
htmlStr.Append("</ul>''); 11 Закрыли маркированный список НТМL
}

11 Отображаем полученные данные ненавистному пользователю


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Ibllnfo.Text := htmlStr.ToS tringO;


}
}

Листинг Код файла DataSetRelationShips.aspx.cs

Пояснения к коду страницы DataSetRelationShips.aspx

Прежде всего мы извлекаем из конфигурационного файла строку


соединения и создаем для нее объект соеди н е ни я. Затем заготавливаем
строки SQL-запросов для извлечения данных из двух таблиц . Создаем
объект Dа t aAdapter для будущего подключения и uзвлечения данных
из первой таблицы. Вручную открываем соединение с базой данных и
извлекаем п оследовательно данные из д вух таблиц в именованные
объекты DataTable коллекции DataTables пр едварительно
созданн ого объекта Da ta Set .

Мы используем один объект Dа taAdapte r, пр едварительно


на страивая его на выполнение разных SQL-комаНА. Но можно создать
два отдельны х объекта DataAdapter для каждой таблицы. Создавать
отдельные объекты DataAdapter нужно обязательно в том случае ,
если мы п ланируем не только читать да нны е из таблицы , но и
сохранять (подтверждать) изменения в источник данных.

Таблицы Categor i es и Products связаны в базе да нных по


Юlючевом у полю CategoryID отношением "один в Categories ко
многим в Products ". ЭТО пол е является первичным Кf/ючем таблицы
Са tegor i ез и внеlШlИМ ключем таблицы Produc t з . Э ТО отношение
н е п ередается в объект Da taSet из базы да нных автоматически и мы
вынужд ены сами повторять его в коде для связывания по столбцам
извлеченных данных.

Именованное отношение создается пyrем о пр еделения объекта


DataRelation и добавления его в коллекцию отношений объекта
DataSet . При создании объекта DataRe l ation в его конструкторе
мы указываем три пар аметра: имя отношения , имя поля первичного

Юlюча таблицы-родителя, имя поля внешнего кnюча дочерней таблицы.

''''
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Замечание. Когда мы добавляем отношение таблиц в DataSet , то


должны соблюдать условие ссылочной целостности. Например, мы не
можем у,цалить родительскую запись, если существуют связанные с ней
дочерние строки, и не можем создать дочернюю запись, ссылающуюся

на н есуществующую родительскую. ЭТО может стать причиной проблем ,


если в Da taSet скопированы частичные данные из двух разных

таблиц. На уровне физического источника полных данных ссылочная


целостиость будет сохраняться , а в виртуальном источнике Da taSe t с
частичными да нными может быть нарушена.

Например , если мы из одной таблицы извлекли полный список всех


заказо в , а и з д ругой таблицы извлекли частичный список заказчиков, то
часть списка заказов бу,цет ссылаться в виртуальном источнике
Da taSe t на несуществующих в нем заказч иков.

Один из способов обойти эту проблему - создать DataRela ti on с


пер е груж е нным конструктором, имеющим четвертый булевский
параметр createConstraints , которому нужно задать значение

f alse . Другой подход состоит в отключении способности Da taSet


проверять целостность данных , в том чи сле целостность отношений.
ЭТО нужно сделать п е ред добавле нием в него отношения установкой
свойства Da t aSe t . Еп forceCons t r a i nts в значение f alse .

Долее мы работаем с ав тон омн ыми дан ными Da t aSet в

отсоединенном режиме. Для выборки данных из виртуального

источника данных Da taSe t мы организуем два цикла полного

перебора элементов.

Во внешнем ци кле мы перебираем все считанные и з источника записи


родительской таб лиц ы. Для каждой из этих зап исей р оди теля мы
создаем динамический Л1Qссив требуемого тип а, в который за гружа ем
за писи и з до черн ей таблицы со з начением поля внешнего КIIюча ,
соответствующего з нач е нию КIIючевого поля родительской таблицы ,
согласно установленному отношению.

Во вн уг реннем цикле мы перебираем все элементы динамического


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

''''
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

оф:Jрмляем в виде строк маркированного списка НТМL для красивого


п редставления н е н авистному пользователю ( мы его н е знаем, но уже
н е любим!).

• ~ сполните страницу DаtаSеtRеlatioпShips.аsрх и получите


следУЮЩИЙ результат

Beverages

• Chai
• Chang
• Guaranc Fа пtсsticа
• Sasquatch Ale
• Steeleye Stout
• CIte de Вlaуе
• Chartreuse уепе
• Ipoh Coffee
• Laughing LшnЬегjасk Lager
• Outback Lager
• RhУпЬгфu Klosterbier
• LakkalikYYri

Сопdimeпts

• Апisееd Syrup
• Chef Anton's СаjuпSeasoning
• Chef Anton's GшnЬо Mix
• Gга пdma ' s Воysе пЬеггу Spread
• Northwoods Сгаnbеггу Sauce
• Gепе п Shouyu
• Gula Маlaсса
• Siro p d'щгаые
• Vegie-spread
• Lоuisiaпа Негу Hot Реррег Sauce
• Lоuisiaпа Hot Spiced Okra
• Original Ргаnkfuпег grN2 пе So-e

Сопfес tiоns

""
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• Pav!ova
• Теаоое Chocolate Biscuits
• Sir Rodney's Мапrnladе
• Sir Rodney's Scones
• NuN uCa Nu· -Nougat-Creme
• Gumbфг Gummibфгсhеп
• Schoggi Schokolade
• Zaanse koeken
• Chocolade
• Maxilaku
• Valkoinen suklaa
• Tarte au sucre
• Scottish Longbreads

Dairy Products

• Queso Cabra!es
• Queso Manchego La Pastora
• Gorgonzola Теlinо
• Mascarpone Fabioti
• Geitost
• Rac!ette Сошdаvа ult
• Camembert Рieпоt
• Gudbrandsdalsost
• F!otemysost
• Mozzarella di Giovanni

Grains/Cereals

• Gustafs К пфсkеЬгУd
• ТшmЬгУd
• Singaporean Hokkien Fried Мее
• Fi/o Mix
• Gnocchi di попna Alice
• Ravioli Апgею
• WiIшners gute SemmelknYde!

MeatIPoultry

""
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• Mishi КоЬе N iku


• Alice М utton
• ТhNQringer Rostbratwurst
• Perth Pasties
• То urtiJше
• Ртtщ chinois

Produce

• Uncle Bob's Organic Dried Pears


• Tofu
• RYssle Sauerkraut
• Manjimup Dried Apples
• Longlife Tofu

Seafood

• Ikura
• КопЬи
• Са тагуоп 1igers
• Nord-Ost Matjeshering
• lnlagd S iI!
• Gravad !ax
• Boston Сга Ь Meat
• Jack's New Епg1зпd Clam C howder
• Rogede sild
• Spegesild
• Escargots de Bourgogne
• RYd Kaviar

Поиск определенных строк в извлеченных авто номных


данных

Класс DataTable имеет метод Select () , по з воляю щий извлекать


из зап олненного DataSet массив объектов-строк DataRow по
допол ни тель ном у усло вию на основе SQ L-выраже ния . Чтобы
проиллюстрировать этот метод, модифицируем п оследний пример.
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• IJ$Сделайте из ст раницы DаtаSеtRеLзtiопShips.аsрх ко пию с


име н ем DataTableSelec t . asp x
• ~3аполните файл DataTableSelect.aspx.cs следующим кодом

us iпg System;
us iпg System.Data;

us iпg System. WеЬ.Сопfigшаtiоп;


us iпg System.Data.SqlClient;
us iпg System.Text;

public partial class DаtаSеtRеLзtiопShips : System.Web.UI.Page


(
protected void Page_Load(object sender, EventArgs е)
(
11 Изв лекаем строку соединения с им ен ем No rthwind из фай ла web.c
striпg connectionString = WеЬСоnfigшаtioпМапаgеr.
С о nnесоо nS trings[''N orthwind "]. С оnnесйо nS triпg;

11 Создаем объект соединения


SqlC onnection соп = new SqlConnection(connectionString);

11 Формируем строку SQ L-за про са для заданн ых полей


striпg sqIP roducts := "SELECT ProductName, Discontinued FROM Рrоdш

11С оздаем и настраиваем объект DataAdapter


SqlDataAdapter adapter := new SqlDataAdapter(sqIProducts, соп);

Создаем П УСТОЙ объект DataSet на бо р а


11 данных
DataSet dataset = new DataSet();

11 Выполняем запрос к БД с автоматическим


11 открыти ем и закрытием соединения
try
(
11 Добавить в DataSet данные с им е нованной
11 меткой ProdTable из табл ицы Products
adapter.Fill(dataset, ''P rodTable'');
}

""
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

catch
(
throw пеw АрросаtiопЕхсе рtloп( "О ши бка да нных.'');
}

11 Получить по дополни тел ьн ому условию


11 масс ив про.цуктов , им е ющи х скидки
DataRow[] matchRows = dataset.Tab1es[''ProdTable''].
Sе)ес t(''Disсопtinuеd <> О ''); 11 До полнительно е услов ие

11 Выбрать имена продуктов со с ки дками


S triпgВuildег hunlStr = пеw S triпgВuildег('" ) ;
htmlStr.Аррепd("< оl> ' ') ; 11 Открыли н умерова нный список НТМL
fo reach (DataRow row in matchRows)
(
htmlStr.Аррепd("< li> ''); 11 Элемен т маркированного списка HTM L
htmlStr.Аррепd(гоw[''РгоduсtNаmе ''].ТоStгingО); 11 Имя поля
htmlStr.Аррепd("< IIi> ');
}
htmlStr.Аррепd("<lоl> ''); 11 Закрыли н умерова нный список НТМL

11 Отображаем получе нные данные пользователю


Ibllnfo.Text = "< h2 > Список про.цуктов, < Ьг I> и мею щих скидки </h2 > ";
Ibllnfo.Text += htmlStr.ToS tringO;
}
}

Листинг
DataTableSelect.aspx.cs
Применение метода Select • файле

Приведенный код при мера достаточ н о пр ост. Из данных, загруженных в


Da taSet по SQ L·ЗQПРОСУ, мы выбираем данные в массив строк по
допол ни тельному услов ию.

• ~ сполните стра ниц у DataTab)eSelect.aspx, чтобы получить


следУЮЩИЙ результат

С пи сок продукто в , имеющи х скидки

''''
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

1. Chef Anton's GшnЬо Mix


2. Mishi КоЬе Niku
з. Alice Mutton
4. Guaranc Fantcstica
s. RYssle Sauerkraut
б. ThN:!ringer Rostbratwurst
7. Singaporean Hokkien Fried Мее
8. Perth Pasties

Первое знакомство с механизмом привязки

извлекаемых автономных данных

Иногда более удобно не самому формировать НТМL-вывод для изъятых


из базы автономных да нны х, как мы это делали до сих пор , а
воспользоваться специальным механизмом привяэки данных, который
по заботится о правильном представлении данных по льзователю .
Самым пр остым в использовании для привязки и отображении данных
является элемент управления Gr i dVi e w. Он ав томатически формирует
НТМL-таблицы , в ячейки которых выводит данные, загруженные в
набор данных Da taSe t . Порядок при вязки набора данн ы х da tase t к
эюемпляру G ri dV i еw l класса Gr i dVi еw следующий:

1. Подключить набор дан ны х

GгidViеw1.DаtаSошсе:= dataset;

2. Указать именованную метку таблицы в н аборе да нны х,


подлежащи х отображению

GridView1.DataMember = 'TabIeLabel";

з. Загрузить при вязанные данные в конкретный элемент

отображения ил и сразу во все элементы отображения страницы

GridView1.DataBindO; или Page.DataBindO;

Если мы вызовем Page . DataB i nd ( ), ТО он пройдет по всем


элементам управления страницы, подцержив аю щи х привя зку да нны х, и

""
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

для каждого вызовет метод DataBind () .

Приведем п ример страницы , в которой за гр узим и отоб р азим


п ользователю п е рвые пять строк таблицы Emp l oyees учебной базы
данны х Northwind .

• r;:;='Добавьте к прил ожению WebSite8 новую страницу с


р аздельны м кодом и именем GridViewEmployees. азр х .
Назначьте эту страницу стартовой
• ~ оместите на страницу и з ВЮJaДЮ1 Data панели Toolbox
элем е нт управления Gr i dVi ew с име н ем Gr idViewl
• ~Откройте на редактирование файл подцержЮ1
GridViewEmployees.aspx.cs и за п олните его следУЮЩИМ кодом

using System;
using System. Data;

using Sуstеm.WеЬ.Сопfiguгаtiоп;
using Sуstеm. D аtа.sqlС ~е пt;

pub lic ра пial class GridViewEmp loyees : System Web.UI.Page


(
protected void Page_Load(object sепdег, ЕvепtAгgs е)
(
// Содать Со rшес ооп, DataAdapter и DataSet
string соппесtio пS tring = Wе Ь Со пfigша tiоnМа паgег.
Со ппесtio пS tr iпgs[''N о rthwind "]. С о rшесtio nS tгiпg;
Sq}Cormection соп = new Sq ICormectio n(cormectionString);
string sq! =
"SELECT тор 5 Emp!oyeeID, 1ideOfCourtesy, LastName, "
+ ''FirstName FROM Employees";
SqIDataAdapter adapter = new Sq ID a taAdap ter(sq~ са п);
DataSet dataset == new Data Set();
ada р ter. F ill( da taset, ''Еmр loyeesTab Ie '');

// П ри вя зать да н н ы е к GridViewl для отоб р аже ни я


Gгid View l . D аtаSошсе == dataset;
GridViewl .DataMember == ''EmployeesTable'';
GridViewl .DataBind O;

""
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

}
}

Листинг. Код файла GridViewEmployees.aspx.cs


• ~ сполните стран иц у GridViewEmployees.aspx, чтобы получить
следУЮЩИЙ результат

EmployeeID 1ideOfCourtesy LasrName FirsrName


1 Ms. Davolio Nancy
2 Dг. Fuller Arкlrew

3 Ms. Lеvегliпg Janet


4 Mгs. Peacock Margaret
5 Мг. Buchanan Steven

к элементу отображе ни я можн о привязать сразу ко н кретную таблицу из


на бора данных. В этом случае строки пр ивязки будУГ выглядеть так
(стра ница GridViewEmployeesl .aspx )

11 Привяз ать да нны е к


GridVJewl для отображен ия
GridViewl .DataSource = dataset.Tables[''EmployeesTab1e''];
GridViewl .DataBindO;

Более того, существует масс Оа taV i ew , который является

п редставлением масса Data Table , с п омощью которого можно

п редвари тельн о отсорти ровать или отфильтровать данные перед


п ри вязкой к элементу управле ни я Gr i dVi ew для показа поль зователю.

Со ртировка извлеченных авто номных данных с

помощь ю DataView

Приведем пример страницы, в которой и с п ользуем тр и разных


п редставления одной и той же таблицы в наборе да нных.

• ~Скопируйте стран ицу GridViewEmp loyees.aspx и дайте ей и мя


GridView DataView . asp x

При копирова нии не заБУдьте на страниц е в д ирективе @Page


,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

исправить пар аметр Inher i ts= " Gr i dV i ewDataV i ew " а в

фай ле поддержки п ерео пр еделит ь имя класса на


GridViewDataView

• ~ оместите на страницу дополнит ельные элементы

управления Gr i dVi ew так, чтоб ы они располагались друг за


друго м по вертикали в порядке GridViewl , Gr i dView2 ,
GridViеwЗ

• ~CTaBbTe перед каждым элеме нтом строку· заголовок


о <h 2 >Несорт и рованные д а нн ые</h2>
о <h 2 >Сорт и рованы по полю F i r stName</h2>
о <h 2 >Сорт и рованы по полю LastName</h2>

Ин терфейс страницы на этапе проектUРО6анuя долже н бы ть таким

'"
в м С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

GridViewDataView.BSpx

Несортированные данные

Т:: оlшnnО Соlшnnl Соlшnn2


аЬс аЬс аЬс
аЬс аЬс аЬс
аЬс аЬс аЬс
аЬс аЬс аЬс
аЬс аЬс аЬс

Сортированы по полю FirstName


Т:: оlшnnО Соlшnnl Соlшnn2
аЬс аЬс аЬс
аЬс аЬс аЬс
аЬс аЬс аЬс
аЬс аЬс аЬс
аЬс аЬс аЬс

Сортированы по полю LastName


Т:: оlшnnО Соlшnnl Соlшnn2
аЬс аЬс аЬс
аЬс аЬс аЬс
аЬс аЬс аЬс
аЬс аЬс аЬс
аЬс аЬс аЬс

Ici De~gn Iв Scuce I В]1 <Ьоdу> I <civ>ll<h2>I


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• ~Отредактируйте файл n одцержЮ1 страни цы следУЮ ЩИ М


об р азом

using System;
using System.Data;

using Sуstеm.WеЬ.Сопfiguгаtiоп;
using Sуstеm.Dаtа .sqlС ~е пt;

public рапial class GridViewDataView: System.Web. UI.Page


(
protected void Page_Load(object sепdег, ЕvепtAгgs е)
(
// Содать Соrшес ооп, DataAdapter и DataSet
string соппесtioпString = WеЬСопfigшаtiоnМапаgег.
СО ппесtioпS triпgs[''N о rthwind "]. С о rшесtio nS tгiпg;
Sq}Cormection соп = new Sq IСо rmесtiо п(соrmесtioпS tring);
string sq! =
"SELECT ТОР 5 Emp!oyeeID, 1ideOfCourtesy, LastName, "
+ ''FirstName FROM Employees";
SqIDataAdapter adapter = new SqIDataAdap ter(sq~ соп);
DataSet dataset == new DataSet();
ada р ter. F ill( da taset, ''Еmр loyeesTab Ie '');

// Привязать данн ые к GridViewl для отображения


// без сортировЮ1 как они есть
GгidView l.Dаtа Sошсе = dataset.Tables[''EmployeesTab!e''];

// Скопировать данн ы е в эюемnляр масса DataView,


// отсортировать по полю FirstName, затем привязать
DataView view2 = пеw DataView(dataset.Tab)es[''EmployeesTable'~
view2.Sort = ''FirstName'';
GгidView2.DаtаSошсе == view2;

// Скопировать данн ы е в эюемnляр масса DataView,


// отсортировать по полю FirstName, затем привязать
DataView viеwЗ = пеw DataView(dataset.Tables[''EmployeesTable'~
viеwЗ.Sоrt = '1.astN аmе";
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Gгid ViewЗ. D аtаSошсе:= viеwЗ;

// З а грузи ть пр и вязаНН bl е да нны е во все элемеН ТbI отобр а же i


Ра gе. D аtаВiпd О;
}
}

Листинг. Код файла GridViewDataView.aspx.cs


• ~ сполните стра ниц у GridViewDataView.aspx, чтобbl получить
следУЮЩИЙ результат

НесортироваННblе данные

EmployeeID 1ideOfCourtesy LastNйme FirstNйme

1 Ms. Оауоио Nancy


2 Dг. Fuller Апdгеw

3 Ms. Lеvегliпg Jапеt

4 Mгs. Peacock Margaret


5 Мг. Вuсhanaп S tеvеп

СортироваНbI по полю FirstName

EmployeeID 1ideOfCourtesy LastNйme FirstNйme

2 Dг. Fuller Апdгеw

3 Ms. Lеvегliпg Jапеt

4 Mгs . Peacock Margaret


1 Ms. Оауоио Nancy
5 Мг. Вuсhanaп S tеvеп

СортироваНbI по полю LastName

EmployeeID 1ideOfCourtesy LastNйme FirstNйme

5 Мг. Вuсhanaп S tеvеп

1 Ms. Оауоио Nancy


2 Dг. Fuller Апdгеw

,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

з Ms. Lеvегliпg Jапеt

4 Mгs. Peacock Margaret

Фильтрация извлеченных автономных данных с

помощью DataView

Объект DataV i ew можно использовать для фильтрации извлеченных


автономных данных перед их отображением пользователю. Для этого
нужно за.цать объекту значение свойства RowF i 1 te r , которое
использует те же операторы логичесЮ1Х условий , что и в SQL-запросе.
В таблице приведены наиболее часто используемые операторы
фильтрации

Некоторые операторы фильтрации в свойстве DataView.RowFilter


Операция Описание

<, >,
С р авнение числовых или строковых типов
<= , >=
<> , = Проверка на эквивален тность

NO T Отрицание

Указывает диапазон ВЮlючительно. Например, Un i ts


BETW EEN 5 AND 1 5 выбирает строЮ1, у которых
BETWE E N
знач ен ие столб ца Un i ts находится в диапазоне 5 -1 5
ВЮlючительно

I S NULL Проверяет столбец на н улевое знач ен и е

Краткая ф:Jрма операции OR с одним и тем же пол ем.


IN ( a , Проверяет эквивалентность знач ения столбца любому и з
Ь , с) п ереч исл енных значений списка нужной длины, например
а , Ь, с

LIK E Проверяет соответствие строкового значения шаблону

Конкатенация СЮJа.цывает два числа или СЮJеивает две


+
строЮ1

Вычитает одно числовое значение из друго го

* Перемножает два числовых значения

I Дели т одно числовое значение на другое


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

% Вычисляет модуль - остаток от деления одного числового


значения на д ругое

ANO Логическое умножение

OR Логическое сложение

Приведем п ример страницы , в которой им е ются три эл ем ента


Gr i dVi ew. Каждый из них привяза н через OataView к одним и тем
же да нным Оа ta Table , но с разными установками фильтрации .

• г;;;?С оздайте копию страницы GridViewDataView.aspx с имен ем


Оа taViewF i 1 te r ed . asp x и назначьте ее стартовой
• ~ стра н ице DataViewFiltered.aspx выполните следую щие
изменения

о В директиве @Page установите новое значе н ие атрибyrа


Inherit s= " OataViewFiltered "
о Поме н яйте НТМL-дескрипторы <h2> на <hЗ> со
следующим содержимым

• < hЗ >
Фи льтровать продукт Chocolade<br />
(RowFilter = ''ProductName = 'Chocolade"')
< 1hЗ >

• < hЗ >
Фи льтровать продукты , которых н ет в заказах и на сЮJ
(RowFilter = ''UnitsInStock = О AN D UnitsOnOrder = О ' ')
< 1hЗ >

• < hЗ >
Фи льтровать продукты , ч ье на зва ни е начинается с б)'l'
(RowFilter = ''ProductName LIKE ' Р %" ')
< 1hЗ >

• r;.:.=в файле подцержки DataVJewFiltered.aspx.cs установите новое


имя КIIacca OataV i ewFi l tered и нап олните файл следУЮЩИМ
КОДОМ

using System;
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

using System.Data;

using Sуstеm.WеЬ.Сопfiguгаtiоп;
using Sуstеm.Dаtа.sqlСlieпt;

риыic рапial class DataViewFiltered: System.Web.UI.Page


(
protected void Page_Load(object sепdег, ЕvепtAгgs е)
(
// Содать Соrmесtiоп, DataAdapter и DataSet
string соппесtioпStriпg = WеЬСопfigшаtiопМапаgег.
СО ппесtioпS trings["N о rthwind "]. С о пnесtio пS tгiпg;
Sq}Сопnесtiоп соп = пеw SqlСопnесtiоп(сопnесtioпString);
string sq! =
"SELECT ProductID, ProductName, UпitslпStосk, UпitsОпОгdе
+ ''Disсо пtinuеd FROM Products";
SqIDataAdapter adapter = пеw SqIDataAdapter(sqL соп);
DataSet dataset = пеw DataSet();
adapter.Fill( dataset, ''ProductsTab!e'');

// Фильтровать продУКТ Сlюсо ladе


DataView viewl = пеw DataView(dataset.Tab)es[''ProductsTab)e'1);
viewl.RowFilter = ''Ргоd uсtNаше = 'Chocolade''';
GгidViewl.DаtаSошсе = viewl;

// Фильтровать продУКТЫ, которых нет в заказах и на скrщце


DataView view2 = пеw DataView(dataset.Tab)es[''ProductsTab)e'1);
view2.RowFilter = 'uпits lпStосk = О AND UпitsОпОгdег = О";
GгidView2.DаtаSошсе = view2;

// Фильтровать продУКТЫ, чье название начинается с буквы Р


DataView viеwЗ = пеw DataView(dataset.Tab)es[''ProductsTab)e'1);
viеwЗ.RоwFiltег = ''Ргоd uсtNаше LIKE ' Р %"';
GгidViewЗ.DаtаSошсе = viеwЗ;

// Загрузить привязанные данные во все элементы отображеi


this.DаtаВiпdО ;
}
}
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET
Листинг. Код файла DataViewFiltered.aspx.cs
• ~3апустите страницу DataViewFiltered.aspx и получите

следУЮЩИЙ результат

Фильтровать продукт Chocolade (RowFilter := ''P rodllctName := 'Chocolade"')

ProdllctID ProdllctN аmе UnitsInStock UпitsОпОгdег Discontinued

48 Chocolade 15 70 г

Фильтровать продукты , которых нет в заказах и на складе (RowFilter :=


'UnitsInStock := О AND UnitsOnOrder:= О '')

ProdllctID ProductName UпitsIпStосk UпitsОпОгdег Discontinued

5 Chef Anton's GllmbO Mix О о

17 Alk:e Mlltton о о

29 ТhNQringer RоstЬгаtwшst О о

53 Репh Pasties о о

Фильтровать продукты , чье название начинается с буквы Р (RowFilter :=


''ProdllctName LIKE ' Р %"')

ProdllctID ProdllctN аmе UnitsInStock UпitsОпОгdег Discontinued

16 Pavlova 29 о
г

53 Репh Pasties О о

г
55 PTtlЦ chinois 115 о

Класс System .D ata . DataView также имеет свойство


RowS t ateFilter , которое можно использовать для фильтрации
данных так, чтобы отображались только строки, имеющие определенное
состояние (вставленные , помеченные на Удаление , модифицированные
или неизмененные). По умолчанию это свойство установлено на
отображение все х строк, кроме помеченных на Удаление.
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Фильтрация извлеченных авто но мных данны х в

DataView с установкой отнош ений

Класс DataV i ew может выполнять и более сложную фильтрацию на


основе таблиц , связанных отношением 'Тлавн ыЙ - подчин е нныЙ ".
Наприм ер, можно отобразить категор ии , каж.цая из которых содержи т
более 20 наи менований пр одуктов, или отобрази ть заказч иков ,
сделавших о п ределенное количество п окупок.

Продемонстрируем эту возможность на примере д вух табли ц :


Categor i es и Products учебной базы Northwind.

• ~Сделайте копи ю ст р аницы DataS etRelationStllps.aspx и назовите


ee DataViewRelation . asp x
• ~ справьте значения атрибуга Inherits в aupeKmUBe @Page
страницы и имя клаССQ в файле п одцержки
• ~дали те со страницы DataViewRelatlon.aspx текстовую метку
lbl 1 n fo и поместите вм есто нее за головочный дескриптор

<h2 > Катего рии с пр одУКТам и до роже $SO <Ih2>

• r;:;nоместите п осле заголовочного дескриптора элемент


управления Gr i dVi ew и з вкладки Data панели Toolbox
• Г;:;=С корректируйте файл п одцержки страницы
DataViewRelation.aspx.cs следующим образом

using System;
using System.Data;

using System.Web.Configuration;
using System.Data.SqlClient;
using System.Text;

public рапial class DataSetRelationStllps : System Web.UI.Page


(
protected void Page_Load(object sender, EventArgs е)
{
// Извлекаем строку соед ин е ния с и ме н ем Northwind из файла
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

string соппесtioпString = Wе Ь Со пfigша tiоnМ а паgег.


СО nnectionS trings[''N о rthwind "]. С о nnесtio nS tring;

// Создаем объект соединения


Sq}Connection соп = new Sq ICo nnectio n(connectionS tring);

// Фор м ируем строки SQL-запросов


string sqlCatego ries = ''SELECT CategoryID, CategoryName FRO~
string sqlProducts = "SELECT ProductName, CategoryID, U n.itPricE

// Создаем объект DataAda pter


SqIDataAdapter adapter = new Sq IDataAdapter(sqICategories, con:

// Создаем пустой объект DataSet набора данн ых


DataSet dataset = new DataSet();

// Выполняем два запроса к БД с открытием


// и закрытием соед ин е ния вручную.
// Возможные ИСЮJючения н е об р абатываем, а просто подавл
try
(
соп.ОрепО;
// Н аполни ть DataSet данными из таблицы Categories
// с именованной меткой CatTable
ada pter.F ill(dataset, "C atTable");
// Сме ни т ь команду и добавить в DataSet дан ны е
// с именованной меткой ProdTabIe из табл ицы Products
ada pter.SelectCommand. CommandText = sqlProducts;
ada pter.F ill(dataset, ''ProdTable'');
}
finа Пу
{
con.CloseO;
}

// Определение отношения между и звле ченны м и в DataSet


// именованными данными CatTable и ProdTable
DataRelation relation = new DataRelation(
"CatProd ", // Имя отношения
,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

dataset.таы s[ ' 'са tтаь l е''].соl шnns[ ' 'са tеgогуID' '],' // Роди теЛ l
dataset.Таblеs [ ''РгоdТаЫе''].Со lumпs[''СаtеgогуID ''] // Дочер ю
);
// Добавле н ие от н о ше ни я в коллекцию отн о шени й DataSet
dataset.Relations. Add( ге Ia tio п);

// С о здаем объект Data View, в который за гружаем дан н ые Cat'


DataView viewl = пеw DataView(dataset. TabIes["CatTabIe'1);

// Уста н авл и в а ем фильтр для отображе ни я тол ь ко кате го р ий 1


// це н а которых в связан н о й табл и це пр одУКТов удовлетворяе
// "Самый дорогой продукт дороже 50"
viewl .RowF ilter = "МАХ(Сhild(СаtРгоd ) .uпitРгiсе) > 50";

// П оказываем отфи льтр ова н н ы е да нн ые п ользователю


Gгid View l . D аtаSошсе:= viewl ;
GridViewl .DataBindO;
}
}

Листинг. Код файла DataViewRelation.aspx.cs


• r;:;'н азначьте страницу DаtaViewRеlatiоп.аsрх стартовой и
вы п ол н ите ее

Долж е н получиться следующий результат

Категории с продуктами дороже $50

CategoryID CategoryName
1 Beverages
3 С опfeсtio пs

4 Dairy Products
б MeatIPouhry
7 Produce
8 Seafood

в фильтре мы установили условие , чтобы показать п ользователю только


те записи в родител ьской таблице , для которых в дочерн е й связа нн ой

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

таблице имеется хотя бы одна запись со з начением поля


Un i tPrice>50 . ЭТО означает, что выводятся категории продуктов , в
которых хотя бы один продукт дороже $50.

Добавление к автономным данным вычисляемых


столбцов

Таким образом, масс Da t a Se t позволяет одноразово загрузить


нужные данные из источника, а затем в отсоединенном автономном

режиме что-то с ними делать. До сих пор мы пока зывали польз ователю
все автономные данные, полученные по SQL -заnр осу. Показывали
данные с налож е ни ем некоторых условий в методе

Data 5et.Та Ь les['Tab Ie N ате '1. 5е lе с t( "Д оп ол н и тел ьн о е -.Усл ов и е ")

Пока зывали, также, да нные с условием, наложе нным в свойстве


Dа taV i ew . RowF i 1 te r вспомогательного объекта Dа taV i ew .

Теперь рассмотрим вопрос, как в дополнение к полям, и звле ч е нным в


набор данных DataSet из фи зи ч еско го источника данных, можно
добавить вычисляемые столбцы. Вычисляемые столбцы являются
искуств е нно полученными в наборе данных и игнорируются при
и звле чении и обновлении да нны х . Вместо этого они представляют

собой знач е ния , которые вычисляются на основе физически


существующих данных.

Чтобы создать вычисляемый столбец в Da taSet , необходимо отдельно


создать новый объект масса DataColumn , уста новить форм улу в его
свойстве Ex p r ess i on и добави ть этот столбец в коллекцию
Col umns объекта Da taSe t

dataset. ТаЬ les['Ta Ь le N ате '1. С о lшnns . Add( dataco hmт)

Ра ссмотри м при мер , в котором создадим столбец , объединяющий


фамилию и имя каждого служащего из таблицы Emp l oyees учебной
базы данных No r thw i nd .

• г;;;?Создай те копию фай ла TestDataSet.aspx с именем


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Ex p r ess i onCo l um n s . asp x и назначьте ее стартовой


• Г;;:;=Откройте на редактирование файл подцержки
ЕхргessiопСоlШl1ПS.аsрх.сs и отредактируй те его так

using System;
using System.Data;

using Sуstеm.WеЬ.Сопfiguгаtiоп;
using Sуstеm.Dаtа.sqlСlie пt;
using System.Text;

public рапial class ЕхргеssiопСоlumпs : System Web.uI.Page


(
protected void Page_Load(object sепdег, ЕvепtAгgs е)
(
// Извлекаем строку соединения с именем Nоrthwiпd из файла
string соппесtioпStriпg = WеЬСопfigшаtiопМапаgег.
СО ппесtioпS triпgs[''N о rthwind "]. С о пnесtio пS tring;

// Формируем строку SQL дЛЯ выборки всех данных таблицы


string commandString = "SELECT * FROM Employees";

// Создаем и настраиваем экземпляр класса SqIDataAdapter


SqIDataAdapter adapter =
new Sq lDаtаАdарtе г( соmmа пdStriпg, сопnесtioПStгing);

// Создаем объект DataSet результирующего набора данных


DataSet dataset = пеw DataSet();

// Безопасно заполняем данными объект DataTabIe с произвOJ


// именем, например ''EmployeesResuh'', созданного объекта О,
try
(
adapter.Fill( dataset, ''EmployeesResuh');
}
catch
(
throw new АррliсаtionEхсерtiоп("Ошибка дан ны х. ');
}
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

// Создаем именованный столбец и доба вляем к таблице в О.


string strExpr =
'~СОТРУдник' + 1ideOfCourtesy +" + LastName +', . + FirstN,
Data Co lumn соlШ1Ш = new DataColumn(''FullName'', typeof(string),
dataset. Та Ь les["EmployeesResult"]. С о lшnns. Add( со lиmn);

// Перебираем все объекты DataRow с полученным зап и сами


StringВ uilder htmlStr = new StringВuilder("");
foreac h (DataRow dr in dataset.Tables[''EmployeesResult'']. Rows)
{
hunlS tr. Ар pend ("<П> ');
// Существующий столбе ц
hunlStr.Append(dr[''EmployeelD ''].ToS tringO + ') ');
hunlStr. Append("<Ь> ');
// Новый столбец
hunlS tr. Ар pend (dr[''FuIIN ате '1. То 5 tringO);
hunlS tr. Ар pend ("< !Ь> ');
hunlS tr. Ар pend ("<1Ii> ');
}

// Отоб р ажаем полученные данные


IblInfo.Text = "< h2 > С п исок СОТРУдников<1h2 >";
IblInfo.Text += htmlStr.ToStringO;
}
}

Листинг. Код файла ExpressionColumns.aspx.cs


• ~ы п ол н и т е стра ниц у ЕхргеssiопСо lшnns.аs р х и п олучи те
следую щий р езул ьта т

С ПИ СОК СОТРУд н иков

• 1) Сотрудник Ms. Davolio, Nancy


• 2) Сотрудник Ог. Fuller, Andrew
• 3) Сотрудник Ms. Leverling, J апеt
• 4) Сотрудник Mrs. Peacock, Margaret
• 5) Сотрудник М г. В ис Ьа na п, Steven
• 6) Сотрудник М г. Suyama, Michael
,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• 7) СОТРУДНИК Мг. King, Robert


• 8) СОТРУДНИК Ms. Callahan, Laura
• 9) СОТРУДНИК Ms. Dodsworth, Аппе

Добавление к авто номным данным вычисляемых


столбцов для связанных таблиц

Можно создать в Da t а Se t вычисляемые столбцы для связанных


стр ок Например, можно добав и ть в виртуальную таблицу CatTable
столбец, показывающий количество связанных строк виртуальной
таблицы ProdTable . В этом случае нужно определить отн ошение
объектом DataRelat i on и иcnользовать агрегатную функцию SQL.
такую,как АVG() , МАХ() , MIN() , COUNT() .

Приведем пример , в котор ом создается тр и вычисляемых столбца со


своей агрегатной функцией и ис п ол ь зуется отн ошение таблиц.


• IJ$Создайте копию стра ницы DataViewRelation.aspx с именем
Ex p r essionCo l umnsRela ti on . asp x и назначьте ее

стартовой
• ~ cnравьте значения атрибyrа Inhe r its в aupeKmUBe @Page
страницы и имя клаССQ в файле п одцержки
• Г;:;=Измените на странице заголовочн ый дескриптор на

< h2 > Добавле ни е вычисляемых столбцов < lh2 >

• ~Откройте кодовый файл ExpressionColumnsRelation.aspx.cs на


редактирование и откорректируйте его так

using System;
using System. Data;

using System.Web.Configuration;
using System. Data .SqlC ~e nt;
using System.Text;

public partial class ЕхргеssiопСоlumпsRеlatiоп: System Web.UI.Page


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

(
protected void Page_Load(object sепdег, ЕvепtAгgs е)
(
// Извлекаем строку соединения с имен ем Nоrthwiпd из файла
stгiпg сопneсtioпStriпg = WеЬСо пfigша tiопМ а паgег.
СО ппесtio пS triпgs['N о rthwiпd '1. С о ппесtio пS tгiпg;

// Создаем объект соединения


SqК::о ппе с tiоп соп:= пеw Sq IСо ппесtiо п(соппесtюпS triпg);

// Формир уем строки SQL-запросов


stгiпg sqlCatego ries = ''SELECT CategoryID, CategoryName FRO!l
stгiпg sqlProducts:= "SELECT ProductName, CategoryID, U nitPricE

// Создаем объект DataAda pter


SqIDataAdapter adapter = new Sq IDataAdapter(sqICategories, соп:

// Создаем пустой объект DataSet набора данн ы х


DataSet dataset = new DataSet();

// Выполняем два запроса к БД с открытием


// и закрытием соед ин е ни я в ручную .
// Возможные ИСЮJючения н е об р абатываем, а просто подавл
try
(
соп.ОрепО;
// Н аполни ть DataSet данными из таблицы Categories
// с именованной меткой CatTable
ada pter.F ill(dataset, ''C atTable'');
// Сме ни т ь команду и добавить в DataSet дан ны е
// с именованной меткой ProdTabIe из та бл ицы Prod ucts
ada pter.SelectCommand. CommandText = sqlProducts;
ada pter.F ill(dataset, ''ProdTable'');
}
finа Пу
{
con.CloseO;
}
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

// Определение отношения между и звле ченны м и в DataSet


// именованными данными CatTable и ProdTable
DataRelation relation := пеw DаtаRеlauоп(
"CatProd ", // Имя отношения
dataset. Tables["C atTable"].Co lumns[''CategoryID''], // РодитеЛl
dataset. таblеs [ ''ргоdта ыe '].соl umпs[''саtеgогуID'11 // Дочер ю
);
// Добавле ние отношения в коллекцию отношений DataSet
dataset. Rela tions. Add( ге Ia tio п);

// Создать вычисляемые столб цы и добав ить их в DataSet


Data Co lumn соuпt:= new Dаtа Соlunm( "Кол. продуктов", tур еоf(iп
"С О UNT( С hild (С atP гod). С а 'е goгyID)',;
dataset. Та Ь les[' 'С atTab le "]. С о lumns. Add( со Шlt) ;
Dаtа Со lumп шах = пеw DаtaСоlumn("Самый дорогой п р одУКТ",
'MAX(ChiId(Ca tPгod) . UnitPгice )',;
dataset. Та Ь les[''C atTab le "]. С о lumns. Add( шах);
Dаtа Со lumп пlln := new DаtаСоIШl1П("Самый де шевый п р одУКТ",
''М IN (С hiId( С а tPгod). UnitPгice )',;
dataset. Та Ь les[' 'С atTab le '1. С о lumns. Ad d( пlln);

// Меняем названи я заголовков стол бцов на р усский язык


dataset. Та Ь les[' 'С atTab le '1. С о lumns[' 'С atego ryID"]. С о lumnN аme :=
dataset. Та Ь les[''C atTab le "]. С о lumns[' 'С atego ryN ате '1.С о IumпN am

// Показыва ем данные пользователю


GгidView l.Dаtа Sошсе:= dataset.Tables["CatTable"];
GridViewl.DataBindO;
}
}

Листинг. Код файла ExpressionColumnsRelation.aspx.cs


• ~ сполните страницу ExpressionColumnsRelation.aspx и получите
следУЮЩИЙ резул ьтат

Добавление вычисляемы х столбцов

NQ Наименование Кол. Самый дорогой Самый дешевый


л /п категории продУКТов продУКТ лродукт
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

1 Beverages 12 263,5000 4,5000


2 Condiments 12 43,9000 10,0000
3 Confections 13 81,0000 9,2000
4 Dairy Products 10 55,0000 2,5000
5 Grains/C ereals 7 38,0000 7,0000
6 MeatIPouhry 6 123,7900 7,4500
7 Produce 5 53,0000 10,0000
8 Seafood 12 62,5000 6,0000

С HeT(og
- -- .....
J
,

,,,
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Привязка данных ADO.NET


Привяз ка одного з начения. Привяз ка множественно го з н аче ни я к
списковым элем е нтам управления. При вязка DataReader к с пи сков ым
элементам управления. Элеме н т управления GridView с м н ожестве нн ой
при вязкой да нны х . Элеме нты управления и сточ никами да нны х .
Элеме н т управления SqlData Source. Пер едача парам етр а источнику
данных че рез элеме н т управления. П е р едач а п араметра источнику
данных через строку запроса . П е р едача пара мет р а источнику данны х в
хранимых пр о ц едур ах. Обработка ИСЮlюч е ний источников да нны х .
Р еда ктир о в а ние за писей в источнике данны х. Обновление дан ных пр и
па раллельном доступе. Компонент управления источником данных
ObjectDataSource. Применение перегруженного метода
Uр dаtеЕ mplо уееО .И спользова ни е ObjectDataSource для вставки и
удален ия за писе й. Програ мм но е и зменен и е за п роса пользователя в
Sq lDataSource.

Программировать стараться - с конкурентами распрощаться

Файлы к лекц ии Вы можете скачать здесь скачать:

httр :l/оkl . iпtШ . ruld е р а rtmeпtJiпtе mе tJр rasp netJ 1 3/1 з.пр .

Профессиональное Web- п риложение всегда им еет дело с данными ,


которые MOryr храниться в базе данны х, XML- и л и ст руктур ированном
файле , или гд е- то еще. Прави л ьно е отображение эти х данных на
страниц е пользов ателя так же важно , как и их извлеч ение. ADO .NET
им еет меха низм привязки данных , который позволяет декларати вно (на
этапе праект иравания ) о пр едел ить связь между э леме нта ми и звлече н ия
данных и элеме н там и их отображения . При этом может не
п отребоваться н и ст р о чки кода.

При вязка данных - это средство , которое позволя ет ассоциировать


источник данных с элементом управле ни я с целью автоматического
отображения да нны х в этом элеме н те управления. Различают привя зку
од ного з н ач е ния и привя зку множественн о го значения.

Привязка одного значения


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

При вязка одного значения позволяет связать свойство элемента


управления с местом на странице. ЭТО место называется вычислимым
выражением привя зки данны х. Различают вычислимые # - выражения
и более общие $ - выражения привязки данных. Выражение привязки
данных может располагаться как внугри дескрипторов элементов
управления, так и самостоятельно в любом месте страницы, даже вне
дескриптора <forт> . .. </ forт> .

Выражение привязки данных н е может содержать конструкций языка


(ЦИЮJЫ, условные операторы , объявления и т.д.). Оно может только
содержать:

• значение свойства
• значение , возвращаемое функцией
• п ереме нную -член ЮJасса

• ссылку на свойство друго го элемента управления


• арифметическое выражение с прим е н е ни ем л итералов и
переменных

• и т.д.

Выражение привязки данных в ASP.NET помещается в огр ани чит ельные


скобки <%# ... %> (в РНР это будуг скобки <?php ... ?> или < ?
= ... ? > ). Если выражение привязки данных используется внугри
дескриптора элемента управления в качестве вычисляемого значения
атрибуга, то оно помещается в одинарные или двойные кавычки.
Испол н е ни е выражения привязки данных тр ебует обязательного
выполнения метода Page . DataB i nd ( ) в сценарии ст р аницы. Если
мы заБУдем это сделать, то выражение привязки данных будет
проигн орировано в НТМL -выводе страни цы.

Пример корректных #- выражений привязки данных:

• <%# Reques t . Br owse r . B r owse r %>


• <%# GetUse r Name ( 10) %>
• <%# va ri able %>
• <%# " Доро г о й " + " д руг " + пате %>
• <%# 2 * Р 1 * r ad iu s + cos(alpha) %>

,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Прим е р инт ерфей с ной части страницы, использующей несколько


выраж ени й ПрU6ЯЗКU данных:

<html>
<body>
< fо пn method="post" nmat="server''>
<asp:Image ID='1magel " runat="server" ImageUr!=' <%# FilePath %>' /><
<asp:Labe! ID="Label1 " runat="server" Text="<%# FilePath %>" /><br />
<aspTextBox ID='TextBoxl " runat="server" Text=' <%# GetFilePathO %>
< а sр:НуреrLink ID='HyperLinkl " runat="server"
NavigateUr!="<%# LogoPath. Value %>" Font- Bo!d =''true'' Text=''S hc
<input type="hidden" ID=' 'Lo goPath'' runat="server" va!ue='M yMy.png">
< Ь > <%# FilePath %></b ><br />
< iшg src="<%# GetFilePathO %>">
</foпn>
</body>
</html>

в при веденном коде выраж е ние ПрU6Я3КU данных и с пользуется не


только для динамической смены з начений свойств элементов
управления, но и строковых з н ач е ний пер еме нных. И еще разок, чтобы
выраж ени я не были отброшены системой, не забыть бы вып ол нить
метод D а t a Bi nd () стр а ницы.

Прив едем пр остой при мер .

• г;.:.=СоздаЙте новый сайт с именем Web S i t e 9 командой


FilelNewlWeb Site (шаблон ASP.NET Web Site)
• Г;;:;=СкопируИ:те из проекта WebSite8 файл Web.Config, который
долже н иметь такой ви д

<?xml version="l.O'? >


< сопfigшаtiоп>
<connectionStrings>
<add name=''N orthwind " connectionString=
' Па ы Sо шсе= !осаlhо st; lnitia! Cata!o g=N orthwind ; user ю=
< /соппе сtюпS trings >
<system.web >
< с о mрilatюп debug=''true''/>

'"
в.м. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

</system. web>
</configuration>

Листинг. Содержимое файла Web.Confiq


• IJ$Добавьте к приложению новую страницу с совмещенным
кодом и и менем S i ngleValueBinding . asp x, назначьте
страницу стартовой
• r;:;=вызовите для корня Web-дерева кон текстное меню и создайте
катало г Pictures сай та командой N ew Folder
• ~С копируйте из каталога Pictures да нн ой работы в каталог
Pictures сай та два файла: MyPhoto.jpg и М уМу.рпg (или любые
другие рисунки)
• ~ аполните стра ниц у SiпglеVаluеВiпdiпg.аsрх следУЮЩИМ кодом

<%@ Page Lапguаgе =="С #" %>

<script ruпаt== "server''>


// Объявления переменных масса
stгiпg cat == "Васька ", photo;

// Методы
protected void Page_Load(object sепdег, ЕvепtAгgs е)
{
if (!this.lsPostBack)
{
LabellText == "< h1 > Заполни те поля и ПОlllТlИ те за пр ос < lhl >
pict.Src == "PictureslМyPhoto.jpg";
}
.Is.
{
LabellText == "< Ы > Вот Вам такие oTBeTbI <lhl >";
photo :::: ''Pic ture slМyMy. png'';
pict.Border :::: З ;
}
}

риыic iпt АddFuп(strшg а , stгiпg Ь)


{
try

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

(
геtшп Сопvеrt.ТоlпtЗ2 (а) + Сопvеrt.ТоlпtЗ2(Ь);
}
catch
{
LabellText = "< Ы style='colorred'>B поля вводите цеЛ blе чи
LabellText += "<hr style='height:l0; color:red' 1> ";
геtшп О;
}
}

protected void Buttonl_Click(object sепdег, ЕvепtAгgs е)


(
this.DаtаВiлd();
}
</script>

<html xmIns='huр://www.wЗ.or&,1999/xhtml" >


<head runat= "server''>
<tide > Вblражения привязки одного значения< /tidе >
<lhead>
<body>
<form id ="forml " nшat="sеrvег''>
<div>
<asp:LabelID='1.abel1" nшat="sеrvег" Text="Label" 1>
<h2 >
Кто сказал Мяу .. ?<Ih2 >
< Ь style="color: Red''>
<%# ''Кот'' + cat + "!" 0/0>
<Ib >
<h2 >
Сколько будет дваЖДbl-два?<1h2 >
<Ь style="color: Red''>
<%# 2 * 2 %>
<Ib >
<h2 >
Введите два < еm> цеЛblх </еm> числа < Ьг 1>
и получите их CYМMy<1h2 >
< asp:TextВox ID= 'TextВoxl " nmat="server" />
,,,
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

+
< asp:TextВox ID ='TextВox2" nmat="server" />
= <Ьsty1e="color: Red ">
<%# АddFun(ТеxtВох l .Техt, TextВox2.Text) %> < /Ь>
< Ы > Кто здесь изображен? < /h2>
<img id= ''pk:t'' runat= "server" src ="<%# рlюtо % >" />
< Ьг />
< Ьг />
<asp:Button ID =''Вuttопl '' runat="server" O nClick="Buttonl_ Clic
</div>
</fonn>
</body>
<lhtml>

Листинг. Код страницы SingleVa lueBinding .aspx

При первой загрузке ст р а НИЦbl в текстовую метку ВblВОДИТСЯ начаЛЬНblЙ


за головок<h 1> и установленно е п о умолчанию знач ение свойства s r c
дескр иптора <i mg> . Все Вblраже ния пр и вязкu дан ных при этом
игн о рируют ся. При обратн ой ОТСblлке , инициир о в а нн о й кнопкой ,
срабаТblвает метод DataBind () ст р а НИЦbl. Он заставляет
ВblПОЛНИТЬ СЯ все Вblражения прuвязкu данных , код п олучения которых
разм еще н в блоке сценариев <script> .

• Г;:;=Вblполните страницу S ingleValueBirкling.aspx и убедитесь в


р аботоспособнос ти выражений пр и вязкu данных

Р езул ьтат при начальной загрузке страницы:

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Заподните подя и пошдите 'JащJOС

Кто сказа.' Мяу ... ?

Сколько б уд ет дважды-два?

Введит е два це.IlЬLУ числа

и полу ч_ите их CYMl\JY

Кто здесь изображеи ?

Результат посл е обратной отсылки стра ницы :


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Вот Вам TaКlle ответы

Кто сказа." Мяу ... ?

Сколько будет дважды-два?

Введите два J~ел&IХ числа


и получите их C)'Mi\l}'

- 11

Кто здесь изображеи?

с не т

Привязка множественного значения к списковым


элементам управления

Некоторые элементы управления библиотеки .N ET Framework,


служащие для отображения данны х, позволяют привязать сразу

н есколько своих дочерних элементов к источнику данных. К ним

,,,
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

ОТНО С ЯТСЯ прежде всего списковые элементы управления:

• Все списковые элементы управлени я, которые генерируют свой


HTML - КОd с использованием дескриптора
<selec t >, ВЮlючая
HtmlSelect , List Bo x и Dr op DownList
• Элеме нты управления CheckBo xL i st и Rad i oBut t on List ,
гене рирующие HTML -КОd свои х дочерних эл еме нтов в ви де
фл ажков или nерекл ючат еле й
• Элеме нт управлен и я Bul l eted List , создающий
нумерованный или маркированный список

Все они насле~т от


Sys tem . Web . U1 . WebCon t r ols . Li s tControl , который
соде р жи т свой ства, необходимые для при вязки множеств е нного
з н ач ени я. Э ти свойства приведены в таблице

С вой ст ва ListControl для привязки м ножествен ного з начения

С войство Описание

ПОДЮlючает ссылку на объект с да нны м и (для


DataSou r ce
загрузки методом Da t aB in d ( ) ), и меющим и

При соединяется к уже загруженному объекту


данных. Используется как альтернатива свойству
DataSource ID
Da t aSou r ce . Оба свойства сразу применять
нельзя

С одержит наименование поля (столбца) таблицы,


значения которого БУдУГ отображатьс я списком

<select s ize =''З'' naше ="L istВохl " id =' 'L istВoxl ''>
DataTe x tF i eld
< орооп value="l ">Textl <Ioption> 1::;
< орооп value=''2''>Text2 <loption>
</select>

С одержит наименование поля (столбца) таблицы,


значения которого БУдУГ загружены в список как
атрибугы v al ие , но пользователь и х не ув иди т

Dа ta Va 1 ие Fi е ld <select s ize =''З'' name ="L istВoxl " id =' 'L istВoxl ''>
'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

< орооп value="l ">Textl <Ioption>


< орооп value=''2''>Text2<loption>
</select>

в свою очередь, масс L i stControl наследУет метод DataBind ()


ОТ масса

System . Web . UI . WebControls . BaseDataBoundCont r ol ,


иницирующий привязку.

Для прим е р а прив язки м ножестве нного знач е ния спроектируем


страниц у, в которой в качестве объекта , имитирующего источник
данных, и с пользуем масс На
sh tabl е (hash - мусор) . Он реализует
интерфейс System . Collections . Generic . IDi c ti ona r y ,
имеющий шаблонный метод IDictionary<TKey ,
TVa l ue> . Add(TKey , TVa l ue) .

• г;;.:;='Добавьте к прило жению страницу с неразделяемым кодом и


им е н ем Repea tedVa l ueBinding . asp x

• Г;:;==Заполните ин терфейсную часть страницы следующим кодом

<%@ Page Language="C#" % >

<script nmat= "server''>

</script>

<html xmIns=''httр ://www.wЗ.огgl 1 999/xhtml'' >


<head nmat="server">
< title > </title >
</head>
<body>
< fо пn id ="fо пnl " runat="server''>
<div>
<select гuпаt="sеrvег" id= "S elect1 "
datatextfield='Key" datavaluefield =''Value'' size=''З'' 1>
<select гuпаt="sеrvе г" id= "S elect2"
datatextfield='Key" datavaluefie ld =''Value'' 1>
,,,
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

<asp:ListBox runat="server" ID=''ListBoxl''


DataTextFie!d='Key" DataValueFie!d='Value " Rоws='З" />
<asp:DropDownList runat="server" ID=''DropDownListl ''
DataTextFie!d='Key" DataValueFie!d='Va!ue " />
<asp:RadioButtonList runat="server" ID=''RadioButtonListl ''
DataTextFie!d='Key" DataValueFie!d='Va!ue " />
<asp:CheckBoxList runat:::::"server" ID="CheckBoxList1"
DataTextFie!d='Key" DataValueFie!d='Va!ue " />
< Ьг />
<aspButton runat="server" ID="GetSe!ectio n" Теxt=''Получить выделеНl
< Ьг />
< Ьг />
<asp:Litera! runat="server" ID=''Resuh'' Enab!eViewS tate="false" />
</div>
</form>
</body>
</html>

Листинг Объявление элементов управления в интерфейсной


части страницы RереаtеdVаluеВiпdiпg.аsрх

Объявления первых двух статически х списков нужно набирать вручную ,


чтобы подсказчи к кода до п ускал к и х атрибугам . Элемен т управления
L i te r al все-равно БУдет заполняться при каждой обратной отсылке и
отображать значения свойств выбранных дочерних элемен тов. Поэтом)';
чтобы не таскат ь состояние этого элемента с сервера на броузер и
обратно, отключим у него свойство сохранения состояния.

• ~ ереведи те редактор страницы в режим Design и двойным


щелчком мыши на свободном месте создай те обработчик
Page Load ( ), который заполните так

protected void Page_Load(object sender, EventArgs е)


(
if (!this. I sPostВack)
(
// Создать источник данных (коллекцию) с тремя элеме н тами
Hashtable ht = new наshtaыез);;

,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

// Добавить в коллекцию элеме НТbI по схеме: Add(Key, Value)


ht. Аdd(' 'Иванов '', 'Valuel ");
ht . Аdd(' 'Петров '', 'Value2'');
ht . Аdd("СиДоров", 'VаluеЗ',;

// С вязать эл емеН ТbI управления с источнико м данных


Sеleс t1 . Dаtа Sо шсе =ht;
Sеleс t2. Dаtа Sо шсе = ht;
ListВo xl.Da taSourc e = ht;
DгорDоwnListl.DаtаSошсе = ht;
RadioВuttоnListl.DаtаSошсе = ht;
СhесkВоxList1 . Dаtа Sо шсе = ht;

// 3агрузи ть данные в элеме Н Т bI управления


this.DataBindO;
}
}

Листинг Код обработчика события Page_Load() страницы


RepeatedValueBinding.aspx

Источник данных Hash t able можно представить таблиц ей и з двух


столбцов. ПеРВblЙ столбец считается Кеу , второй - Value .

• ~3апусти те ст р аницу, чтобbl проверить работу механизма


пр ивязки м н ожествен н ого значения к СПИСКОВblМ элементам

управления

Теперь реализуем функциональность, чтобbl при щелчке на кнопке


элемент L i teral собирал и отображал и н формацию о ВblделеННblХ
элементах списков.

• г;;;?Создайте обработчик для кнопки Button и заполните его


следУЮЩИМ кодом

protected void GеtSеleс tiоп_Сlk:k(оЬjесt sender, EventArgs е)


{
try
{
,,,
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Result.Text += "<Ii>B Selectl в ы брано : "


+ "(\""
+ Selectl.Items[Select1.Selectedlndex].Text 11 Кеу
+ '\", \""
+ Selectl.Value + '\'')''; /1 Value
Result.Text += "<Ii>B Select2 в ы брано : "
+ "(\'11'
+ Select2.Items[Select2.Selectedlndex].Text 1/ Кеу
+ '\", \""
+ Select2.Value + '\'')''; /1 Value
Result.Text += "<Ii>B ListВoxl выбрано:"
+ "(\'11'
+ ListВoxl.Selectedltem Text // Кеу
+ '\", \""
+ ListВoxl.Selectedltem Value + '\'')''; // Value
Result.Text += "<Ii>B DгорDоwпListl выбрано:"
+ "(\'11'
+ DгорDоwпListl.SеIeсtеdltеm.Техt // Ке у
+ '\", \""
+ DгорDоwпListl.SеIeсtеdltеm.Vаluе + '\'')''; 11 Value
Result.Text += "<Ii>B RаdiоВuttопListl выбрано:"
+ "(\'11'
+ RаdioВuttопListl. Selected ltem. Text // Кеу
+ '\", \""
+ RаdioВuttопListl.Sеlесtеdltеm.Vаluе + '\ '')'';/1 Value

// Пр оверяем флажки
int сhесkеdСО Шlt = О;
striпg сhесkStгiпg = '11';
fo reach (Listltem check iп CheckBoxListl .ltems)
(
if (check.Selected)
(
с hес k S triпg
+= "(\'"'
+ check.Text // Кеу
+ '\", \''''
+ check.Value + '\ ''); "; 1/ Value
с hес kе dСО Шlt++ ;// Сч и тем выделенные флажки
}
,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

}
if (checkedCount == О)
Result.Text += "< li>B CheckBoxListl ничего не выбрано! ";
e~e
Result.Text += "< li>B CheckBoxListl выбрано: " + checkString;
}
catch
(
Result.Text = "< Ы s tуle='соloг:Rеd' > Выберите в каждом элементе <,
)
}

Листинг Код обработчика кнопки для отображения результатов

вы бора пользователя страницы RepeatedValueBinding.aspx

Разница в коде до ступа к свойствам списков между серверными


элементами управления и статиче сЮ1М И объясняется подгонкой фирмой
Мiсrоsоft HTML-ЮJaССОВ под ранее разработанные дескрипторы
<se l ect> .

• r;:;'выпо л ните полностью готовую страницу, демо нстрирующую


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

,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

И~8НО~ И~IIНО~

Петров
ИВOIНОВ
iJ ГleTPO В

r
Иванов

r
Сидоров

r Петров

Г
Иван о в

'" СИДОРОВ

'" Петров

Попучнть ~ЫАеленное I

Выберите в каждом Э.rIементе

Привязка DataReader к С ПИ СКQВЫМ элемен там

управления

ПредыдуЩИЙ п ример использует в качестве источника данных класс


Hash tabl е , потому что он реализует и н терфейс

System . Colleetions . Generie . IColleet i on<Syste m. Colj

в кач естве источника данных можно и с пользов ать любой класс ,


на следую щий этот интерфейс. Вот некоторые и з б и бл иотеч ны х классо в ,
п роизводных от интерфейсно го класса IColl ее ti оп :

• Sys t em . Colleet i ons . Arr ayL i st


• Mi c r osof t . Vi sualBas i c . Colleet i on
• Sys t em . Colleet i ons . Hash t able
• Sys t em . Colleet i ons . Gener i e . Diet i ona r y<TKey ,
TValue>
• Sys t em . Data . DataV i ew
,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Учитывая, что DataReader представляет данные также в виде


таблицы с именованными столбцами , мы можем так сформулировать
SQ L-запрас к базе дан ны х, что в DataReader БУдУГ загружены два
нужных нам столбца: оди н из которых можно считать Кеу , д ругой -
Value . В элементе управления свойству Data Te x tF i eld н ужно
присвоить имя поля , отображаемого в списке , а свойству
DataValueF i eld - имя поля , неотображаемого в списке .

Приведем пример. П усть мы хотим за полнить окно с пи ска L i s t Bo x


полными именами в сех СОТРУдников, хранящихся в таблице
Emp l oyees учебной базы данны х Northwind . Чтобы получить два
столбца DataReade r, оди н из которы х БУдет вычисляемый , н ужно
сформулировать SQ L-запрас таким образом

SELECT EmployeeID, ТitleOfCourtesy + "+ FirstName + ' , + LastName AS ]

• ~Добавьте к проекту новую страницу

DataReaderL i s t Bi nding . asp x с ра зделяем ым кодом и

назначьте ее стартовой
• ]J$ОФОрмите и настройте интерфейсную часть страницы
DataReaderListВinding.aspx так, чтобы она имела следующее
дес крипторное представление

<%@ Page Language="C#" AutoEventWireup=''true''


С ode F ile= ''DataReaderListB ind ing.asp х. cs"
Inherits= ''DataReaderListВ inding'' %>

<html xmIns='huр ://www.wЗ.or&,1 999/xhtml" >


<head runat= "server''>
<title >Untitled Page</title>
<lhead>
<body>
<form id="forml" nшat="sеrvег''>
<div>
< asp:ListВox ID=''ListBoxl'' runat="server" DataTextFie ld =''FuIlNan
DataValue Field= ''Employee ID'' Selec tionМ ode='M ultip)e" Rows=
< Ьг 1>
< Ьг 1>
<asp:Button ID="GetSelectio n" nшat="sеrvег" Теxt="Получить вы/
,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

ОпСlick= "G еtSеleсtioп_Сlick "


1>
< Ьг 1>
< Ьг 1>
<asp:Literal ID='Result" runat= "server" Епаыeiеwstаtе="Fаlsе" />
</div>
</fonn>
</body>
<lhtml>

Листинг Дескрипторное представление интерфейсной


части страницы DataReaderListBinding.aspx
• Г;:;==Заполните файл поддержки DataReaderListВinding.aspx.cs
следУЮЩИМ кодом

using System;
using System.Data;
using Sуstеm.WеЬ.Сопfiguгаtiоп;
using Sуstеm.Dаtа.sqlСlie пt;
using Sуstеm.WеЬ.U I .WеЬСопtrоls;

public рапial class DataReaderListBinding: System Web.UI.Page


(

protected void Page_Load(object sепdег, ЕvепtAгgs е)


{
if (!this.IsPostBack)
(
/1 Создать объекты Command и Соnnесооп
string соппесtioпString = WеЬСопfigшаtiоnМапаgег.
Со ппесtioпS trings["N о rthwind "]. С о nnесtio пS tring;
string sql = "S ELECT EmployeeID, "
+ 'TttleOfCourtesy +" + FirstName +" + LastName "
+ "AS FullName FROM Employees";
Sq}Соnnесtiоп соп = пеw Sq IСоnnесtiо п(соnnесtiопString);
Sq}Command сшd = new SqlCоmma пd( sq L соп);

try
{
/1 Открыть соединение и получить DataReader
соп.ОрепО;
,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

SqlDataReader reader = cmd.ExecuteReaderO;


// Привяза т ь DataRead er к с пи ску и заполнить с пи сок
ListВохl.DаtаSошсе = reader;
ListВохl.DаtаВiпdО;
reader.CloseO;
}
finа Пу
{
// Закрыт ь соединение
con.CloseO;
}
}
}

protected void GetSe lection_Click(obj ect sender, EventArgs е)


{
Result.Text = "< Ь > Выделены сотруд ники:</Ь>";
Result.Text += "<01>";
foreach (ListItem item in ListBoxl.Items)
if (item.Selected)
Result.Text +=
String.Format("<li> (\"{О } \", \"{l }\'')</li>'', item.Text, item.V<
Result.Text += "</01>";
)
}

Листинг Код файла поддержхи

DataReaderListBinding.aspx.cs

Здесь мы заполнили список только при первом запросе стр аницы ,


расчитывая , что далее за п ол н е нный спи сок будет сохраняться в
состоянии вида. Если в элементе ListBoxl ОТЮJючить сохр анение
состояния вида , установив Ena bl eViewSta t e= " Fa l se ", то пр и

обратной отсылке список окажется пустым (п опробуйте!) .

• Г;:;=И сполните стран ицу DataReaderListВinding.aspx для получения


следУЮщего результата

,,,
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

ПОЛ'\,ЧИТЬ выделенное

Выделены сот р удники:

1. (''Ог. Andrew Fuller", ''2'')


2. ('Мг. Stеvеп ВисЬаnaп", "5'')
з. ('Ms. А п пе Dodsworth", ''9'')

Если для вuэуализац ии да нны х мы хотим исп ользовать

Dr opDownList , CheckLis t Box или RadioButtonList вместо


Li s tBo x, то достаточ но изменить объявление элеме н та управле ния в
интерфейсной части ст р аницы. Остальная часть кода останется
прежнеЙ.

Элемент управления GridView с множественной


привязкой данных

Кроме списковы х элементов управле ни я, которые мож но исп ользовать


для отображе ни я множественных да нны х, существую т более
специализированные элемен ты управления , спроектированные

специально для эти х ц елей . К ни м относятся Gr i dVi ew.


De ta i lsVi ew и FormVi ew. Кроме того, меха ни зм прив язки имею т и
такие элементы , как Мели , TreeVi ew и AdRotator, хотя и служат

несколько для других целей.

Здесь м ы поговорим об элеме нт е управления GridView. во змож ны х


способах е го настройки и при вязки к нему разных источников данных.
,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Как и С ПИ СROвые элемен ты управле ни я, Gr i dVi ew имеет свой ство


DataSou r ce и метод DataB i nd() . Тип овое объявление эл ем ента
Gr i dVi е w в интерфейсной части страни цы выглядит так:

<asp:GridView ID="GridViewl" runat="server" 1>

Ра с смотрим прим е р , в ROтором да нны е DataReader будyr


привязываться не к списковому элемен ту управл е ния , а к Gr i dVi ew.

• ~С оздайте новую страниц у GridViewDataBind.aspx с

р азделяемым кодом и на значьте ее стартовой


• ~ оместите на страницу и з вкrщцЮ1 Data панели Toolbox
элем е нт управления Gri dVi ew

• ~Откройте на реда ктирование файл GridViewDataBind .aspx.cs и


заполни те его следую щим ROдом

using System;
using System.Data;
using System.Web.Configuration;
using System.Data.SqlClient;
using System.Web.UI.WebContro ls;

public рапia l class DataReaderListBind ing: System Web.UI. Page


(

protected void Page_Load(object sender, EventArgs е)


(
11 Создать объекты Command и Соnnесооп
string соппесtioпString == WеЬСо пfigша tiоnМ а паgег.
Со nnectionS trings["N о rthwind "]. С о nnесtio nS tring;
string sql = "SELECT EmployeeID, FirstName, LastN аmе . "
+ 'Tttle, С ку FROM Employees";
Sq}Connection соп = new Sq ICo nnectio n(connectionString);
Sq}Command сшd == new Sq}Command(sqL соп);

try
{
/1 Открыть соединение и получи ть DataReader
соп.ОрепО;
,,,
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

SqlDataReader reader = cmd.ExecuteReaderO;


// При вяза ть DataReader к GrklView
GгidView l . D аtа Sошсе = reader;
GridViewl.DataBindO;
reader.CloseO;
}
finа Пу
{
// З акры т ь соединение
con.CloseO;
}
}
}

Листинг. Код файла GridViewDataBind.aspx.cs


• г;.:.=исполните страницу GridViewDataBind.aspx для получения
следУЮщего результат

Emp!oyeeID FirsrName LasrName Title City


1 Nancy Davolio Sa!es Representative Rеdпюпd

2 Andrew Fuller Vice President, Sales Тасота

3 Janet Leverling Sa!es Rергеsепtаtivе Kirkland


4 Margaret Peacock Sa!es Representative Rеdпюпd

5 Steven ВисЬаnaп Sa!es Manager London


б Michae! Suyama Sa!es Rергеsепtаtivе Lопdоп

7 Robert King Sa!es Representative London


8 Laura СаПаЬап Inside Sa!es Coordinator Rеdпюпd

9 Аnnе Dodsworth Sa!es Representative London

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

в библиотеке .NET Framework имеется ряд классов , которые


соединяются с любым поставщиком данных ADO .NET, облегчая
nрuвязку данных к элементам отображения. О ни называются
источниками данных и реал изуют интерфейс 1 Dа ta S ои r се .

,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

EJ-.. "'O System.Web.UI IDataSource


r!J . Base Types
"'Ib Derr<ed Турео
B":~ DataSourceConuol
i r!J. 4$: ObjectDataSource
I 14,.. '\: SqlDataSOurce
rВ,,·4f$ SiteМapDataSource
liJ '\: XmlDataSwrce
к источникам данных относятся следующие ЮJассы:

• Sys t em . Web . UI. WebControls . 0bjectDataSource


позволяет ПОДЮJючиться к п ользовательскому ЮJассу доступа к

да нным

• Sys t em . Web . U I. WebControls . SqlDataSource


позволяет ПОДЮJючиться к любому поставщику ADO.NET
• Sys t em . Web . U I. WebControls . S iteMapDataSource
позволяет П ОДЮJючи ть ся к файлу System.Web.SiteMap,
описывающему навига ц и онную структуру Web-сайта
• Sys t em . Web . UI. WebControls . XmlDa t aSource
позволяет П ОДЮJючиться к ХМL-файлу

Все эт и ЮJассы представл е ны как элемен ты управления на ВЮJадке Data


пан елиToolbox оболочки VlSua! Studio 2005 и являются н овшеством
библиотеки .NET Framework 2.0. Есл и перенести этот элемент на
страницу, то он отображается серым цветом как н е визуальный
компо н ент стра ницы . В то же время в р азметочной части страницы
п оявляется соответствующий дескриптор элеме н та управления.

Источники д анных используют поставщики данных для П ОДЮJюче ния и


обмена да нными с базой данных. Но исполь зуют они их в обобщенном
виде через фабрики поставщиков , которые находятся в пр остранствах
и мен

• Sys t em . Data . Common


• Sys t em . Data . SqlCl i ent
• Sys t em . Data . Or acleClient
• Sys t em . Data . OleDb
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• Sys t em . Data . Odbc

Элемент управления SqlDataSource

Чтобы манипулировать да нными одной конкретной таблицы базы


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

отдельному источнику д анных. Не отображаемый на странице


источник данных нужно конфигурировать (настроить) на соединение со
своей таблицей. ЭТО делается чере з атрибугы дескри птора напрямую
или через свойства в панели Properties. В настройках обязательно
следует указать

• строку соединения ConnectionSt r ing


• имя фабрики постав щиков Prov iderNa me
• тип SQL-команды (встроенная SQ L -комаНАа Text или хранимая

процедура StoredProcedure ) в свойствах


SelectCommandType , Inse r tCommandType ,
UрdаtеСоm m апdТуре и Dеlе tеСоm m апdТуре

• саму SQ L-комаН АУ или имя хранилюй процедуры в свойствах


SelectQuery, InsertQuery, Upda t eQue r y и

Dele teQuery (Такие имена имеют свойства в панели Properties,


которые в дескр ипторном представлении источника данных
трансф:Jрмируются в имена атрибугов Se l ectCommand,
InsertCommand , Upda t eCo mmand и Dele teCommand )

Нам нужно определять команды только для тех типов действий, которые
мы намерены выполнить. Так, например , если мы используем источник
данных только для чтения набора записей, то нам достаточно
определить только свойство SelectQue r y .

Строку соединения можно жестко указать в свойствах источника


данных, но луч ше читать из файла web.config, используя $ - выражение
привяэки данных.

Прив едем прим е р дескриптора сконфигурированного источника


данных, который и звлекает записи из таблицы Employees учебной
базы данных No r t hwind .
'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

<asp : S qlDаtа Sошсе I D="SqlDаtаSошсе 1" runat="server"


ProviderN аmе= "S ystem.Data" SqlC lient"
Connectio nString="<%$ connectionStrings:Northwind %>"
SelectCommand=
"SELECT EmployeelD, FirstName , LastName, Тitle , City FROM Emp loyees

Источник данных можно сконфигурировать и с помощью мастера ,


вызвав е го командой Сопfigше Data Source встроенного меню

SqlDataSourceSimple "aspx

;•Sфаtasot.rсе - ~ataSOJce 1 SqlDataSource Tasks


_.".._..."."..."..."."..."..."."..."..."."..."...".".._.."."..~ СCn:fi~щ~е~D~а:ta:s~cu~,~е~Гг::;;::-::::С=:-:;::::-==;:-::;;:="
"
Refresh Sdlema
IcmftgJre Y0Lr фtз s c:иce's *1:tr"gS. I

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


при вязать к нем у любой элемент отображен ия данных: HtmlSelect ,
L i s tBo x, Dr op DownLi s t , Chec k Bo x L i s t , Rad i oBu t t on Li s t ,
Bul l etedL i st уже на этапе проектирования , н е написав ни одн ой
строки кода в обработчике Page Load () . Более того, если выполнить
команду Refresh Scheme в строенной п ан ели источника данных, то он
одноразово соединится с базой да нны х и заполнится требуемой
информацией , которую потом можно выбирать из раскрывающихся
списков при настройке п ривязываемых к нему элементов отображения
да нны х " Есл и мы используем источник данных, то создавать
соединение, объекты команд и вызывать метод Page . DataB i nd () в
коде страницы для заполнения элементов отображения, не нужно - все
будет выполняться автоматически при запуске страницы.

• г;.:.=СоздаЙте страницу с объединенным кодом и им ен ем


Sql DataSou r ceS i mp l e . азр х . Назначьте ее стартовой
• Г;;:;=ИЗ ВКlщцки Data панели Toolbox добавьте на страницу
неотображаемый элемент управления SqlDataSou r ce , через
который мы при вяжем да нны е к элементу отображения
• ~ з вкладки Standard панели Toolbox добавьте на страницу
элем е нт управления Li st Bo x
• ~ з вкладки Data панели Toolbox добавьте на стра ниц у элемент
управления Gr i dVi ew
• IJ$и з вкладки Standard панели Toolbox добавьте на страницу

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

элеме нт управления Button


• Г;;:;=Н аст р ойте объекты страниц ы: источник данных
SqlDataSou r cel , элеме н т отображе ни я дан н ых ListBox l .
м н огофункцио н аль н ый элеме н т отображе ни я да нн ых
GridViewl , кно п ку обратн ой отс ы лки Bu t ton l следУЮ ЩИ М
об р азом

<%@ Page Language="C#" %>

<script runat= "server''>


// Здесь мы не написали ни строчки кода! ! !
</script>

<html xmIns= ' huр ://www.wЗ.or!j'1999/xhtml" >


<head runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nmat= "server''>
<div>
<asp:5 qIData 50urce ID="5q lDаtа50шсе 1" nmat= "server"
Provid erN аmе= "5 ystem Da ы. 5q IC lient"
Connection5 tring="<%$ connection5trings:Northwind %>"
5electCommand=
"5ELECT EmployeeID, FirstName, LastName, 1ide, City FROM
< a s p :ListВox ID=''ListBoxl'' runat="server" Data50urce ID="5 qIDat
DataTextField=''FirstN аmе " />
< Ьг />
< Ьг />
<asp:GridView ID="GridViewl " runat="server" Data50urceID="5qI
< Ьг />
<asp:Button ID =''Вuttопl '' nmat="server" Техt="Обновить " /></di\.
</fonn>
</body>
<lhtml>

Листинг Разметочная часть страницы


SqlDataSourceSimple.aspx
• ~ с п ол ни те ст р аницу 5q IData50urce5imple .aspx, чтобы п олучи ть
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

следУЮЩИЙ результат

Nanc'i ....
Andrew
Janel
Margare1 ~

Emp!oyeeID FirsrName LasrName Title City


1 Nancy Davolio Sa!es Representative Rеdпюпd

2 Andrew Fuller Vice President, Sales Тасота

3 Janet Leverling Sa!es Rергеsепtаtivе Kirkland


4 Margaret Peacock Sa!es Representative Rеdпюпd

5 Steven Buchanan Sa!es Manager London


б Michae! Suyama Sa!es Representative London
7 Robert King Sa!es Representative London
8 Laura СаПа Ьап Inside Sa!es Coordinator Rеdпюпd

9 Аnnе Dodsworth Sa!es Representative London


ОБНОБИТЬ

Все работает автоматически без необходимости написания кода


(который нам тоже не страшен) . Привязка данных при каждой обратн ой
отсылке п овторяется зан ово , и в этом есть некоторый недостаток,
п оскольку каждый раз должно создаваться соединение с базой данных и
п роизводиться выборка данных. К счасть ю, разработчики ASP.NET 2.0
устран или этот н едостаток за счет автоматического кэширования

данных источником SqlDataSource на случай , если данные


и зменяются редко.

Если и зме ни ть свойство DataSourceMode источника данных с


DataSet (установле н о по умолчанию) на DataReader и исполни ть
страницу, то в дан н ом случае получим тот же самый результат. Режим
DataSourceMode=DataSet работы источника данных почти
всегда лучше, чем режим DataSourceMode=DataReader,
п оскольку он подцерживает расширенную сортировку, фильтра цию и
на стройку кэширования, и меющиеся в DataSet . Одна ко, если стои т
задача отоб р ажать большие экранные таблицы, то лучше использовать

,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

режим DataSourceMode=DataReader , потому что он более


эqxpeктивно использует па мять сервера.

Передача параметра и сточнику данных через элемент


управления

Прим е н е ни е параметриЗ0ванных ком ан д выполняется в тех случаях,


если необход имо работать с двумя и более связанными та бли ца ми. Дл я
каждой та бл ицы н ужно создать свой источник данных. Н уж но связать
эти источники с элементами отображения так, чтобы при выборе
да нного в одном элементе пр оисходила выборка в другой элемент всех
дан ны х из второй табл ицы с требуем ы м з н ач ени ем Юlюча.

Прив едем прим е р , в котором при выборе города в списковом элементе


автоматически выбир аются и отображаются в другом элементе все
сотру,цники, проживающие в данном городе. Мы бу,цем исп ользовать
два элемента отображения , к каждому ИЗ которых привяжем по своему
источнику данных. И сточн и ки данных бу,цем зап олн ять из одной и той
же табл ицы Employees выбор кой данных по разным SQ L-запро сам. В
одном ИЗ источников команда будет иметь пар аметр , значение которого
будет передаваться из элемента отображения , за пол н е нного д руги м
источником .

• IJ$Создайте страницу с объеди н енным кодом и им ен ем


Sql DataSou r cePa r a mete r s . asp x . На з нач ьте ее стар товой
• ~далите контейнер сценария <sc ri pt
r unat= " ser v er " > .. . </sc ri pt> как н е н уж ны й дл я
данно го при мера

• ~ з ВЮlадки Data пан ели Toolbox добав ьт е на страницу п ер вый


источник данных SqlDataSo urce , кото рый бу,цет поста в л ять
список в сех городов и з та бл ицы Employees . На зови те его
sou r ceEmp l oyeeC i t i es
• ~ з ВЮlадки Standard панели Too lbox добав ьт е на страницу
элемент ynравл ения DropDown L i st , который будет отображать
все города , вы бра нны е источником sou r ceE mployeeC i t i es
из таблицы Employees . На зови те его ls t Ci t i es
• Г;;:;=ИЗ ВЮlадки Data пан ели Too lbox добавьте на страницу второй
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

источник данных, который будет выбирать всех сотру,цников из


таб лиц ы Employees , пр оживающих в п ередан ном ему из
р аскрывающегося lstC i ti es через парам етр городе.
списка

На зови те его sourceEmployees


• Г;;:;=ИЗ ВЮIaДКИ Data панели Toolbox добавьте на страницу элемент
управления Gri dVi ew с именем GridViewl , который будет
отображать список сотрудников, проживающих в выбранном
гор оде и получе нны х и з источника sourceEmp l oyees

• r;:Fн астройте объекты страницы так, как показано ниже.

При добавле нии параметров пользуйтесь удоб ны м редактором


оболочки, по зволяющим создавать команды и определять пара метры.
Редактор вызывается при выделенном элементе второго источника
source Employees щелчком на кнопке ( ... ) свойства SelectQue r y
Properties
в п анел и

S8..ECT coтrn.тd:

f;ELECТ ЕтpioуссD, F,"otN.Jmo, LxtN.Jmo, 111Ю, City FROМ Errployocs INt-f:RЕ City -@City

~
Refresh Paameters (>ну Е'Ше<.. I
P"..""",t".-s; Pi:I"~"",t".- sС<..п,, ;

R~~my~~~y,,
~~==~I::::::::::;I ~ Сlс~m~'~d=С=С~------СОiJ
aty IstCitJeS ,5€le:::tedV", • I
~ ,с=m~УСdС'DС-____________________-:l
--".J l ею",," iJ
DcfюtVаlю

Add Рзжпеtег

еж
I
Обратите внимание, что обратную отсылку мы выполняем за счет
"'
включенного свойства Аи t oPos t Ba c k раскрывающегося списка
lstC i ties . Обратите также внимание , что правильный перенос

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

строковой константы в свойстве Se lectCommand второго источника


н е влияет на возвращаемые SQL~команДой результаты .

<%@ Page Lапguagе="С#" %>

<html xm1пs=''httр://www.wЗ.огgl1999/xhtml'' >


<head nmat="server">
< title>Uпtitled Page</tide>
<lhead>
<body>
< fопn kl="fопnl" ruпаt="sеrvег' '>
<div>
< h2 > Выберите город < lh2>
<asp : SqlDаtа Sошсе ID="sошсеЕmp lоуееС ities" runat="server"
Connectio n5tring="<%$ connection5trings:Northwind % >"
Р roviderN аmе= "5 ystem. Data. 5 q IС liепt "
5е1есtСOIшna пd ="5ЕL ЕСТ DI5TINCT City FRQM Ешрloуееs" 1>
< аsр:DгорDоwпList ID=''1stCities'' runat="server"
Аиto Р ostBac k = 'True" Data 5 о игс е ID= "sошсе Етр lоуееС ities"
DataTextField="City" 1>

< h2 > Проживающие сотру,цники < lh2>


< аsр:sqlDаtа50шсе ID="sошсеЕmp lо уееs" nmat="server"
Connectio n5tring="<%$ connection5trings:Northwind % >"
Р roviderN аmе= "5 ystem. Data. 5 q IС liепt "
5e1ectCommand="5ELECT EmployeeID, FirstName, LastName,
TJtle, City FROM Employees WHERE C ity=@City''>
<5e)ectP arameters>
<asp :СопtrоlPагаmе tег N аmе= "City" Co ntrollD="lstC ities"
PropertyName="SelectedValue" 1>
</SеlесtРагашеtеrs >
</asp:5q lDataSource>
<asp:GridView ID="GrklViewl" runat="server"
DаtаSоuгсеID="sошсеЕmplоуееs" 1>
</div>
</foпn>
<!body>
<lhtml>

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET
Листинг ДеСlCрипторное представление страницы

SqlDataSourceParameters.aspx

• Г;:;=И сполните страницу SqlDataSourceParameters.aspx АЛ Я

получения следующего результата

Выберите город

I Lomon iJ
Проживающие сотру,цниЮ1

Emp!oyeeID FirsrName LasrName Title City


5 Steven ВисЬаnaп Sa!es Manager London
б Michae! Suyama Sa!es Representative London
7 Robert King Sa!es Representative London
9 Аnnе Dodsworth Sa!es Representative London

Здесь мы всю привязку данных источников данных к элементам


управления вы по лнили на этапе nроектuрованuя без всякого кода.

Вернемся к редактору команд и параметров, представленному р анее


окном

,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

=~
S8..ECT co т rn.тd:

SELE CТ Е т pioуссD , F r-о tN.J m о ,


LxtN.J mo,
То" , City FROМ Emi=*Jyees \.\It-fORЕ City = @City

ReFresh Paameters

Add PiI"ameter

еж
I
"'1
После набора команды в области SELECT coттand щелчок на кнопке
Refresh Parameters сканирует введенную командУ и заполняет другие
области и раскрывающиеся списки редактора н ужн ой инqюрмацией , из
которой можн о п отом быстро выб р ать требуемое значе н ие. В списке
Paraтe t e r source перечисле н ы тип ы элемен тов, которые MOryr
передавать значения параметров в источник данных:

• Cook i e
• Con t ro1
• Ротт
• Pro f i le
• Que r ySt ri ng
• Sess i on

в нашем случае и с п ользуется элемен т управле ни я DropDown Li s t ,


поэтому мы установили ти п парамет р а Cont r o 1.

Передача параметра источ нику данных через строку

,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

запроса

ПредыдуЩИЙ пример можно разбить на две страницы , чтобы


продемонстрировать способ передачи параметра через строку запроса
QuerySt r i ng . На первой странице мы определим списковый
элемент управления , который отобразит все города , находящиеся в
таблице Employees учебной базы данных Nor t hwind . На второй
странице БУдем отображать спи сак СОТРУдников, проживающих в
выбранном городе. Инqюрмацию о городе БУдем перенаправлять в
источник на второй странице через строку запроса. Там же и
отобразим результаты, полученные источником второй страницы.

• Г;:;=Создайте новую страницу с объединенным кодом и им ен ем


Que r yPa r a mete r 1 . asp x. Назначьте ее стартовой
• г;.:.=поместите на страницу источник данных SqlDataSource ,
списочный элемент Li s tBo x и кнопку Ви t ton
• u;.;rн астроЙте свойства элементов так, как показано ниже ,
ВЮlючая обработчики, полученные двойнь/Л1 щелчком на
свободном месте страницы ( Page Load ) и на кнопке (
cmdGo Cllck )

<%@ Page Language="C#" % >

<script runat= "server''>

protected void Page_Load(object sender, EventArgs е)


{
if (!IsPostВack)
IstCities.SelectedIndex = О;
}

protected void cmdGo_ Click(obj ect se nd er, EventArgs е)


(
Resp о nse. Red irect( "Q ueryP arameter 2 .aspx?se !ectC ity="
+ IstCities.Se!ectedVa!ue);
}
</script>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<html xmIns= ' huр ://www.wЗ.or&,1999/xhtml" >


<head runat= "server''>
< tidе > Стран ица выбора ropoAa </title >
<lhead>
<body>
<form id= "forml " nшat= "sе rvег ''>
<div>
< аsр:5qlDаta50шсе ID ="sошсеЕmр lоуееСitiеs" nmat= "server"
Provid erN аmе= "5 ystem Da ы. 5q IC lient"
connection5 trmg="<%$ Connection5trmgs:Northwmd %>"
5electCommand="5ELECT DI5ТlN CT C ity FROM Employees"
</as р:5 q lData5 о шсе >

<h2 >
Выберите ropoA <Ih2 >
< asp:ListВox ID=''lstCities'' nmat= "server"
Dаtа50шсеID= "s ошсеЕmрlоуее С itiеs "
DataTextField= "С пу">
</asp:ListВox>
< Ьг />
< Ьг />
<asp:Button ID="cmdGo" nmat= "sе rvег"Теxt=' При ме ни ть"
OnClick="cmdGo Click" />
</div>
</fonn>
</body>
<lhtml>

Листинг Разметочная часть страницы

QueryParameterl.aspx
• Г;:;=Создайте н овую страницу с объединенным кодом и им енем
QueryPara meter2 . asp x
• ~ оместите на страницу источник данных SqlDataSource
и элемент Gr i dView

• u;.;rн астроЙте свойства элементов так, как показано ниже

<%@ Page Language="C#" %>

<html xmIns= ' huр ://www.wЗ .or&,1999/xhtml" >


..,
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<head runat= "server''>


< tidе > Страница проживающи х сотр удн иков </titlе >
<lhead>
<body>
<form id ="forml " nmat= "server''>
<div>
<asp:S qIData 50urce ID="sourceEmp loyees" ruпаt="s еrvег"
СоппесtioпStriпg= "<%$ Со nnесtiоп5 tгiпgs:Nогthw iпd %>"
Provid erN аmе= "5 ystem Da ы. Sq IC lient"
5e lectCommand="5ELECT EmployeeID, FirstName, LastName,
City FROM Emp loyees WHERE C<y= @C ity''>
< 5electParameters>
<asp:Query5 triпgP агашеtег N аше= "С ity" QueryStringFie ld ="sl
<ISelectParameters>
<1as р:5 q lDataS о шсе >

<h2 >
Прожив аю щие сотру,цники < lh2>
<asp:GridView ID="GridViewl " runat="server" Data50urceID= "sou
</asp:GridView>
</div>
</fоПll>
</body>
<lhtml>

Листинг Разметочная часть страницы


QueryParameter2.aspx
• ~ с полните страницу QueryParameterl.aspx и у6еди т ес ь, чт о
запро с, сqюрми р ова нный на ней и направ ленн ый странице
QueryParameter2.aspx на об р аботку, дает то т же самый р езульта т,
что и в пр едьщущем прим е ре

Передача параметра источнику данных в хранимых


процедурах

Мы уже говори л и о достоинства х хр анимых nроцедур , которы е


пр едставляю т собой именованные 5Q L ~ КOMaH AbI , хра нимы е прямо в
базе дан ны х. Они более над еж ны , поскольку зара н ее проверены и

..,
отлажены. Они более безопасны , ПОСКОЛЬКУ н едостynны и зме н е ниям со
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

стороны кода страницы , а значит недостynны 1Лоумы шле ннику. Они


ynрощают ча сть нашей .aspx - страницы за счет п ереноса
действи тельного SQJ-запроса в базу да нны х, которы й может дост игать
на ст р а нице ВНУlшпельны х ра зме ров. Хранимые процедуры позволяют
п ередавать пар аметры , в том чи сле в источники дан ных.

Прежде всего , создадим и за пишем в базу данных хранимую процедуру


программным спо собом: н а этапе выполнения . Для это го создади м
страниц у.

• Г;;:;=Скопируйте командой Add Existing Item из при ложения

Web Site8 р а зработанную нами ра н ее ст р аницу

SаvеS torеdР го сеdше . аsр х и переименуйте ее в

SaveSto r edProcedurel . asp x


dd E><i5tng Item C·\a.Jr\Book \'NEВ\ЛSr>.NЕТ 2 О I!. С# (VSNET 2005)\9) Привmна дaI+ы'"

Lcok п 1"'::' WebSitoB

му FТ O)eCtS

:=J
Fles ofty~ : СI"~с=,.~"~.~')-------------'.:J
::;
'

• ~Откройте на редактирование ст р аницу

SаvеS torеdР го сеdше l .аsрх и откорректируйте ее так

<%@ Page Language="C#" % >

<script runat= "server''>

// Объявления хранимых процедур


// Выборка городов
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

string sq 11 =
"CREAТE PRO CEDURE GetCityes "
+ "AS"
+ ''SELECT Dl STINCT City FROM Employees";

// Выборка сотрудников для выбранного города


string sq 12 =
"CREAТE PRO CEDURE GetEmployeesByCtty"
+ "@paramCity varchar(1 5) "
+ "AS"
+ ''SELECT EmployeeID, FirstName, LаstNаше, 1itle, City"
+ ''FROM Employees WHERE City=@ paramC ity";

protected void Page_Load(object sепdег, ЕvепtAгgs е)


(
// ИзвлеюlИ строку соединения из wеЬ.со пfig
string сопneсtString = System. WеЬ.Сопfigшаtloп.WеЬСопfigшаtiоШ
СО ппесtio пS trings['N о rthwind '1. С о nnесtlo nS tгiпg;

// Создал и объект соединения


Systеm.Dаtа .SqIСlieпt.SqIСо nnесtiоп соп =
пеw 5 ystem.Data. SqlC lient. SqlСоппесtioп( co nnectS tring);

// Создал и объект Command


Systеm.Dаtа .SqIСlieпt.SqIСоmma пd cmd =
пе w System.Data. SqIClient.SqICommandO;

// Н астрои л и объект Соmma пd


сmd.Соnnесtiоп = соп;
сmd.СоmmaпdТуре = Systе m.Dаtа.Соmma пd Туре.Техt;

IblIпfо.Техt = "";

// Открываем соединение в безопасном режиме


try
{
соп.ОрепО;
}
catch
..,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

{
con.CloseO;
геtшп;

// Выполняем команды в безопасном режиме


// Удаляем процедУРЫ на случай повторного запуска этой стр
try
{
cmd.CommandText = ''DROP PROCEDURE GetCityes";
cmd. ExecuteN onQueryO;
IblIпfо.Техt += ' nРОlШJи \''DROP PROCEDURE GetCityes\"< bl
}
catch { }
try
{
cmd.CommandText = ''DROP PROCEDURE GetEmployeesByC
cmd. ExecuteN onQueryO;
IblIпfо.Техt += ' nРОlШJи \''DROP PROC GetEmployeesByCity\"
}
catch { }

// Выполняем команды в безопасном режиме


// Добавляем в базу данных хранимые процедУРЫ
try
{
cmd.CommandText = sql1;
cmd. ExecuteN onQueryO;
IblIпfо.Техt += ' nРОlШJи \"CREAТE PROCEDURE GetCityes\"<
}
catch { }
try
{
cmd.CommandText = sql2;
cmd. ExecuteN onQueryO;
IblIпfо.Техt += ' nРОlШJи \"CREAТE PROCEDURE GetEmploye
}
finаПу
{
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

con.CloseO;
}
}
</script>

<html XmInS= ' huр ://www. wЗ.or&,1999/xhtml' '>


<head id =' 'Не а dl '' runat="server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nшat= "sе lVег''>
<asp:Label ID="lb Unfo " nшat="sе lVег" />
</fonn>
</body>
<lhtml>

Листинг Код страницы SaveStoredProcedurel.aspx для


нового примера

• ~ сполните страницу SaveStoredProcedurel .aspx, чтобы


добав ить в базу данных Northwind две хранимых процедуры ,
одна и з которы х содержи т параметр

Теперь осталось воспользоваться этими хранимыми процедурами в


и ст очниках данных. Не МУдрствуя лукаво, мы пр осто заменим в двух
предыдущих примерах строку SQ L -запроса источников на имя хранимой
процедуры, а также изменим тип команды.

• г;.:.=СкопирУЙте страни цу SqlDаtаSошсеРагаmetеrs . аsрх и


при свой те ей имя S t o r edProcedure Pa r am . asp x . Назначьте
страницу S tогеdРroсеd шеРагаm.аs рх стартовой
• ~н есите в страницу S tогеdРгосеdшеРагаm.аsрх небольшие
измен е ния , чтобы о н а стала такой

<%@ Page Language="C#" %>

<html xmIns= ' huр ://www. wЗ.or&,1999/xhtml" >


<head runat="selVer''>
<tide >Untitled Page</tide>
<lhead>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<body>
<form id= "forml " nmat="server''>
<div>
< h2 > Выберите город<lh2 >
<asp:SqIData50urce ID="sourceEmp loyeeC ities" nmat= "server"
СоппесtioпS trmg="<%$ соппесtioп5trmgs:Nоrthwind %>"
Provid erN аmе= "5 ystem Da ы. Sq IC lient"
5еlесtСоmmaпd= "Gе tС ityеs "
5 е lectC о mmaпdТуре= "5 to red Proced ше ''>
</as р:5 q lDataS о шсе >
<asp:DropDownList ID="lstCities" runat="server"
AutoPostВack='True" DataSourceID="sourceEmployeeC ities"
DataTextFie!d="C ity" />

< h2 > Прожива ющи е СОТРУдники <lh2>


<asp:SqIData50urce ID="sourceEmp loyees" runat="server"
СоппесtioпS trmg="<%$ соппесtioп5trmgs:Nоrthwind %>"
Provid erN аmе= "5 ystem Da ы. Sq IC lient"
5еlесtСоmmaпd= "Gе tЕmрloуееsВуСitу"
5 е lectC о mmaпdТуре= "5 to red Proced ше ''>
< 5electParameters>
<asp:C ontro!P arameter C ontroIID="lstC ities"
N аmе= "рагаmС ity" PropertyName= "SelectedValue" />
</SelectParameters>
</as р:5 q lDataS о шсе >
<asp:GridView ID="GridViewl " runat="server"
DataSource ID="sourceEmp loyees" />
</div>
</fопn>
</body>
<lhtml>

Листинг. Код страницы StoredProcedureParam.aspx


• r;:;'и с п ол ни те ст р аницу 5 toredProcedureParam.aspx и убедитесь ,
что о на выдает точ н о та кие же результаты, как и стр а ни ца

5 q lDa ta 5 о urce Р arameters.aspx

Выберите город

..,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

I Loгtdon iJ
Проживающие сотру,цниЮ1

Emp!oyeeID FirsrName LasrName Title City


5 Steven ВисЬаnaп Sa!es Manager London
б Michae! Suyama Sa!es Representative London
7 RobeI1 King Sa!es Representative London
9 Аппе Dodsworth Sa!es Rерrеsе пtаtivе London

Теперь попро буем пр о верить раб оту хранимых процедур при передаче
параметра через строку запроса из одной ст р ан ицы в другую.

• ~ыделите в п а нели Sо lutioп Exp!orer сразу две страницы


QueryParameterl .aspx и Q ueryParameter2 .aspx и создайте их копи и с
име на ми QueryStoredProcParaml . aspx и

QueryStoredProcParam2 . aspx . Назначьте страницу

QueryStoredProcParaml .aspx ста ртов ой


• г;;;?Зап олните обе новых страни цы следУЮЩИМИ п оправками

<%@ Page Language="C#" %>

<scгipt ruпаt= "server''>

protected void Page_Load(object sепdег, ЕvепtAгgs е)


{
if (!lsPostВack)
IstСitiеs.Sеleсtеdlпdех = О;
}

protected void cmdGo_ Click(obj ect se nd er, EventArgs е)


(
Resp о nsе. Red iгect( "Q ueryS to red Рго сР ar am2 .asp х ?se IectC Ку= "
+ IstCities.Se!ectedVa!ue);
}
</script>

..,
<html xmIns='huр ://www.wЗ .or&,1999/xhtml" >
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<head runat= "server''>


< tidе > Стран ица выбора ropoAa </title >
<lhead>
<body>
<form id ="forml " nmat= "server''>
<div>
<asp:5qIData50urce ID="soureeEmp loyeeCities" nmat= "server"
connection5 trmg="<%$ Conneetion5trmgs:Northwmd %>"
Provid erN аmе= "5 ystem Da ы. 5q IC lient"
SeleetCommand="GetC ityes"
S е leetC о mmandType=' 'S to red Proeed ше ''>
</as p:S q lData5 о шее >

<h2 >
Выберите ropoA <Ih2>
< asp:ListВox ID=''lstC ities'' nmat= "server"
Data50ureeID= "soureeEmployeeC ities"
DataTextField= "С пу">
</asp:ListВox>
< Ьг/>
< Ьг />
<asp:Button ID="emdGo" nmat= "sе rvег"Теxt=' При ме ни ть"
OnClick="cmdGo_Cliek " />
</div>
</fonn>
</body>
<lhtml>

Листинг. Код страницы QueryStoredProcParaml.aspx

<%@ Page Language="C#" %>

<html xmIns= ' huр ://www.wЗ.or!j'1 999/xhtml" >


<head runat= "server''>
< tidе > Стран ица проживающих еотр удн ико в </titlе >
<lhead>
<body>
<form id ="forml " nmat= "server''>
<div>
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

< аsр:5qlDаta50шсе ID ="sошсеЕmрlоуееs" runat= "server"


Соппесtюп5tring="<%$ Connection5trings:Northwind %>"
Provid erN ате= "5 ystem Da ы. 5q IC lient"
5electCommand="GetEmployeesByCity"
5 е lectC о mmandType= "5 to red Proced иге' '>
< 5electParameters>
<asp:Query5 tringP агашеtег N аше= ' 'рагаmCitу'' Q uery5 tringFiI
</5electParameters>
</as р:5 q lData5 о шсе >

<h2 >
Проживающие сотру,цники < lh2>
<asp:GridView ID="GridViewl " runat="server" Dаta50шсе ID ="sо u
</asp:GridView>
</div>
</fonn>
</body>
<lhtml>

Листинг. Код страницы QueryStoredProcParam2 .aspx


• ~ сполните страницу Query5toredProcParaml.aspx и убедитесь ,
что получился тот же результат, что и в соответствующем прим ере

без использования хранимых процедур, но код вышел более


удоб ным (все переходим на хранимые процедуры!)

Обработка исключений источников данных

Любая среда исп ол нения программ при возникновении ошибки выдает


соответствующее сообщение, которое для пользователя представляет
наб ор непонятных символов. Задача прикладного программи ста -
предусмотреть в своем приложении п ерехват этого сообщения ,
распознавание е го и заме н у на более понятные для пользователя
рекомендации. Даже есл и код нашей страницы не содержит Оl.Ш1бок, все
равно сбой может произойти по причинам, от на с не зависящим .
Например , может быть не запущен во время за про са страницы сервер
базы данных или разорвано соединение с н е й.

Сбо й в работе источника данных SqlDataSource сопровождается


гене р а цией события, которое прои сходит сразу по сле возникновения
,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

ошибки. Сбой при выполнении запроса выбрасывает событие


Selected, а при обновлении , вставке или Удалении записей -
события Updated , Inse rt ed или Deleted соответственно. Мы
можем пр едусмотреть обработку каждо го из этих событий в
отдельности или запланировать общий обработчик на любой из эти х
сбоев.

в обработчике ошибок можно получить доступ к объекту


сгенерированного ИСЮlючения через его свойство
SqlDataSourceStatus EventA r gs . Ex cept i on . Если после
выброса ИСЮlюч е ни я мы хотим подавить его далнейшее
распространение , то в обработч ике должны установи ть
SqlDataSourceStatus EventA r gs . Ex cept i onHandled в

t r ue .

в качестве примера предусмотрим общий обработчик возможных


ИС Юlючений источника данных Sql Da t a So urce на выполнение всех
четырех операций выборки, обновления, вставки и удаления записей в
базе данных .

• ~Создайте копию страницы SqIDаtаSошсеSimрlе.аsрх с именем


Sql Da t aSou r ceE x cep ti on . азр х и назначьте ее стартовой
• ~Откройте страницу SqIDаtaSошсеЕхсерtioп .аsрх на
редактирование в режиме Design и двойным щелчкам на

свободном месте Web-формы создайте обработчик


Page Load ( )
• ~ обработчике Page Load () начинайте набирать строки
кода регистрации событий объекта источника данных
Sql Da t aSou r cel страницы , активно пользуясь под сказчиком

кода

'"
В.М. СН"""'
f~~'~~~~~~;~~~~S;:h::::::::::~П~
SqlDataSourceException,aspx* ":'':':":"~-
~ :~"~"~'~"~":"~''~N~'i"..
Ser\ler Objects & Events ~

< %@ Page Language-"C#" %>

B <scr:ipt r: un a t ="server:">

protected void Page Load( object sender, EventArgs е)


(
SqlDataSourcel.se
11 PreReno:ier
</ scr:ipt> :s" ProVidErName
.~ Resd veClentltl

IB-<html xmlns ="httD: 11 .. '" Resdve\.X1


1[_ -<head run a t =" ger:ver") ·~ Seect
<titl e )-I)nti tled 1:jI S€lectcоmm юd
</ head>
,L- <b ody >-
~вSeiК;tJ:iiс!imimiariТiilУР'i• • • •'-1
'1 Seectn;;J
' г_ -<for:m i d =rrforml"
~ selec1Fз-аmеters •
l_I.l- -<d iv >-

• ~Следуйте указани ям подсказч ика кода и наж имай те клавишу


ТаЬ, чтобы п авильно сге н е и овать за гатавк об аботч ика
8«<>О! d8<u,oE>O«Ption_><*
"""' .. Obj<ct . ......,..
<\е F . ~ e Lon~u.ge- · C ~" '~

a<~c<ip t e~not _ · 'Hvee">

:,ot~ct~d чоid paqe_1.Oddlotj~ct ~~ndo", ~~o~tA[q, е!

l L
</~c<lpo
~ qlDot .SQ uc<:;~ 1 . 8 ~ 1 = t ed +=
lIi<W Вф"OIIOUU!IIotuoEY_(S<p>tOllou<>ol-"_U<I)' (f!ш ,-'" '" ",<ftj

• г;.:.=указанным способом за регистр ируй те события (и создайте для


каждого из н их об р аботчики)
о Selected
о Upda t ed
о Inse r ted
о Dele t ed

По сле пр о веде нны х де йс твий стра ниц а s qlDа ta sоurсеЕхсерtЮп.аsрх


до лжна выглядеть так

<%@ Page L апguagе="С#" %>

<script nmat="server''>
В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

protected void Page_Load(object sender, EventArgs е)


(
SqlDataSourcel.Se lected += пеw SqlDа tаSоurсеS tаtusЕvе пtН аrкl lег(Sq [
SqlDataSourcel.Updated += пеw SqlDataSourceSta tusEve ntНandler(Sq[
SqlDаtaSоurсеl. l пsегtеd += new SqlDа tаSо uгсеStatusЕvепtНа пdlег(S q ID
SqlDataSourcel .Deleted += new Sq lDataSourceStatusEventHandler(SqlD
)

void SqlDataSo urcel_ Deleted(object sender, SqlDataSourceStatusEventArgs


(
throw new Ехсерtio п('Тhе metlюd or орегапо п is поt imр lеmепtеd. ') ;
}

void SqlDаtaSо uгсеl _l пsеrtеd(оЬjесt sender, SqlDataSo urceStatusEventArg


(
throw new Ехсерtio п('Тhе metlюd or орегапо п is поt imр lеmепtеd. ') ;
}

void SqlDataSo urcel_Updated(object sender, SqlDataSourceStatusEventArg


(
throw new Ехсерtio п('Тhе шеtlюd or орегапо п is поt imp lemented. ') ;
}

void SqlDataSourcel_Selected{object sender, SqlDataSourceS tatusEventArg


(
throw new Ехсерtio п('Тhе шеtlюd or орегапо п is поt imp lemented. ') ;
}
</script>

<html xm1пs =' 'httр ://www.wЗ.огgl 1 999/xhtml'' >


<head nmat="server">
< title > Uпtitled Page</tide >
<lhead>
<body>
< fопn id ="fопnl " runat="server''>
<div>
<asp :SqlDataSource ID="SqlDataSource 1" гuпа t="sеrvег"
Р roviderN аmе = "system. Data.S q IС liепt "
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Connectio nString="<%$ connectionStrings:Northwind %>"


Sе1есtСOIшna пd =
"S ELECT EmployeelD, FirstName, LastName, Тitle, City FROM Empl<
<asp:ListBox ID="ListВo x l " runat= "server" DаtаSошсе ID ="Sq lDаtаSошс
DataTextField=''FirstName '' 1>
<br 1>
<br 1>
<asp:GridView ID="GrklViewl " runat= "server" DаtаSошсеID="S qlDаtaS<
<br 1>
<aspButton ID="Buttonl" runat= "server" Теxt= "Обновить" /></div>
</form>
</body>
</html>

Листинг Промежуточный .од страницы

SqlDataSourceException.aspx

• ~OCTaBbTe только один обработчик, а остальные удалите


• r;:;'и змените имя оставше гося общего обработчика на
SqlDataSou r cel Error и внесите это имя в регистрацию
каждо го соб ытия , чтобы блок кода сценария стал таким

<script nmat= "server">

protected void Page_Load(object sender, EventArgs е)


(
SqlDаtaSошсеl.Sе lесtеd += new SqlDаtаSошсеStаtusЕvепtНаrкllег(Sq[
SqlDаtaSошсеl.uрdаtеd += new S qlDаtaSошсеStа tusЕvе пtНапd1е г(Sq[
SqlDаtaSошсеl .l nsегtеd += new SqlDa taSo urc eStatusEventНa ndler( S qlD
SqlDаtaSошсеl.Dеle tеd += new Sq lDаtаSошсеStatusЕvе пtН а пdlег( SqlD
)

void SqlDataSourcel_Error(object sender, SqlDаtаSошсеS tаtusЕvепtA гgs е :


(
)
</script>

Листинг Блок кода сценария страницы

SqlDataSourceException.aspx

,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Теперь осталось обработать возможное ИСЮlючение источника данных


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

• ~ оместите в конец страницы текстовую метку Label с


именем l blE rr or

• г;;;?Заполните обработчик ошибки источника данных


предУПреждающим кодом, чтобы окончательно страница стала
следующей

<%@ Page Language="C#" %>

<script runat= "server''>

protected void Page_Load(object sender, EventArgs е)


{
SqlDа tа Sошсе l .Sе lесtеd += new Sq lD a taSourc eS tatusEventНandl(
SqlDа tа Sошсе l .Uрdаtе d += new SqlDаtаSошсеStаtusЕvепtНапdlЕ
SqlDа tа Sошсе l.lns е rtеd += new sqlDаtаsошсеS tаtusЕvепtНа пdle
SqlDа tа Sошсе l.D е lе tеd += new SqlDа ta SошсеS tаtusЕvе пtНапd lei
}

void SqlDаtаSошсеСЕггог(оЬjесt sender, sq lDаtаsошсеS tatus Еvепt


{
if (e.Exception != null)
{
// Изве ст и ть пользователя , что команда не была завершена
Ib lErroг.Text = "< Ы style='color:#FFOOOO'>"
+ ' При испол н е нии запроса произоllИО ИСЮlюч ени е ! < /h

// Изве ст и ть с и стему, что ошибка обработана


e.ExceptionНandled = true ;
}
}
</script>

<html xmIns= ' huр ://www.wЗ.or!j'1999/xhtml" >


<head runat="server''>
<tide >Untitled Page</tide>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<lhead>
<body>
<form id= "form1 " nmat= "selVer''>
<div>
<asp:SqIDataSource ID="Sq lDаtаSошсе 1" nmat= "selVer"
Provid erN аmе= "5 ystem Da ы. 5q IC Iient"
СоппесtюпS tring="<%$ соппесtюп5trings:Nоrthwind %>"
5electCommand=
"5ELECT Emp!oyeeID, FirstName, LastName, 1ide, с ку FROM
< asp:ListВox ID=''ListBoxl'' runat="selVer" DataSource ID=''S qlDat
DataTextField=''FirstName'' 1>
< Ьг 1>
< Ьг 1>
<asp:GridView ID="GridViewl " runat="selVer" Data50urceID="5qI
< Ьг 1>
<asp:Button ID =''Вuttоп l '' nmat="selVer" Техt="Обновить " 1>
<asp:Labe! ID="lb lError" runat= "selVer" 1>
</div>
</fопn>
<!body>
<lhtml>

Листинг Окончательный код страницы


SqlDataSourceException.aspx
• u;.;rч тобbl ИСПblтать обработчик ИСЮlюч е ния , внесите какую­
нибуд ь ошибку в строку запроса (измените имя поля или иска зи те
SQL - оператор) и запустите страницу. Результат БУдет таким

При IIСИО.'шеНIIII '!аироса IIIIОIВОШ.тJО IIСКТlЮ'lение!

Редактирование записей в источнике данных

Чтобbl дать во зможность пользователю редактировать записи в


механизме множественной прuвязки данных, не обязательно писать
дополнительный код. Можно настроить источник данных и элемент
отображения так, чтобbl редактирование данных происходило
автоматически. СПИСКОВblе элемеНТbI отображения не им еют
возможностей редактирования, а более СЛОЖНblе элемеНТbI , такие как

,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Gr i dVi ew, Deta i lsVi ew и FormView имеют таЮ1е средства ,

которые можно в них включить .

Настройка возможностей редактирования состоит из двух шагов:

1. О п ределения SQ L -о п е р аций в соответствующи х свойствах


UpdateQuery , InsertQuery и Dele t eQue r y
2. На стр ойЮ1 элемента отображения

КаЮ1е операции с данными мы хотим р азре шить поль зователю, таЮ1е


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

Прив едем пример, в котором дадим возможность пользователю

редактировать таблицу Emp l oyees учебной базы данных


Northwind .

• Г;:;=Скопируйте страницу SqlDataSourceSimple.aspx с именем


Sql DataSou r ceUpdates . азр х и назначьте ее стартовой
• г;.:.=удалите из нее объекты списка Lis t Bo xl и кнопЮ1
В u t t о n1, чтобы остались только источник данных
Sql D а taSou r ce 1 и элемент отображения Gr i dV i ew l
• ~ с полните страницу, чтоб ы убедиться, что дан ные ,
извлеченн ые источником из таблицы Employees , по - пр еж н ему
отображаются в Gr i dV i ew l

Теперь настроим источник на об н овление да нны х.

• ~ыделите в режиме Dеsigп источник данных


Sql DataSou r cel и в панел и Properties щелкните на кно п ке с
м н оготочием в поле UpdateQue r y , чтобы запустить редактор
формирования SQL-комаНАbI обновления за писей с параметрами
• ~Заполните поле UPDATE comтand редактора строкой SQ L-
команды с параметрами

UPDAТE Еmрюуееs SET FirstName= @FirstName,


LastName=@ LastName, 1itle= @1itle, City= @City
FROM Employees WHERE EmployeeID=@ EmployeeID
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

После щелчка на кнопке Refresh Parameters ав томатич ески заполнится


поле Paraтeters , как показано на р и сунке

LfDATE соmrnз:-кi:
lPD ~ТE ЕrrvЮ УОО S SEТ Fr- stN.JmО-@Fr-stN.JmО, LastN.Ynо-@...astN.J.-ne , Т1t1з-@Тfu ,
Oy =:ij)City FROМ Е т plo"ее; W i-fllЕ Е m ploуееЮ = @:t m ploу",Ю

~
ReFresh Paameters (>ну Е'Ше< .. I
P,.-"гт-oo=t".-s ; Рi:I"~гт-оо=t".- 5('_П" ;

"No~mgy~]jY~""~;;;;;;;;F;;;;;;;;;;;;;;;;;; ~ I,iij.
IIJ _._• •113
3
~rstNзmе • I
LastNзm е ~ [)"fcOJtV"L..:

~i~
ЕmploуооЮ
~I% ..... зdviПЫ !Xcootjes

Add Paameter

еж
I41
После таких действ ий редактор п араметров сге н ерирует

допол ни тельные поправки в настройку источника данных ,


дес крипторное оп и сание которо го станет таким

<asp : Sq lD аtа50шсе ID="SqlDаtа50шсе 1" runat="server"


ProviderN аmе= "5 ystem.Data. SqlC lient"
Connectio n5tring="<%$ connection5trings:Northwind %>"
5e)ectCommand=
"5 ELECT EmployeelD, FirstName, LastName, Тitle, City FROM Emp loy€
UpdateComma nd ='UPDAТE Еmрюуееs SET FirstName=@FirstName,
LastN ame=@ LastName, Td:le =@Тitle, City= @C ity
FRO M Employees WHERE Еmр ю уееI D =@Еmрю уееID">
<Update Parameters>
<asp:Parameter Name=''FirstN аmе " 1>
<asp:Parameter Name=''LastName '' />
<asp:Parameter Name='Тitle" 1>
<asp:Parameter Name="C ity" 1>
,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<asp:Parameter Name=''EmployeeID'' />


<lUpdateParameters>
</asp:Sq lDataSource>

Обратите внимание , что им е на пара метров, пр едва ря ем ых символом @,


мы выбр ал и совпадающими с именами полей таблицы . Это необходимо
потому, что объект GridViewl п осле при вязЮ1 к нем у источника
да нных будеть иметь колле кцию столбцов с именами полей , которые и
будуг вы ступ ать в кач естве пар аметров для обм е на при об н овлении
за писе й . Такое соглашение именования параметров должно
выполняться для всех э леме нт ов управления данными ASP.NET
множественной привязЮ1 .

• Г;;:;=И сполните стран ицу SqlData SourceUpdates.aspx с в н есен ными


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

п о яви лос ь

Теперь осталось настр о ить инте рфей с ный объект Gr i dViewl на


возм ож ность редактирования да нны х . Для этого добавим к
GridView l до полнительн ый столбец с функциями управления
редактирова ни ем за писе й .

• ~ызовите внугреннюю панел ь настройЮ1 объекта


GridViewl , как п оказано на рисунке, и выберите пункт Edi t
Соlиmnз

,,,
в.м. СН"",,,В Про,рйммupoвtJNШ' Na ASP.NET
SqlDataSourceUpdates.aspx*

~qOatasource - SqOataScucel !шшшшшшшшшшшшшшшшшшшшшш.


GГldVlеw Tasks
'batabo1Uld ColODatabo1Uld Col1Databo1Uld Со
Auto Fспnаt ..
;аЬс О аЬс
аЬс 1 аЬс Crm se Dаtз Yu-ce : I SфJtзsо.JГсеl ~I
аЬс 2 аЬс ConflgJe Оаtэ Scuce"
аЬс аЬс Лleта

________
3 Refresh

"аЬ~'________~4С- ~аЬ
~'_________ :d
~t~СiclJ~mш
AooN
~~~~~~ с,
IEd t the Grt:!Yiew 's cctJ mnsl
Г Еп ЮleР~

Г Еп Юle 5a"th]
Г Еn Юle Ed th]
Г Еп Юle Selecbo'l
Ed t Те rrфtеs

Появ и тся ди ало говое о кн о Fields, которое предоставляет в удобном виде


н астройки столбцов объекта GridViewl

Flelds

АvalЮle ftelds : Bc:u-кFieId P"operties:


[I] Вc:<J:d=ieId ,,- ГАТ1
1
"'-~
. ИJ CheckВoxFieId
Acces sbleНeader Т ext
&iJ НyperLIi<.FieId Ap;JyFcr matI rEdtМxi Fase
, tgJ ImageFieId S CootrolStyIe
g] ВuttCn=ieId
CoovertErrp tySIrilgTo True
~БJ Comm zn::1 FieId DаtзFieId E~yeeID
.!Е TemplateFieId
DаtзFcr matStrh;)
S FooterStyIe
FooterText
~ader I ~
Selected ftelds :
[I] т n/П

"'"
~ ФiМ.1ЛИЯ
IIJ
.~!!!-~~ "1" T,~

Insert Visble True


[IJ Статус
[I] Г):ю~т
mИзмен--,пь НeadeгText
ТЬе text l'Iit!-il the Ьезder of ths field .

г Auto-generate fteIdS Coovert!lis ficlj nto а Terro!.a1:eFicld

Refresh хЬеmз

• ~ с п ользуя диало говое окно Fields выполни те следующее:


о Сбросьте флажок A uto - generate f i elds , чтобы

ею
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

ОТКЛЮЧИТЬ неконтропир уемое отображ е ние всех столбцов


о Добавьте кнопкой Add в поле Selected f i elds пять
столбцов типа BoundFie l d , которые БУдУГ свя заны с
источником д анных
о Выделяя каждый из пяти добав л енных столбцов ,
опред елите их свойства Da taF i eld (имя связыв а емого
поля в и с точнике данных) и HeaderTe xt (отображаемый
на экране за головок столбца)
о Добавьте шестой столбец типа CommandF i eld/Edit ,
Upda t e , Саnсеl и задайте ему следующие свойства:
• Еdit Т е х t= " Редак ци я "
• СапсеlТе х t= " От м еиа "
• UрdаtеТе х t= " Пр и мени т ь
• ButtonType= " Button "
• Неаdе r Те х t= " Из м еи и ть "
• Heade r Sty l e/ BackColo r = " Red "
• Heade r Sty l e/ForeColo r = " Yellow "

в результате таких опосредованных дей ствий оболочка сф:Jрмирует


следующее описани е объекта Gr i dV i ew l

<asp:GridView ID="GridViewl" runat="server" D аtаSошсе I D=''S q lDаtaSошсе


AutoGenerateCo lumns=''False'' >
<Co lumns>
<aspBoundField DataField=''Emp loyeeID'' HeaderText=''NQ п /п" 1>
<aspBoundField DataField=''FirstName'' НеаdегТехt="И мя" 1>
<aspBoundField DataField='1.astName" Неаdе гТехt= "О тч ество" 1>
<aspBoundField DataField=''Iit1e'' HeaderText="CTaTYc" 1>
<aspBoundField DataField="City" Н еаdегТеxt='Прож и вает" 1>
<asp :CommandField ButtonType='Button" НеаdегТехt=' И змен и ть"
ShowEditButton='True" ShowHeader='True"
Ed itText= ''Р едакци я" С апсе fТe xt=' 'Отме н а" U pdate Те xt= 'ПРИ ме н и ТI
<HeaderStyle BackColor='Red" ForeColor= ''Yellow'' 1>
</asp:CommandField >
</Columns>
</asp:GridView>

в итоге окончательный код страницы БУдет следующим

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<%@ Page L апguagе="С#" %>

<script nmat="server''>
11 Здесь м ы не напи сал и ни стро чки кода!!!
</script>

<html xm1пs=''httр ://www.wЗ.0гgl1999/xhtml'' >


<head nmat="server">
< title >Uпtitled Page</tide>
<lhead>
<body>
< fо пn id="fопn1" runat="server''>
<div>
<asp : S qlDаtа 50шсе ID="Sq lDаtа 50 шсе 1" runat="server"
Р roviderN аmе= "5 ystem. Data. S q lC liепt"
Connectio n5tring="<%$ connection5trings:Northwind % >"
5e}ectCommand=
"5ELECT ЕшрloуееID , FirstNаше, LastName, Тtde, City FROM EIТ
UрdаtеСоmшaпd=''UРDАТЕ Ешрloуееs SET FirstNаme=@FirstNаше
Lа stNаme=@ Lа stNа ше , Tlt1e=@1ide,C ity=@City
FRQM Employees WHERE Employee ID=@EmployeeID" >
<Update Рагашеtегs >
<asp:Parameter Nаше=''FirstN аше" 1>
<asp:Parameter Nаше=' 1.. аstNаше" 1>
<asp:Parameter Nаше=''Iidе'' 1>
<asp:Parameter Nаше="С itу" 1>
<asp:Parameter Nаше=''Еmp lоуее ID '' 1>
<IUpdateParameters>
</asp:5q lDataSo urce>
<asp:GridView ID="GridView1" runat="server" Dаtа Sошсе ID="5qlDа ta S<
AutoGenerateColumns=''False'' >
< Соluпms>
< аsр:ВоundField DаtаFiеld ="ЕшрlоуееID" HeaderText=''NQ п /п" 1>
< аsр:ВоundField DataField="FirstName" Н еа d егТехt=' И мя" 1>
< аsр:ВоundField DataField="LastName" Н еаdе гТеxt="Фамил ия " 1>
< аsр:ВоundField DataField=''Iide'' HeaderText="CTaTYc" 1>
< аsр:ВоundField DataField="City" Неаd е гТеxt=' Пр ож ива ет" 1>
< аsр:СошmaпdFiеld ButtonType='Button" Н еаdегТеxt=' И зменить"
5lюwЕditВuttоп='Тruе" ShowHeader='True"

в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

EditText= ' 'Редакция '' Cancerrext='OTMeHa " Uрdа tеТеxt=''Прим(


<HeaderStyle BackColor="Red" ForeCo!or= ''Yellow'' 1>
</asp:CommandField>
</Columns>
</asp:GridView>
</div>
</form>
<lbody>
</html>

Листинг Окончательный дескрипторный "ОД страницы

SqlDataSourceUpdates.aspx

• ~Запустите страницу и испытайте ее функцион альность.


Можно спокойно редактировать за писи , не написав при этом ни
строчки кода - все делает встроенный механизм ASP.NET

Стра ница SqIDаtаSошсеUрdаtеs.аsрх в действии может выглядеть так

Имя Фамилия Статус Проживает Изменить

1 N апсу Davolio Sa!es Representative Redmond


2 Andrew Fuller Vice President, Sales Тасоша

3 Janet Leverling Sa!es Representative Kirk1and


4 Margaret Peacock Sa!es Representative Redmond
5 5 teven Buchanan Sa!es Manager London
б МкЬае! Suyama Sa!es Representative London
7 Robert King Sa!es Representative London
In side Sa!es
8 Lаша Ca.llahan Redmond
Coordinaror
9 Владимир Снетков Доцент 007 Красноярск

В добавленном столбце управления редактированием (его можно


разместить на любом месте, и зме нив порядок следования
дескрипторов) щелчок на кнопке ' 'Применить '' инициирует обратную
отсылку, которая при поступлении на сервер п е редает источнику

з нач ения коллекции пар аметров, используя имена полей , и за тем



В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

вызывает метод SqlDataSource . Update() ДЛЯ внесения

изменений в базу данных .

Можно создать аналогичные параметриЗ0ванные команды в и ст очнике


данных для свойств и
DeleteQuery . Чтобы
InsertQuery
разр ешить , н а п ример , вставку в элементе отображе н ия Gr i dVi ew,
н ужно доба вить ynравляющий столбец типа Co mmandField и
установить его отобр аж ение в свойстве Show l nsertBu t t on

Flelds

АvalЮle ftelds : Соm lТJ.З:""d'ieId lXoperties:

-,
&iJ НyperLIi<.FieId ,,-
>- ,
[!]
, .g] Im ageFieId
Seiectl rnageLXl
g] Вuttс:П'ieId
SeiectText
1;].!iJ Соmm ю::JFieId SI-ю....сю::eВuttоо T~
m Ed t, Цx1ate , сю::eI Sl-юv.DeieteВuttоо ,асе
- g] Seiect
SГюwEdtБuttоо ,асе
..m
Delete
5m""'_ ,асе
,,~
-'.J
Sl-юwSelectБuttоо ,асе

So:xtExlXessio1
Selected ftelds :
Цxiзtе l rnageLXl
[I] т п/п
ЦxiзtеТехt "сМе
~ "'"
IIJ ФiМ.1ЛИЯ
Vaida~oц:>
Vrsb!e T~
[IJ Статус
[I] Г):ю~т
ShowInseгtButton
mИзмен.1ть
ii] New, Insert, сю::eI 'Nhether the field Sh::Ud dspIзу ап hsert Шtton to ,

г Auto-generate fteIdS Convert!lis ficlj n to а Terro!.a1:eFicld

Refresh хЬеmз

Об новление данных при параллель ном доступе

в сетевых приложениях множество пользователей MOryr работать с


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

н есколькими пользователями , но в базе будуг сохра н ены изменения

''''
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

пользователя , сбросившего обновления последним.

Такая ситуация называется конкуренцией данных или конфликтом


изменений. Для ее решения применяются разные способы, один из
которых опирается на тот факт, ЧТО в элементе отображения Gr i dVi ew
хранятся как оригинальные значения полей , так и их последние
изменения. Сам источник данных может оперировать с д вумя видами
параметров: оригинальными , носящими имя поля с префиксом
or ~ g ~ nal по умолчанию (например , @o rl glnal F lr stName ), и
измененными , носящими имя поля. Источник может понимать имена
ориrn.нальных параметров и с другим префиксом, который можно
установить в его свойстве OldValuesParameterFo r matSt ri ng
(например, ххх {О } ).

Принимая решение о сохранении конечных изменений в базе да нны х,


мы можем сконфигурировать в источнике данных команду обновления
так, что она выполнится только в том случае, если с момента

считывания нами данных их никто не менял. Например

UpdateCommand='UPDAТE Еmрюуееs SET FirstName= @FirstName,


LastName=@ LastName, Til:Ie=@ТItle, City=@C ity
FRO M Employees WHERE EmployeeID=@original_EmployeeID
AND FirstName=@original_FirstName
AN D LastName=@original_LastName
AN D ТItle= @ origina l_ТItle AN D City= @original_City"

Здесь для пров ерЮ1 н еизменности полей в базе данных при меняются
ориrn.нальные параметры , переда нные из Gr i dVi e w в источник

данных, а для замены - параметры с модифицированными значениями.


Приведенная команда выполнит обновление значений полей только тех
записей, которые остались неизм енными с момента их считывания
нашей страницей.

подобную проверку конфликта изменений данных не обязательно


закладывать в SQ L-команду обновления. Эту обязанность можно
возложить на источник данных , пом е няв в нем значение свойства
Con f l i c t Detection с Ove r wri teChanges (заменять без
проверЮ1 , установлено по умолчанию) на CompareA l lValues

(заменять только при совпадении все х ориrn.нальных значений).


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Применение параметров обновления , не

совпа,цающими с именами полей

Ранее м ы говорили , что н еобход и мым условием пр авильной пересылки


да нны х из GridVie w в SqlDataSource с целью обновления
конечных дан ны х долж но быть совпадение имен пар аметров с им е нами
полей табл ицы. Но иногда может возникнугь необходимость применить
для обновления конечных данных чью-то подходящую хр анимую
процедуру, в которой им е на параметров отличаются от имен пол е й , и ли
использовать более информативные имена параметров. Чтобы обойти
упомянугое условие совпадения им е н пар аметров и полей ,
декларативного способа (только настройки объектов на этапе
проектuрования) не существует, тр ебуется писать дополнительный код
сценария.

Рассмотрим этот способ на пример е.

• ~Скопируйте страницу 5qIDаtаSошсеUрdаtеs.аsрх с им ен ем


otherNameParamUpda te s . asp x и назначьте ее стартовой
• ~ pOBepbTe, что страница OtherNameParamUpdates.aspx работает
• Г;;:;=Назовите параметры источника другими именами , отличными
от имен полей, например так

< аsр:SqIDаtaSошсе ID="SqIData50 urcel " nmat= "server"


Provid erN ате=' '5 ystem. Оа ы. Sq IC lient"
Connection5tring="<%$ connection5trings:Northwind %>"
SelectCommand=
"5ELECT EmployeeID, FirstName, LastName, 1ide, С пу FROM Е!
Up dateCommand ="UPDAТE Employees SET FirstName =@ p aramFiг.
LastName=@paramLastName, Trtle= @ paramТitle, City=@ paramC
FROM Employees WHERE EmployeeID= @paramEmployeeID">
<UpdateP агашеtеrs >
<asp:Parameter Name=''paramFirstName'' Type="string" />
<asp:Parameter Name=''paramLastName'' Type="string" />
<asp:Parameter Name=''paramTrtle'' Type= "string" />
<asp:Parameter Name=''paramCity'' Type="string" />
<asp:Parameter Name=''paramEmployeeID'' Type="string" />
<lUpdateParameters >

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</аsр:SqIDаtаSошсе >

Листинг Назначение параметрам хоманды обновления


других имен

• ~3апустите страницу OtherNameParamUpdates.aspx и убедитесь ,


что конечные обновления в базе да нных не выполняются из за
того , что измененные поля не передаются из GridViewl в

источник данных SqlDa taSource 1

Для решения задачи используем событие


SqlDataSource . Updating , которое возбуждается
непосредственно перед подтв е рждением обновлений.

• ~ ерейдите в режим Design редактировани я страницы


OtherNameParamUpdates.aspx и двойным щелчком на свободном
месте Web-формы создайте обработчик события Page Load ()
• ~3айдите в тело обработчика и начинайте регистрировать
событие Upda ting источника данных , н абирая следующий код

SqIDаtа Sошсе l .Uрdа ting +=

ТаЬ
OtherNameParamupdate5.a5px*
Server Object5 & Event5
<%@ Page Language ="c#~ %>

8 -< SCI: ipt I:unt'i.t =~зеl:vеl:~>


11 Здесь мы не написали ни строчки кода!!!

pl:otected void Page Load{ object sender, EventArgs е)


(
5qlData50u r ce l .up
"iТ TempateSCU rcect"ectcry •
-</script> • ToStrir.;J
'!f! u-q..oeID
8 <html xrnlns =~http://,; -1 u-I03:J
- -<head rUn8.t =~server") Q ЦXJate
<title>Unti tled I 'ff! ЦXiatесоmmапd
</head> '!f! ЦXiatесоmmапdrуре
- -<body>
_too
-<form id="forml"
<div>

''''
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Оболочка создаст прав ильную заготовку обработчика события


Upda ti ng . Теперь можно полностью удалить обработчик
Page Load () как н еиспользуемыЙ.

• ~далите н е н ужный тепер ь обработчик Page Load ()


• г;;.:;='Добавьте к описанию источника атрибyr
OnUpdatlng= " SqlDataSource l Upda tl ng "

Здесь мы ПОlШlи более длинным , но универсальным n yreM создания


заготовки обработчика Sq lD ataSou r cel Updat l ng () . З на комый
нам более короткий и традиционный пyrь - создать заготовку
обработчика ч е рез п анель Properties, при этом имя обработчика
а втоматически доб авится в описание источника данных.

• Г;;:;=Заполните обработчик события Upda t i ng так, чтобы


страница и мела следующий ви д

<%@ Page Language="C#" %>

<script runat= "server''>

void SqIDаtаSошсеСUрdаting(оЬjесt sender, Sq IDаtа SошсеСоmmaJ


{
// Пер едать значения нестандартным именам параметров
e.Command.Parameters["@paramFirstName"].Value :=
е .Command.Parameters["@ FirstName"].Value;
e.Comma nd. Parameters["@paramLastName"].Value :=
e.Command.Parameters["@LastName"].Value;
e.Comma nd.Parameters["@paramTil:1e"].Value :=
e.Command.Parameters["@1ide"].Value;
e.Command.Parameters["@paramCity"].Value :=
е .С о mma nd .Р arameterS["@City"]. Value;
e.Command.Parameters["@paramEmployee ID"].Value :=
е.Соmmaпd . Рагаmеtегs[ "@ ЕmpЮуееI D "].Vа luе;

// Удал и ть и з коллекции стандартные и ме н а параметров


e.Command.Parameters.Remove(e.Command.Parameters["@ FirstN
e.Command.Parameters.Remove(e.Command.Parameters["@ LastN

""
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

e.Command .Parameters.Remove(e.Command.Parameters["@Tttle'T
e.Command .Parameters.Remove(e.Command.Parameters["@City'T
e.Command .Parameters.Remove(e.Command.Parameters["@Emplo
}
</seript>

<html xmIns='huр://www.wЗ.or!j'1999/xhtml" >


<head runat= "server''>
<tide > Untitled Page</tide>
<lhead>
<body>
<form id= "forml " nmat="server''>
<div>
<asp:SqIData50urce ID="Sq lData50uree 1" nmat="server"
Provid erN аmе= "5 ystem Da ы. Sq IC lient"
СоппесtюпString="<%$ соппееtюп5trings:Nоrthwind %>"
5e leetCommand=
"5ELECT Employee ID, FirstName, LastName, Тitle, City FRC
UpdateCommand='UPDAТE Emp loyees SET FirstName=@par~
LastName=@paramLastName, Тide=@paramTttle, City=@pal
FROM Employees WHERE Employee ID=@paramEmployeeJ:
OnUpdating= "Sq lData50ureel_Updating" >
<UpdateP arameters>
<asp:Parameter Name=''paramFirstName'' Type="string" />
<asp:Parameter Name=''paramLastName'' Type="string" />
<asp:Parameter Name=''paramТide'' Type="string" />
<asp:Parameter Name=''paramCity'' Type="string" />
<asp:Parameter Name=''paramEmployee ID'' Type="string" />
<lUpdateParameters>
</as р:5 q lDataS о шее >
<asp:GridView ID="GridViewl " runat="server" Data50urceID="5qI
АutоGепегаtеСоlШ11I1S=''Fаlsе'' >
<Columns >
< asp:BourкlFiekl DаtаFiеld =''Еmpюуее ID '' HeaderText=''NQ n l
< asp:BourкlFiekl DataField =''FirstName '' НеаdегТеxt=' 'Имя '' /:
< asp:BourкlFiekl DataField =''LastName'' НеаdегТехt= "Фами л
< asp:BourкlFiekl DataField ='Тide " HeaderText="CTaTye" />
< asp:BourкlFiekl DataField =''City'' НеаdегТеxt=' 'Проживает ''
< аSР:СО П1JnaпdFiеkl Вuttо пТуре=''Вuttоп'' НеаdегТеxt= "И зме

""
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

ShowEditВutton=' True "ShowHeader='True"


Еd itТехt=''Редакция''
Cancerrext= "OTMeHa" UpdateText= "
<HeaderSty!e Васk Со !ог= ' 'Rеd '' ForeCo!or=''Yellow'' 1>
</аsр:СоmmaпdFiеkl >
</Co !umns>
</asp:GridView>
</div>
</fOmI>
<!body>
<lhtml>

Листинг Окончательный код страницы


OtherNameParamUpdates.aspx
• ~3апустите страницу OtherNameParamUpdates.aspx и убеди те сь ,
что она сохранила пр ежние сп особности обновления данных в
базе

Переход им к следующей части ...

Старательно сопишь - значит победишь

Компонент управления источником данных

ObjectDataSource

Компон ент ObjectDataSource находится на вкrщцке Data панели


Toolbox. Он позволяет создавать декла р атив ны м (на этапе
праектирования) cnо с обом связь между элементом отображения и
компо н ентом доступа к данным, который запрашивает и обновляет и х .
Он является более rnбким по с р ав н ению с источникам данных
SqlDa taSource . Но для корректного применения п ользовательский
класс доступа к дан ны м, которым может быть и разработанный на ми
класс , должен подчиняться нескольким правилам:

1. Пользовательский класс не должен сохранять состояние ,


п оскольку ObjectDataSource создает е го экземпляры по

необходимо ст и и уничтожает их за собой в конце каждого запроса


2. Пользовательский класс долже н иметь конструктор по
умолчанию (без аргументов)

,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

з. Компонент должен быть представлен только одним классом. Если


для решения разных частей одной задачи используются несколько
классов , то они долж ны быть упакованы в оболочку одного
высокоуровневого масса

4. Ни один ИЗ основных рабочих методов, используемы х для


извлечения и обновления записей, не долже н быть статическим.
Они должны быть то лько методами экземпляра
s. Каждый тип за про са (извлечение, вставка , удале ние и
обновление) должен быть представ ле н еди н ственным методом ,
возвращающим результаты запроса

б. Результаты запроса долж ны р азмещаться в общедоступных


свойствах, которые представляют собой коллекции , массивы и ли
списковые объекты , реализующие инт е рфейс IEn umerabl е
7. Пользовательский компонент доступа к данны м должен
р азмещаться в папке App_Code или быть скомпилированным в
сборку и пом еще н в пап ку Вin

Выполнение этих правил гарантирует, что nривязка данных будет


простой и организована без дополнитель ны х ус и лий с нашей стороны.
Отступление от правил требует написания дополнительного кода.

Простое использование ObjectDataSource

Для даль н ейшего рассмотрения применим пользов ат ельский компонент


доступ а к данн ы м , разработанный на м и ранее, в пр остом в ар ианте:
конструктор без пар аметр ов (конструктор по умолча нию ) и метод без
параметров .

• ~ a корне Web-дерева создайте п а п ку App_Code командой


кон текстного меню Add ASP.NET Fokler
• r;:;=н a папке Add_Code выполните командУ Website/Add Existing
Item и скопируйте из папки WebSite8/App_Code все ее содерж имо е ,
которое пр едставляет собой описание пользовательско го масса
EmployeeDB

СО,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Add EXlstNlg Item - C:\Chalf \Book\WEB\ASP.NET 2.0 8< С# (VS.I\ET 2005)\9) Привязка данныx AD

Look п:

f,1y Project5

Ае rn т е :

ICode Fles (*. \.Ь ;*.cs;*.р ;*.}зvа ;*. хsd;*.wsd)


FIes ofty]::e:
L
Вспомним, что ра н ее мы поместили в базу да нн ых с помощью
страницы WebSite8/SaveStoredProcedure.aspx хранимые процедуры .

• ~Скопируйте в текущее п риложение страницу


WebSite8/SaveStoredProcedure.aspx, откройте ее и п осмотрите, что
хранимые процедуры объявляются в ней так

II Объявления хранимых процедур


II Вставка записи
striпg sql1 =
"C REAТE PROCEDURE InsertEmployee"
+ "@EmployeeID iпt OUТPUТ, "
+ "@ FirstName varchar(10),"
+ "@ LastName varchar(20),"
+ "@ 1it1eОfCошtеsу уа гсшг( 25)"
+ "AS"
+ '1NSERT INTO Emp loyees "
+ "(1ideOfCourtesy, LastName, FirstName, HireDate)"
+ 'VA LU ES(@ndeOfCouгtesy, @ LastName, @FirstName, GЕШАТЕ())'
+ "S ET @EmployeeID = @@ IDЕ NПТУ";

,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

11 Удаление записи
striпg sql2 ==
"CREAТE PROCEDURE De)eteEmployee "
+ "@EmployeeID iпt"
+ "AS"
+ ''DELEТE FROM Employees WHERE EmployeeID == @EmployeeID";

11 Обновление записи
striпg sq13 ==
"CREAТE PROCEDURE Upda'eEmployee"
+ "@EmployeeID iпt, "
+ "@FirstName varchar(10),"
+ "@LastName varchar(20),"
+ "@1itleОfCошtеsу уагсшг(25)"
+ "AS"
+ 'UPDAТE Еmрюуееs "
+ "SET"
+ ''FirstName == @FirstName,"
+ ''LastN аmе := @LastName,"
+ 'TltleOfCourtesy = @Tlt!eOfCourtesy"
+ 'WHERE EmployeeID = @EmployeeID";

11 Выбрать все
striпg sq14 :=

"CREAТE PROCEDURE GetAllEmployees "


+ "AS"
+ "SELECT ЕmрюуееID, FirstName, LastName, TltleOfCourtesy"
+ ''FROM Employees";

11 Подсчитать число записей


striпg sqlS :=

"CREAТE PROCEDURE CountEmployees "


+ "AS"
+ "SELECT COUNT(EmployeelD)"
+ ''FROM Employees";

11 Выбрать запись
striпg sql6 ==
"CREAТE PROCEDURE GetEmployee "
,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

+ "@EmployeeID int "


+ "AS"
+ "SELECT Еmрюуее ID , FirstName, LastName, TltleOfCourtesy"
+ ''FROM Employees "
+ 'WHERE EmployeeID = @ Employee ID";

Листинг

в их числе и процедура Ge t AI IEmp l oyees , которую реализует в


пользовательском классе Emp l oyeeDB одноименный метод
GetAII Employees ( ) . Э та процедУРа и звлекает из таблицы
Emp l oyees за пи си четырех полей в порядке их следования в строке
ЗQПРОСQ. Если мы укажем пом еще нному на страницу компоненту
ObjeetDataSou r ce имя нашего пользовательского класса и и мя

метода, который реализует в классе нужный SQL -запрос , то


Obj ее tDa taSou r ce сам создаст эюемпляр это го пользовательского

класса и вызовет указанный метод. В результате, объект


пользовательско го класса будет заполн е н да нны ми, которые увидит
пользователь через при вязанные к компоненту Obj ее tDa taSou r ce
элементы отображения.

• ~С оздайте новую страницу с совмещенным кодом и именем


Obj ectDa t aSou r ceS i mple . азр х . На значьте ее стартовой
• ~ еренесите на страницу
Obj ectDa t aSou r ceS i mple . азр х из панели Toolbox
следующие компон е нты

о ObjeetDa taSou r ee из вкладки Data


о Li s tBo x из вклад ки
Standard
о Gr i dVi еw извкладки Data
• u;.;rвыполните прос тые настройки свой ств ком пон е нтов , чтобы
окончательный код страницы стал таким

<%@ Page Language="C#" %>

<html xmIns='huр ://www.wЗ.or!j'1 999/xhtml" >


<head runat="server">
<tide >Untitled Page</tide>
<lhead>
<body>
,,,
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<form id= "forml " nшat="sеlVег''>


<div>
< аsр:ОЬjесtDаtаSошсе ID="ОЬjесtDаtаSо шсе l " runat="selVer"
S е lectМ ethod = "GetAllEmp 10 yees"
TypeName=''EmployeeDB'' 1>
< asp:ListВox ID=''ListBox1'' runat="selVer"
DаtаSошсе ID ="О ЬjесtDаtaSошсе 1" DataTextField= ''LastN а mе'
<asp:GridVlt'w ID="GridView1" runat="selVer"
DаtаSошсе ID ="ОЬjесtDаtaSошсе1" 1>
</div>
</fonn>
</body>
<lhtml>

Листинг Код страницы ObjectDataSourceSimple. азрх


после декларативных настроек

• ~ сполните страницу ОЬjесtDаtаSошсеSimplе.аsрх, чтобы


получить следующий результат

LastName l1t1eOfCourtesy EmployeeID FirstName


Davolio Ms . 1 Nancy
Fuller Ог. 2 Andrew
Leverling Ms . 3 Janet
Peacock Mгs. 4 Margaret
Buchanan Мг. 5 Steven
Suyama Мг. б Michael
King Мг. 7 Robert
Callahan Ms . 8 Lаша

Снетков Доцент 007 9 Владимир

ИСЮlючитель но пр остой получилась прuвязка данных к элементам


отображения через ком п онент Obj ectDa taSource . Никакого кода не
п ришrюсь писать. Прямо - работа ДЛЯ дизайнеров или кухарок! Но
,о;
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

пользовательский- то Юlасс EmployeeOB мы ран ее с вами создали. Его


просто здесь н е видно - он работает за кулисами и вызывается по
ссылке , указан ной в свойстве TypeNa me компонента
ObjeetDataSouree . Эл ементы отображения , в свою очередь ,
получают свою порцию да нных через ссылку на заполненный
Obj ее tDa taSource , указанную в свойстве Оа taSource I о.

Использование ObjectDataSource с параметризованным


конструктором пользовательского класса

Компон е нт ObjeetDataSouree сам создает эюемпляр

пользовательско го масса и мы не имеем возможности деЮlа р атив но

п ередать в н е го инqюрмацию ч е рез параметры конструкто р а. Но можно


воспользоваться событиями компонента ObjeetDataSouree, чтобы
обойти эт о ограничение.

Компон е нт ObjeetDataSouree и меет богатую модель событий ,


пр едставленную ниже

• Sys t em . Web . U I. WebControls . 0bjeetDataSouree . De J


• Sys t em . Web . U I. WebControls . 0bjeetDataSouree . De J
• Sys t em . Web . U I. WebControls . 0bjeetDataSouree . F i j
• Sys t em . Web . U I. WebControls . 0bjeetDataSouree . In~
• Sys t em . Web . U I. WebControls . 0bjeetDataSouree . In~
• Sys t em . Web . U I. WebControls . 0bjeetDataSouree . Ob~
• Sys t em . Web . U I. WebControls . 0bjeetDataSouree . Ob~
• Sys t em . Web . U I. WebControls . 0bjeetDataSouree . Ob~
• Sys t em . Web . U I. WebControls . 0bjeetDataSouree . Se J
• Sys t em . Web . U I. WebControls . 0bjeetDataSouree . Se J
• Sys t em . Web . U I. WebControls . 0bjeetDataSouree . Upc
• Sys t em . Web . U I. WebControls . 0bjeetDataSouree . Upc

Эти события можно разделить на д ве категории:

1. 3аканчивающиеся на ing - прои сходят во время выполнения


задач и и позволяют вмешаться в этот проц есс, что -то настр ои ть

или прервать

,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

2. Заканчивающиеся на ed - происходят по завершении задачи и


удобны для протоколирования де йствий , синхронизации других
элементов управления или обработки ошибок

Если мы хотим передать компоненту ObjectDataSource уже


инициализированный параметризованным конструктором готовый
эюемпляр пользовательского масса, то этот эюемпляр нужно самим

создать с вызовом нужного конструктора. И сделать это нужно в


обработчике события Obj ее tDa taSource . Obj ectCrea ting .

Продолжим эксплуатировать наш класс Emp l oyeeDB , в котором как


раз есть параметризованный конструктор наряду с конструктором по
умолчанию. Он принимает произвольную строку соединения и имеет
ВИД

usiпg System;

usiпg System. WеЬ.Сопfigшаtiоп;

public partial class EmployeeDB


(
private striпg соnnесtiопStriпg;
public EmployeeDB()
(
11 Изв ле чь из файла web.config строку соединения по умолчанию
со nnесtiопS triпg:::: WеЬСопfigurаtionМаnagеr.
С о nnеспо nS triпgs [ ''N оrthwiпd "]. С о nnе с йо nS triпg;
)

public ЕmрloуееDВ(striпg со nnе сtiопS triпgСustоm)


(
11 Изв ле чь из файла web.config другую строку соединения
со nnесtiопS triпg:::: WеЬСопfigurаtionМаnagеr.
С о nnеспо nS triпgs [ со nnеспо пS tringC usto m]. С о nnectio nS tring;
)
}

Листинг Параметризованный конструктор в файле

EmployeeDB.cs

СО,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• IJ$Скопируйте страницу ОЬjесtDаtаSошсеSimрlе.аsрх под им енем


ObjectDa t aSou r ceDesigne r . asp x и назначьте ее

стартовой
• ~3апустите страницу, чтобы проверить , что конструктор по
умолчанию работает и извлекает из файла Web.Config строку
соединения с именем "N or t hwind "
• r;:;=в файле WеЬ.Сопfig скопируйте строку соединения с
идентификатором " Northwind " под другим им ен ем

" CloneNorthw i nd " , после чего должно получиться следующее

<?xml version= "l.O'?>


< сопfigшаtiоп>
< соnnесtiопStrings >
<add name=''N orthwind" connectionString=''Data Sо шсе= l<
Iпitial Catalog=Northwind; user id=sa; password=;" />
<add name=''Clo neNo rthwind'' connectio nString=''Data Sо шсе
Iпitial Catalog=Northwind; user id=sa; password=;" />
</соппесtioпS trings >
<system.web >
<compilation debug=''true''/>
</system. web>
</соnfigшаtiоп>

Листинг Файл Web.Config после ~лонирования стро~и


соединения

• r;.:Fизмените в файле Web.Config имя строки соединения


" Northwind " на несуществующее имя , наприм е р

" Northwindl" и вновь запустите страницу. Теперь страница


выдает ошибку, поскольку конструктор по умолчанию ищет в
файле Web.Config строку соединения с им ен ем "N or thwi nd "

Пусть теперь это ошибочное имя строки соединений пока побу,цет в


файле Web.Config, а мы попробуем запустить конструктор по
умолчанию, чтобы страница искал а строку соединения с им ен ем
" CloneNorthwind ", которая у нас есть.

• IJ$Откройте страницу на редактирование в режиме Design и


выделите на н ей объект Obj ectDa taSource 1
• ~ ереведите панель Properties в режим редактирования
,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

событий и двойным щелчкам на поле Objec t Cr ea tin g


создайте обработчик это го события

Properties ....- .r;t х

ObjectDataSourcel System,Web,UI,Wel'"
--=1 1~
rn~ ~ "-J 1"""
....:iI

DаtaЕАndlП\JL-_,
D€~ted IEvents I
D€lebr>;]
Osposed
F~tering
IПlt
Inserted
Inserting
Load
ObJectCreated
ОЬ ectCrea1Jn •
ObjectDisposilg
PгeRend€г
Selected
Selecbng
LklkJad
Updated
Updabng

• г;;;?Заполните обработчик так, чтобы окончательный код


страницы ObjectDataSourceDesigner.aspx был следующим

<%@ Page Language="C#" %>

<script runat= "server''>

protected void ObjectDataSourcel_0bjectCreating(object sender, ОЬ.


(
e.ObjectInstance = new Emp loyeeDB("C loneNorthwind'');
}
</script>

,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<html xmIns= ' huр ://www.wЗ .or&,1999/xhtml" >


<head runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="form1" nшat= "sе rvег ''>
<div>
< аsр:ОЬjесtDаtаSошсе ID="ОЬjес tDаtа Sо шсе 1 " runat="server"
Sе le c tМ ethod = "GetAllEmp 10yees"
TypeN аmе = ''EmployeeDB''
ОпО bjectC reating="O ЬjесtDаtаSошсе 1_ObjectC reating" 1>
< a s p :ListВox ID=''ListBox1 '' runat="server"

DаtаSошсе ID ="О ЬjесtDаtaSошсе 1" DataTextField= ''LastN аmе '


<asp:GridView ID="GridView1" runat="server"
DаtаSошсе ID ="ОЬjес tDа ta Sошсе1" 1>
</div>
</fопn>
<lbody>
<lhtml>

Листинг Окончательный код страницы


ObjectDataSourceDesigner.aspx
• ~Запустите страницу ОЬjесtDаtаSошсеDеsignег.аsрх и убедитесь ,
что опять все заработало , поскольку новую строку соединения
пользовательский объект теперь п олучает через
параметризованный конструктор в обработчике
• ~ерните в файле Web.Config прежнее имя " No rthwind "
строке соединения, поскольку его используют все наши

предыдущие страницы (строку с именем " CloneNorthwind "


также оставьте для работы это го п ри мера)

Использование ObjectDataSource с параметризованным


методом пользовательского класса

По синтаксису настройЮ1 компонента ObjectDataSource мы не


можем использовать ни параметризованный конструктор, ни
параметризованный метод, поскольку свойствам Selec tM ethod,
In sertMethod, DeleteMeth od и Upda te Method можно

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

присваивать тол ько имя метода. Р еальны е же методы поль зо вательского


масса MOryr содержать пар а м етры . Наприм е р , в н а шем массе
Emp l oyeeDB содержатся следующие п араметри зо ванные методы :

• publ i c i nt Inser t Emp l oyee(EmployeeDeta i ls


еmр) ( ... )
• publ i c EmployeeDe t ails GetEmployee( i nt
employeeID) { ... )
• publ i c void DeleteEmployee(int emp l oyee I D)
( ...)
• publ i c void UpdateEmployee(int emp l oyee I D,
st ri ng f irstName , str i ng lastName, st ri ng
ti tleO f Cou r tesy) { ... }

Мы воспользуемс я методом GetEmp l oyee (int employeeID) ,


который ранее был опи с ан так

public EmployeeDetails GetEmployee(int employeeID)


(
SqlСо nnесtiоп соп = пеw SqIСоnnесtioп(соnnесtioпStгing);
SqlСоmmaпd спx:l = new SqIСоmmaпd("GеtЕmрloуее ", сап);
сmd. С оmmaпdТуре = соmma пdТуре.Stо геdРгосеdше;
cmd.P агаmetеrs . Аdd(пеw SqlP arameter("@ EmployeeID ", SqIDbType . Iпt,
cmd.Parameters["@EmployeeID"].Value = employeelD;

try
(
со п.Ор е пО ;
SqIDataReader reader = сmd.ЕхесutеRеаdег(СоmmaпdВеhаviог.Single:
11 Получить п ервую строку
reader.ReadO;
Emp loyeeDetaiJs еmр = пеw EmployeeDetails(
(int)reader[''Employee ID'1,
(striпg)геаdег[ ''F irstN аmе "],
(string)read ег[ '1..astN аmе "],
(striпg)геаd ег[ ' Тit1eO fC о шtеs у" ]);
reader.CloseO;
геtшп еmр;

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

}
catch
(
throw new АрросаtiоnEхсе рtloп( "Ошибка да нных.');
}
fiпаlly
(
con.C loseO;
)
}

Листинг Описание метода GetEmployee () пользовательского


класса EmployeeDB

Метод GetEmployee() вызывает хранимую nроцедуру


GetEmployee с парам етром , имеющую следУЮЩИЙ вид

11 Вы б ра ть з а п и с ь
string sql6 =
"C REAТE PRO C EDURE GetEmployee "
+ "@EmployeeID int "
+ "AS"
+ "S ELECT Еmрюуе е ID , FirstName, LastName, TttleO fC ourtesy "
+ ''FROM Employees "
+ 'WHERE EmployeeID = @ Employee ID";

Листинг Хранимая процедура GetEmployee

Сейчас наша задача создать страницу на основе компонента


ObjectDataSou r ce и пользовательского масса EmployeeDB, в

которой при загрузке автоматически заполнялся бы список з н аче ниями


Emp l oyee I D из табли цы Emp l oyees , а при щелчке польз ователя на
конкретном элементе списка выдавались бы остальные сведе ния о
выбранном сотру,цнике .

• ~Создайте н овую страницу с совмещенным кодом под именем


Obj ectDa t aSou r cePa r ameters . asp x и назначьте ее
стартовой
• ~ оместите на страницу из п анели Toolbox следующие
компоненты в порядке их перечисления:

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

о ObjectDa taSource из ВЮIaДКИ Data


о Дескриптор <h2>Выбер ит е IO сотрудн и к:а</h2>
о Li s tBo x из вклад ки Standard
о ObjectDa taSource из вкладки Data
о Дескриптор <h2>Да нн ые о со т руд ни к:е</h2>

о Dеtа i lsV i еw извкладки Data

Настроим компоненты страницы ОЬjесtDаtаSошсеРагаmеtеrs.аs р х


д екларати вным способом в режиме Design через панель Properties.

• ~ыдел и те первый источ н ик ObjectOataSourcel и


уста н ов и те для не го следУЮщие свойства
о SelectMethod= " GetA l lE mp l oyees " - автоматически

вызываемый метод
о TypeName= " Emp l oyeeDB " приме н яемый
пользовательский класс
• ~ыделите сп и сок Lis t Bo x l и устан овите для него
следУЮщие свойства
о DataSourceID= " ObjectOa t aSourcel "
подключенный источник данных
о DataTe x tField= " Emp l oyee I O" - видимые данные

списка

о AutoPostBack= " True " инициирует обратн ую


отсылку списка

о Rows=9 - количество видимых строк

о Wi dth= 1 о О - I.Ш1ри н а в пuкселах

• ~ыделите второй и сточ ни к Objec t DataSource2 и


уста н ов и те для не го следУЮщие свойства
о SelectMethod= " GetE mployee " автоматически

вызываемый метод
о TypeName= " Emp l oyeeDB " приме н яемый
пользовательский класс
• ~елчком на кнопке ( ... ) в п оле свойства
ObjectOa t aSou r ce 2 . SelectParameters вызови те

диалоговое окно, которое за п ол ни те так

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET
",aтc t" . <.Х> 1 С< I ЮП Ldito.
==~ 211<1

Работа этого окна трансqюрм ируется в следующий дескр ип тор ныи код
разметочной части ст р ани цы

<asp:O bjectDataSollГce ID="O bjectDataSollГce2" runat= "server"


SelectMethod="GetEmployee" TypeName=''EmployeeDB''
О пSеlеСtlng= "О bjectDataSollГce2_Selectlng" >
<SelectP arameters>
<asp :СопtrоlPагаmеtег СопtrоlID= '1.istВoxl "
Name="employeeID" PropertyName="SelectedValue" />
</SelectParameters >
</asp:O bjectDataS ollГce >

Имя для передаваемого в источник ObjectDataSou rc e2 пар аметр а


долж но повторять имя формального параметра, указанного при
объявлении метода

public EmployeeDetails GetEmployee(int employeeID) {... }

поскольку источник допускает перегруэку прикр е пленного метода на

основании анализа числа пер еда нны х параметров и их имен в

объявлении метода (явного-то вызова метода нет!).

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


самого ObjectDataSou r ce , их типы и регистр н е учитываются ,

главное - т о чные имена и их количество. В каком регистре набира ется


имя парам етра при декларативном объявлении в разметочной ч асти

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

страницы значения не имеет, лишь-бы оно повторяло и мя


формальною аргумента в объявлении ПОДЮlючаемого метода.

• r;:;'выделите элемент отображения данных Detai l sV i ewl и


уста нови те для него следУЮщие свойства
о DataSourceID= " ObjectDa t aSou r ce2 "
о AutoGenerateRows= " False " подавляет

самостоятельное ген ер ировани е строк для всех полей без


разбора
• ~3апустите страницу ObjectDataSourceParameters.aspx и
получите ошибку выполнения!!!

Дело здесь в том, что когда страница запрашивается в первый раз, нет
никакого выбранного значения в элементе Li s t Bo xl , но элемен т
ObjectDataSource2 все равно вызовет метод GetE mployee () с
неопределеННblМ значением emp l oyee I D. Э то и вызовет генерац ию
ИСЮlючения в поиске данных. Ситуа цию можно исправить, если
перехватить попытку привязки в элементе Objec t Da t aSou r ce2 и

явно отменить ее, когда пара метр employeeID н е определен.

Для это го нужно обработать событие


Obj ее tDa taSource . Selec t i ng , которое как раз происходит перед

выполнением SQL-запроса по пои ску данных в базе данных . Если мы


проверим коллекцию I nputParameters и не обнаружим в ней
параметра e mployeeID, то работу ObjectDataSource2 н ужно
будет прервать.

• ~Создайте в панели Properties для события


Obj ectDa t aSou r ce 2 . Selecting обработчик, который
заполни те так, чтобы окончательный код страницы

ОЬjесtDаtаSошсеРагаmetеrs.аsрх был следующим

<%@ Page L апgua gе="С#" %>

<script nmat="server''>

protected void ОЬjес tDа ta S о шсе2 _ Sе lе сtiпg(оЬjе сt sе пdе г,


О Ьjе сtDаtаSо шс е S е le сtiпgEvепtAгgs е )

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

(
if (e.lnputParameters["employeeID"] == null)
е.Сапсеl = tпJе ;
}
</script>

<html xmlns=''httр://www.wЗ.огgl1999/xhtml'' >


<head nmat="server">
<title>Untitled Page</tide >
<lhead >
<body>
< fопn id="fопnl" runat="server''>
<div>
<asp:O bjectDataSource IО ="О bjectDataSource 1" runat="server"
Sе1есtМеthоd="GеtAllEmрюуееs" TypeN ате= "ЕmрюуееDВ" 1>

<h2 >
Выберите IО сотрудника<lh2 >
<asp:ListBox ID="ListВoxl " nmat="server" AutoPostВack='True"
DataSourceID="ObjectDataSource 1" DataTextField=''Employee Ш"
Rows=''9'' Width="100px" 1>

<asp:O bjectDataSource IО ="О bjectDataSource2" runat= "server"


Se1ectMethod="GetEmployee" TypeName=''EmployeeDB''
О nS electing= "О bjectDataSource2_Selecting" >
<Se)ectP arameters>
<asp :ControlParameter ControllD= ' 1.istВoxl "
Nаme="ешрюуееID" PropertyName="SelectedValue" 1>
</SelectParameters >
</asp:O ЬjectDataSource>

<h2 >
Данные о СОТРУднике<lh2 >
<asp :DetailsView IО= ''Details Viewl" runat="server"
Height="50px" Width="12 5рх" DataSourceID=''ObjectDataSource2''
AutoGenerateRows=''False'' >
<Fields >
<asp :ВоundField DataField= "LastN ате"
HeaderText='1.astN аmе" SortExpressio n='1.astName" 1>
,ОС
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

<asp BoundField DataField= 'ТItleO fCourtesy"


HeaderText='TrtleO fCourtesy" So rtExpressio n='ТIt1eO fCо шtеsу" 1
<asp BoundField DataField= "EmployeeID"
HeaderText=''EmployeeID'' SortExpression=''EmployeeID'' 1>
<asp BoundField DataField= "FirstN аmе"
HeaderText=''FirstN ате" SortExpression=''FirstN аmе" 1>
<lFields>
</asp:DetailsView>
</div>
</form>
<!body>
<lhtml>

Листинг Охончательный .од страницы

ObjectDataSourceParameters.aspx

Элеме н т управле ни я Deta i lsVi ew отображает только одну запис ь в


виде таб ли цы с двумя столб ца ми, оди н из которых содержи т имена
п оле, второй - их значения .

• r;:;'и с п олните ст р аницу о ь jectData 5 ошсе Р arameters.asp х и

получите результат

Выберите ID сотрудника

2
3
4
5
6

,
7

Да нны е о сотрудн и ке

LastName Снетков

1itleOfCourtesy Доце нт 007


EmployeeID 9
FirstName Владимир

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

АналоП1ЧНЫМ образом можно задействовать и другие методы нашего


пользовательского класса EmployeeDB, имеющие параметры:

• publ i c i nt Inser t Emp l oyee(EmployeeDeta i ls


еmр) ( . .)
• publ i c void DeleteEmployee(int emp l oyee I D)
( ...)
• publ i c void UpdateEmployee(int emp l oyee I D,
st ri ng firstName , s t ring lastName, st ri ng
ti tleO f Cou r tesy) { . . }

Использование ObjectDataSource для обновления


записей

Продемонстрируем возможность подключен ия к ОЬ j ее t Da t а 50 u ree


метода UpdateEmployee () пользовательского класса EmployeeDB,
предназначе нного для обновления записей таб ли цы Emp l oyees . За
одно посмотрим, как правильно вызвать перегруэку этого метода , если в

качестве параметра используется д ругой пользовательский тип ,


эюемпляр которого прежде нужно создать , и только потом передать

компоненту Obj ее tDa ta50uree как параметр.

Применение исходного метода UpdateEmployeeO

Вначале используем метод UpdateEmp l oyee () в том виде с


четырьма параметрами, как он был разработан нами ранее. Для
сокращения работы используем часть наработок страницы
SqlDаtаSошсеUрdаtеs.аsрх. Метод Upda t eEmployee () реализует
SQL·команду хранимой процедуры UpdateEmployee , имеющей
следующий вид

11 Обновление записи
string sql3 =
"C REAТE PROCEDURE UpdateEmployee "
+ "@EmployeeID int, "
+ "@ FirstName varchar(10), "
,ее
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

+ "@ LastName varchar(20),"


+ "@ 1it1eОfCошtеsуvагсhаг(25) "
+ "AS"
+ 'U PDAТE Employees "
+ "S ET "
+ ''FirstName = @ FirstName, "
+ ''LastN аmе = @ LastName, "
+ ' ТItleOfCourtesy = @1itleOfCourtesy"
+ 'WHERE EmployeeID = @ Employee ID";

С а м сущест вующий метод UpdateEmp l oyee () о п исыв ает ся та к в


фа й ле App_ Code/UpdateEmployeeDB.cs

public void UpdateEmp loyee(int employeeID, strmg firstName,


string IastName, string titleOfCourtesy)
(
SqlConnection соп = new SqIConnection(connectio nStrmg);
SqlCommand cmd = new SqICommand('UpdateEmp loyee ", соп);
сmd.Сопuna пdТуре = соmmaпdТуре.StoгеdРгосеdше;
сmd.Рагашеtеrs . Аdd(пеw SqIPагашеtег("@Еmр lоуееID ", SqIDbType. Int, 4)
сmd.Рагашеtеrs["@Еmрlоуее ID "].Vаluе = employeelD;
сmd.Рагашеtеrs . Аdd(пеw SqIPагашеtег("@FirstNаmе", SqlDbType.NVarCh
сmd.Рагашеtеrs["@FirstNаmе"].Vаluе = firstN аmе;
cmd.Parameters.Add(new SqIParameter("@LastName", SqIDbType.NVarC h
сmd.Рагашеtеrs["@LаstNаmе"] . Vаluе = IastName ;
cmd.P arameters .Add(new SqlP arameter("@ TJtleOfCourtesy", Sq IDbType.N\
cmd.P агашеtеrs[ "@ 1it1eОfCошtеsу" ].Vаluе = titleO fCourtesy;

try
(
соп.Оре пО ;
cmd.ExecuteNonQuery();
}
catch
(
throw new АрросаtiоnEхсерtioп("Ошибка данных.");
}
finally
(

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

con.C loseO;
}
}

• ~С копируйте страницу 5qIDаtаsошсеUрdаtеs.аsрх с именем


ObjectDa t aSou r ceUpdates1 . asp x и назначьте ее

стартовой
• ~Запустите страницу о ь j ectDa ta S ошсе U pdates 1.aspx на

выполнение и Удостовертесь, что о на работоспособна


• ~далите элемент Sq 1 DataSource1 и на его месте
р асположите объект Obj ectDa taSource 1
• г;.:;=настроЙте объект ObjectDataSou r ce1 следУЮЩИМ
образом
TypeName= " Emp 1 oyeeDB "
о

SelectMethod= " GetA l lE mp l oyees "


о

о Upda t eMethod= " UpdateE mp l oyee "

• ~Объект Gr idViewl подкорр ектируйте так:


о DataSourceID= " ObjectDa t aSou r ce1 " - поменять

подключаемый источник данных


о <asp : BoundFie l d DataFi eld= " City "
НеаdеrТе хt = " Про ж и в ает " /> - Удали ть строку с
ОТСУГСТВУЮЩИМ В SQL- комаНАе полем
о <asp : BoundFie l d
DataField= " TitleOfCour t esy "
HeaderTe xt = " CTaTYc " /> - изменить имя поля на
имеющееся в SQ L- комаНАе

в окончательном ви де страница ОЬjесtDаtaSошсеUрdаtеSl.аsрх должна


стать такой

<%@ Page L апguagе="С#" %>

<script nmat= "server''>


11 Здес ь м ы не напи сал и ни стро чки кода!!!
</script>

<html xmlпs =''httр ://www.wЗ.0гgl 19 99/xhtml'' >


<head nmat="server">
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<title>Untitled Page</tide>
</head >
<body>
< fопn id="forml" runat="server''>
<div>
<asp:O bjectDataSource ID="O bjectDataSource 1" runat= "server"
ТуреNаше=''ЕШР1оуееDВ''
5 е 1ectM ethod = "GеtAllEшр 10 yees"
Uрdа tеМеthоd='Uрdа tеЕШР1оуее"
/>
<asp:GridView ID="GridViewl" runat="server"
AutoGenerateCo lumns=''False''
DataSource ID="O bjectDataSource 1 ''>
< Соlшnns>
<aspBoundField Dа tаFiеld="Ешрlоуее ID " HeaderText= "NQ п /п " />
<aspBoundField DataField="FirstName" НеаdегТехt=' Имя " />
<aspBoundField DataField="LastName" НеаdегТеxt="Фамилия " />
<asp BoundField DataField= ' ТIdeO fCourtesy" HeaderText= "C TaTYc "
< аsр:СошmaпdFiеld ButtonType="Button" НеаdегТеxt=' Изменить "
SlюwЕditВuttоп='Тruе" ShowHeader='True"
EditText= ' 'Редакция '' Cancerrext='OTMeHa " UрdаtеТеxt="Прим(
<HeaderStyle BackColor="Red " ForeColor= ''Yellow'' />
</аsр:Сошшапd Field>
</Соlumns>
</asp:GridView>
</div>
</form>
</body>
</html>

Листинг Окончательный страницы

ObjectDataSourceUpdatesl.aspx

Метод Upda t eEmployee () ав томати ч ески получает от объекта


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

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• ~ сполните страницу ObjectDataSourceUpdatesl.aspx и


у6едитесь, что о н а функционирует в соответствии с задуманным и
в одном из вариантов ге н е рирует такой НТМL- результат

NQ п /п Имя Фамилия С татус Изменить

1 Nancy Davolio Ms .
2 Andrew Fuller Dr.
3 Janet Leverling Ms .
4 Margaret Peacock Mrs .
5 Steven Buchanan Mr.
б Michae! Suyama Mr.
7 Robert King Mr.
8 Laura Callahan Ms .
9 Владимир С н етков До ц е н т 007

Применение перегруженного метода UpdateEmployeeO

Исходн ый вариант метода UpdateE mployee ( ) имеет четыре


аргум е нта , которые ав томатиче сЮ1 используются как па раметры канала

передачи данных от источника отображения к п олям табли ц ы. Но дл я


тех же целей можн о и с п ользовать любой пром ежугоч н ый объект,
описание (читай - масс, тип) которого будет у,цо в летворять следУЮЩИМ
условиям:

• Если и меется параметризованный конструктор, то и обязательно


долже н быть объявлен конструктор по ум олча нию , даже п устой
( э то стандартное требов ани е языков С+ + и С # )
• Класс должен имет ь общедоступные ( public ) и за пи сываемые (не
reado nly) свойст в а с и менам и , сов падающим и с полями таб л ицы ,
для передачи дан н ых в которую он будет испол ьзоваться

ТаЮ1М усло виям у,цовлетворяет всп омо гательный масс


Emp l oyeeDeta i l s , который м ы р азработали ран ее и который имеет
следующее описани е в фай ле Арр_СоdеlEmрЮуееDеtаils . сs

m
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

usiпg System;

public class EmployeeDetails


(
11 Общий конструктор
public ЕmрloуееDеtails(iпt employeeID, stгiпg firstName,
striпg IastN аmе, striпg titleOfCourtesy)
(
this.employeeID:= employeeID;
this.firstNаше = firstName;
this.lastName:= IastName;
this.titleOfCourtesy:= tideOfCourtesy;
)

11 Конструктор по умолчанию обязателен,


11 если создали общий конструктор
public EmployeeDetailsO
(
)

11 Добавляем свойства класса


private int employeeID;
public int EmployeeID
(
get { геtшп employeeID; }
set { employeeID = value; }
}
private string firstNаше;
public string FirstNаше
(
get { геtшп firstName; }
set { firstN аmе := value; }
}
private string IastName;
public string LastN аmе
(
get { геtшп IastName; }
set { lastName:= value; }
}
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

private string titleOfCourtesy;


public string TttleOfCourtesy
(
get { rеtшп titleOfCourtesy; }
set { titleOfCourtesy = value; }
}
}

Листинг Описание класса EmployeeDetails в файле

App_Code/EmployeeDetails.cs

Объект масса EmployeeDeta i ls вп ол не мож ет служить кан алом


передачи данных и з э леме нта Gr i dVi ew в таблицу при выполнении
метода обновления, если е го использо вать в качеств е аргумента этого
метода. Д ополни м
масс EmployeeDB еще одни м п е регружа ем ым
методом UpdateEmployee () .

• IJ$О ткрой те на редактирование фай л


App_CodefUpdateEmployeeDB.cs и до п ол ните его (скопируйте и
чyrь подпр авьте!) следующим кодо м пер е гружа емо го метода

UpdateEmp l oyee()

using System;
using System.Data;

using System.Data.SqlClient;

public partial class EmployeeDB


(
11 Исходный метод
public void UpdateEmployee(int employeeID, string firstName,
string lastName, string titleOfCourtesy)
(
SqlСо nnесtiоп соп = пеw SqlСоnnесtioп(сопnесtioпString);
SqlСоmmaпd сшd = new SqlCommand(''UpdateEmployee'', соп);
сmd.Соmma пdТур е = соmmaпdТуре.Stо rеdРrосеdше;
cmd.P arameters.Add(new SqlP arameter("@ EmployeeID", SqIDbType .Int,
cmd.Parameters["@EmployeeID"].Value := employeelD;
cmd.Parameters.Add(new SqIParameter("@FirstName", SqIDbType.NVar

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

cmd.Parameters["@FirstName"].Value = firstN аmе;


cmd.Parameters.Add(new SqIParameter("@LastName", SqIDbType.NVaf"1
cmd.Parameters["@ LastName"]. Value = IastName;
cmd.P arameters.Add(new SqlP arameter("@ TrtleOfCourtesy", Sq IDbType.:
cmd.P агаmetеrs["@1itleОfCошtеsу"].Vаluе = tit1eO fCourtesy;

try
(
со п.Ор е пО ;
cmd.ExecuteNonQuery();
}
catch
(
throw new АррlicаtiоnEхсерtloп("Ошибка данных.'');
}
finally
(
con.CloseO;
)
}

11 П ерегружаемый метод с объектом класса EmployeeDetails


public void UpdateEmployee(EmployeeDetails еmр)
(
SqlConnection соп = new SqlConnectlon(connectlonString);
SqlCommand спx:l = new SqlCommand(''UpdateEmployee'', соп);
cmd.CommandType = соmmaпdТуре.Stо геdРгосеdше;
cmd.P arameters.Add(new SqlP arameter("@ EmployeeID", SqIDbType .Int,
cmd.Parameters["@EmployeeID"].Value = emp.EmployeeID;
cmd.Parameters .Add(new SqIParameter("@FirstName", SqlDbType.NVar
cmd.Parameters["@FirstName"].Value = emp.FirstName;
cmd.Parameters .Add(new SqIParameter("@LastName", SqIDbType.NVaf"1
cmd.Parameters["@ LastName"]. Value = emp.LastName;
cmd.P arameters.Add(new SqlP arameter("@ TrtleOfCourtesy", Sq IDbType.:
cmd.P агаmetеrs["@ 1itleОfCошtеsу"].Vаluе = еmp. Trt1eO fCourtesy;

try
(
со п .Оре пО ;

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

сmd.ЕхеcutеNопQuеry();
}
catch
(
throw пеw АрросаtiопЕхсерtloп("Ошибка данных.");
}
finally
(
con.CloseO;
)
}
}

Листинг Перегружаемый метод UpdateEmployee() в файле

App_Code/UpdateEmployeeDB.cs

Те п ерь осталось создать стра н и ц у, реализующую этот новы й ка н ал


обмена да нн ым и .

• Г;:;=Сделайте копию страницы ОЬjесtDаtаSошсеUрdаtеsl . аsр х с


име н ем Obj ectDa taSourceUpda tes2 . asp x и назначьте ее

стартовой
• IJ$До п олни те оп и сание объекта ObjectDataSourcel всего­
лишь одним м-а-а-а-ле ньким атр и бугом
о DataObjec t TypeName= " Emp l oyeeDe t ails " - дл я

указан и я того , по о п исанию какого класса создавать

промежуго ч ный объект дл я передачи параметров в SQ L-


кома н ду обновле н ия данных в перегруженном методе
Upda t eEmployee()

Оконча тель н ый код страницы ОЬjесtDаtаSошсеUрdаtеs2.аsрх будет


следующим

<%@ Page L апguagе="С#" %>

<script nmat="server''>
11 Здесь мы не написали ни строчки кода!!!
</script>

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<html xmlns=''httр://www.wЗ.огgl1999/xhtml'' >


<head nmat="server">
<title>Untitled Page</tide>
<lhead >
<body>
< fопn id="forml" runat="server''>
<div>
<asp:O bjectDataSource ID="O bjectDataSource 1" runat= "server"
ТуреNаше=''ЕшрюуееDВ''
Data О Ь j ectTyp е N аше= ''Ешр юуее Details "
5 е }ectM ethod = "GеtAllEшр юуееs"
UрdаtеМеthоd='UрdаtеЕшрюуее" />
<asp:GridView ID="GridViewl" runat="server"
AutoGenerateCo lumns=''False''
DataSourceID="ObjectDataSource 1 ''>
< Соlшnns>
<aspBoundField DаtаFiеld="ЕшрlоуееID" HeaderText=''NQ л /л" />
<aspBoundField DataField="FirstName" НеаdегТехt='Имя" />
<aspBoundField DataField="LastName" НеаdегТеxt="Фамилия" />
<asp BoundField DataField= 'ТIdeO fCourtesy" HeaderText="CTaTYc"
< аsр:СошmaпdFiеld ВuttопТуре=''Вuttоп'' НеаdегТеxt='Изменить"
SlюwЕditВuttоп='Тruе" ShowHeader='True"
EditText= "Редакция" Ca ncefГext='OTMe Ha " UрdаtеТеxt=''Прим(
<HeaderStyle BackColor="Red" ForeColor=''Yellow'' />
</аsр:СошmaпdField >
</Соlumns>
</asp:GridView>
</div>
</form>
<!body>
<lhtml>

Листинг Охончательный .од страницы

ObjectDataSourceUpdates2.aspx

• ~ с лолните страницу О Ь j ectDa ta 5 ource U pdates2 .aspx и

у6ед ит ес ь , что ее функциональность в точности п овторяет


функциональн ость стран иц ы ObjectDataSourceUpdatesl.aspx
• ~ тоб ы р ассе ять сомнения в том , что раб о та ет и менно новый

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

метод

риыic void UpdateEmployee(EmployeeDetails е mр){ ... }

заключите (временно!) в файле UpdateEmployeeDB .cs исходный


метод в комментарные скобки 1* ... * I

/*
11 Исходн ый метод
public void UpdateEmployee(int employee ID, string firstName,
string IastName , string t.itleO fCourtesy)
{

}
*/

• ~HOBb за пусти те страницу ОЬjесtDаtаSошсеUрdаtе s2 . аsрх.


Функциональнос ть п ол н остью сохранил ась , зн ачит работает вс е­
таки наш новый метод
• ~ аскомментируйте исходный метод UpdateEmp l oyee ()

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

нестандартных имен аргументов

к черту п ерегр ужаемые методы вм есте с их ста н дар тными им е на ми


аргуме нтов , сов п адающими с именами п олей табл ицы и порядком
следования! Прим ен им пр оизвол ьны е им ен а метода обновления и его
аргуме нтов (но количество аргументов остав и м пр ежним ,
соответствующим количеству извлечен ны х в Gr i dVi ew полей) .

Такая свобода т ре бует напи са ния дополнительного кода для подмены (в


п ослед ний моме нт) в обработчике события
ObjectDataSource . Updating з н ачений в т ерминах Gr id View.
в значения в терм ина х ис то чника Obj ectDa taSource , п е редаю щего

эти з н ачения дальше в та бл иц у Employees для об нов ле ния ко н еч ны х


да нны х . Р а н ее мы подобную задачу решали на странице
OtherNameParamUpdates.aspx приме ни тель но к элементу
SqlDa taSource .
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• IJ$Добавьте в класс EmployeeDB файла


App_CodefUpdateEmployeeDB.cs юшию исходного метода с
четыр ь мя парамет р ами и подкорректируйте его так (теперь в
файле будyr три метода обновлен ия)

using System;
using System.Data;

using System.Data.SqlClient;

риыic рапial class EmployeeDB


(
// Исходный метод
риыic void UpdateEmployee(int employeelD, string firstName,
string IastName, string tit1eOfCourtesy)
{

// Перегружаемый метод с объектом масса EmployeeDetails


риыic void UpdateEmployee(EmployeeDetails еmр)
{

// Новый метод обновления данных


// Изменены: имя метода, и мена аргументов и порядок их следо
риыic void UpdateEmployeeStrict(string tideOfCourtesyStrict, string la ~
string firstNameS trict, int employee IDStrict)
(
Sq}Connection соп:= new Sq IConnectio n(connectionString);
Sq}Command сшd := new Sq ICommand('UpdateEmployee", соп);
cmd.CommandType := CommarкlType.StoredP ro cedure;
cmd.Parameters.Add(new SqlParameter("@EmployeeID", SqlDbTy
cmd.Parameters["@EmployeelD"].Value := employee IDStrict;
cmd.Parameters.Add( new Sq lParameter("@FirstName", SqIDbTyp€
cmd.Parameters["@FirstName"]. Value == firstNameStrict;
cmd.Parameters.Add( new SqlParameter("@ LastName", SqIDbType
cmd.Parameters["@LastName"].Value = IastNашеStгiсt;

'"
в.м. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

cmd. Parameters.Add( new Sq lParameter("@TItleOfCourtesy", SqIDl


cmd. Parameters["@ TItleOfCourtesy"].Value = tit1eO fCошtеsyS trk:t;

try
{
соп.ОрепО;
cmd. ExecuteN onQueryO;
}
catch
(
throw new А ррliсаtionEхсер tiоп("О ши бка данны х. '');
}
finа Пу
{
con.CloseO;
}
}
}

Листинг НОВЫЙ метод обновления в JCлассе EmployeeDB


файла App_Code/UpdateEmployeeDB.cs

• ~Сделайте копию страницы ОЬjесtDаtаSошсеUрdаtеsl . аsр х с


име н ем ОЬjесtDаtаSоurсеUрdаtеsЗ . аsр х и назначьте ее

стартовой

Сейчас мы во с пользуемся мощью оболочки VlSua! Studio 2005 и одни м


махом сгенерируем н ужный нам код разметочной части страницы

• ~Безжалостно (!!!) удалите в режиме Design настрое нны й (как­


то там) объект Objec t DataSourcel и на его место из вюыдки
Data панели Toolbox скопируй те новый объект типа
ObjectDa taSource с прежним именем
• ~елкните мышью на тр еугол ьнике в п равом верхнем углу
объекта ObjectDataSou r cel , чтобы вызвать для него
внугр е ннюю пан ель настройки

ObjectDataSource ТBsks
COnflgLfe Оаtз 5ource,
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• ~елкните на единственной , пока, ссылке Соп figure Da ta


Source (ско нфигур ировать источник данных), чтобы запустить
мастер генерации настроек элеме нта Obj ectDa t aSou r ce 1
• ~ a первой странице мастера из раскрывающегося списка
выберите используемый класс EmployeeDB и перейдите к
следующей странице мастера конфигурации
ОП!iqUrС!JiJЫ!Юt.r<С UblCCtl);){;)!lour<:Cl

Choose а Bus!ness Object


===-__ .111<1

54с! а b<..sness cbject 1tJa: ею ье LEed to rе1Т.еve ос ~a:e шtэ (for exaгrr,::!e, ю object defГ'ed h the Eil cf
I\pp_Code directcry (ос tfis ёррkэton ).

с ,
11

• r;.:Fнa новой странице вначале установите вюыДку SELECT. через


которую установите метод GetAIIE mployees () для

заполнения элемента GridViewl


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET
ОП!iqUrС!JiJЫ!Юt.r<С UblCCtl);){;)!lour<:Cl
===-~_.111<I
Deflne DiltiI Methods

сакт ILf'DAТE I JJ<Еп l [ВНЕ I

O1oc€e а rne1hxJ 01 1he ыsПe о , oo;ect 1t1эt г OOЛiS dэt3 to asoociate ",1t11he SELECT opera:i:ll ТОО mOOюd
с'" rc1JJn а DUOЖ, D "mцюjо г, of s:ronj,-typoJ coloctIOll,

• ~ста новите вкладку UPDAТE, через которую уста новите наш


новый метод обновления данных
ОП!iqurС!JiJЫ!Юt.r<С UblcctlJ;){;)!lour<:cl

Deflne DiltiI Methods


=====___ .1 1<1
Upda t eEmplo ye eS t r ict ( )

O1oc€e а rne1hxJ 01 1he ыsПe» oo;ect (о =о",,,:е " i11 the ISQCJ.ТE ope<a:i::tl ТПе method mOtJd ,," се р! а
>",,,,,,,,,ti,, Iа- eoch P'op::rty 01 1tю сЬ и ob1'ct, Of" snjз p,,,-,rnNor I'kri1rs the dxa OOjOCt (о цх1зm,

I 3
-1
~rrpby "" q гt::J 2 . mpb ~D )
&.1Ещ:Jo ~ qп tJ 2 .тф", . D), rm.n, Етф", .,с.,~
n' <Г1Е nфy .. (Е nфy .. D<иI, ' rrv}, г-ш-n, IгtЗ 2
Цх1ЛЕгсрЬУ"" (ЕГСРЬ~ .тр}
:nE гс vоо а гtЗ 2 ет eD s:r ftotName , sttтю Iэo tlJ:>:ne stг ~j :IOK OIJ tes v

Посл е щелчка на кнопке Finish, поско льку на ст р анице уже имеется


элемен т Gr i dViewl , не со гл асова нный с но в ы м и настройками

m
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

источника д анных , мастер выдаст пред.УПрежде ние с предложе ни ем

автоматичесЮ1 приве сти ИХ В соответстви е (мы занимаемся


декларативной стыковкой элементов под неусыпным при смотром
среды пр оектирования - оболо чЮ1 !)

Мicrosoft Visual studio

~ Retresh FieIds rn Keys fcr 'GrtlViewl'

VJoUd you lI<e to regenerate the GrdView с olJ тп /ieI±,.-,j dh key' lEh;J the , elPcted data , ос.- се ,chema7
VliftJ;-.;j : ths WI delete aI e>dstn;) roli mn /ieI±.

• IJ$OTBeTbTe отрицательно - на м н е нужны новые замены в


настройках GridViewl

Вот какой код сгенерировал мастер настроек объекта


Obj ее tDa taSouree 1 (Ах, какой умны й Большой Билл! Даже
yrочнения типов пар аметров сгенерировал сам)

<asp:O bje ctD a taSollГce ID="O bje c tDa ta S ollГce 1" runat= "server"
TypeName=''EmployeeDB ''
SelectMethod="CountEmployees"
Upda te М ethod = 'U pda te Еmр Ioуее S trk:t">
<Update Parameters>
<asp:Parameter Name="titleO fC ourtesyStrict" Typ e="S tring" />
<asp:Parameter Name="lastN ameStrict" Type="String" />
<asp:Parameter Name="firs tNameStrict" Type=''S tring'' />
<asp:Parameter Name="employeeIDStrict" Туре=' 1пtЗ2" />
<lUpdateParameters>
</asp:O bjectDataS OllГc e >

Листинг Настройки объекта ObjectDataSourcel на странице


ОЬjесtDаtаSоurсеUрdаtеsЗ.аsрх

Теперь осталось напи сать код подмены з н ач ении парам етров из


Gri dV i ew l в принимающих пар аметр ах источника

Obj ее tDa taSouree 1 п еред обновлением коне чны х данны х

• Г;;:;=Выделите в режиме Design объект Ob j ee t Da t aSou r eel и


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

через пан ель Properties двойным щелчком на п оле собы тия


Upda t i n g создай те для н е го за готовку об р аботч ика
• u;.;rЗаполните об р аботч и к так, чтобы окончательный код
стр а н ицы стал следую щи м

<%@ Page Lапguagе= "С#" %>

<script nшat="sеrvеr''>

protected void ObjectDataSource1_Updatmg(object sепdеr, ОЬjесtDаtаSош


(
11 Перегрузить данные на дрyrnх лошадей для
11 продолжения поездки к базе да нных
е .lпрutР arameters[''firstN аmе S trict"] = е .lnputP arameters["F irstN аme "];
е.lпрutРаrаmеtеrs[''lastN ameS trict'1 = e.lnputParameters['1.astN аmе"];
е .lпрutР arameters[' 'titleO fC о urtesyS trk:t"] = е .l прutР ar ameters['ТitleO fC 01
е .lпр utP arameters["emp loyee IDS trict"] = е .lпр utP arameters[''Emp 10 уее IО "

11 Удалить из коллекции параметров ненужное


е .lпр utP arameters. Rепюvе(''F irstN ате ');
е.lпрutРаrаmеtеrs.Rепюvе('1.аstN аmе');
е .lпр utP arameters. Rепюvе('ТltleО fC ourtesy');
е .lпрutР arameters. Rепюvе(''Еmp lоуее lD ');
}
</script>

<html xmlns=''httр://www.wЗ.оrgl1999/xhtml'' >


<head nmat="server">
< title >Uпtitled Page</title>
<lhead >
<body>
< fопn ю="fоrm1" ruпаt="sеrvеr' '>
<div>
<asp:O bjectDataSource IО= "О bjectDataSource 1" runat= "server"
ТуреNаше=''ЕmрюуееDВ''
S е 1ectM ethod = "GetAllEmp)o yees"
UpdateMethod='UpdateEmp1oyeeStrk:t"
О nU pd atmg=' О Ь j ectDa ta S о urce 1_ Updating''>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<Update Parameters>
<asp:Parameter Name=''titleO fCourtesyS trict'' Type="S tring" />
<asp:Parameter Name="lastN ameStrk:t" Type="String" />
<asp:Parameter Name="firstNameS trict" Type="String" />
<asp:Parameter Name="emp loyeeIDStrict" Туре=' 1пtЗ2" />
<IUpdateParameters>

</asp:O ЬjectDataS ошсе >

<asp:GridView ID="GridView1" runat="server"


Auto GenerateCo lumns=''False''
DataSourceID="ObjectDataSource 1''>

< Соluпms>
<aspBoundField DataField="EmployeeID" HeaderText=''NQ л /л" />
<aspBoundField DataField="FirstName" Неаd егТехt=' И мя" />
<aspBoundField DataField="LastName" Н е аd е гТеxt="Фамил ия " />
<asp BoundField DataField= 'ТItleO fCourtesy" HeaderText="C TaTYc"
<asp :CommandField ButtonType='1.ink" Cancerrext=''OTMeHa ''
ЕditТеxt="Редакци я " Н еаdе гТеxt="И зме нить "
SlюwЕd itВuttоп='Тruе"
ShowHeader='True" U рdаtеТеxt=' 'ПРИМf
<HeaderStyle BackColor="Red" ForeColor=''Yellow'' />
</asp:CommandField >
</Соluпms>

</asp:GridView>
</div>
</form>
<!body>
<lhtml>

Листинг Охончательный .од страницы

ОЬjесtDаtаSоurсеUрdаtеsЗ.аsрх

Обратите внимание на выделенные места кода стра ницы , особенно на


настр ойки ynравляющего столбца элемен та Gri dV i e w1 · в н ем мы для
разнообразия сменили интерфейс п ользователя с кнопок на
гuперссылкu.
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• ~Запустите на выполнение ОЬjесtDаtаSоuгсеUрdаtеsЗ.аsрх и


получите работающую страницу редактирования да нны х,
стерилизованный (ссылки отключены) вариант НТМL-вывода
которой приведен ниже

NQ п /п Имя Фамилия Статус Изменить

1 Nancy Davolio Ms . Редакция

2 Andrew FuIler Dr. Редакция

3 Janet Leverling Ms . Редакция

4 Margaret Peacock Mгs . Редакция

5 Steven Buchanan Мг. Редакция

б Michae! Suyama Мг. Редакция

7 Robert King Мг. Редакция

8 Lаша Cal1ahan Ms . Редакция

9 Владимир С н етков До ц е н т 007 Редакция

Использование ObjectDataSource для вставки и

удаления записей

Ан алоП1Ч Н ЫМ образом можно задействовать и другие оставшиеся


методы нашего пользовательского класса EmployeeD B, имеющие

п араметры:

• publ i c i nt Inser t Emp l oyee( EmployeeDeta i ls


еmр) ( . .)
• publ i c vo i d DeleteEmployee( int emp l oyee I D)
( ...)

Ра ссмотрим операц ию вставки с применением пользовательского


класса Employee DB. Эту о п ерацию мы вправе добав ить н а ст р аницу в
допол н ение к уже реализованной операц ии об н овления . Особенность
реализаци и метода вставки состоит в том, что он возвращает значение ,

указывающее содержимое поля EmployeeID. Это поле в таблице


является ключевым и имеет свойство Autolncrement
(автомати ческое увеличение). Его значение , возвраще нн ое методом ,
по
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

можно проигнорировать , но можно и перехватывать и использовать

для каких-ниБУдЬ целей, например извещения пользователя.

Технологию вставки новой и у,цаления существующей записи в таблице


базы данных лучше рассмотреть на примере.

• ~Создайте копию страницы ОЬjесtDаtаSошсеUрdаtеs2.аsрх с


именем Object DataSou r ceFull . asp x и назначьте ее

стартовой
• Г;;:;npoBepЬTe работоспособность начального варианта страницы
О Ь jectDataSo шсе F ullasp х

Этот вариант страницы хорош тем, что в нем параметры между


элементами согласованы стандартно по именам полей и нет
дополнитеЛЫЮ20 кода, отвлекающего от решения поставленной задачи.
В нем уже существует определенная нами ранее функциональность
редактирования данных.

• ~Добавьте после элемента Gr i dV i ewl компонент

L i n k Button и создайте ДЛЯ него обработчик


L i n k Buttonl Cl i ck()
• ~ режиме Design двойным щелчком на свободном месте Web-
формы создайте обработчик Page Load () страницы , в котором
мы бу,цем формировать сообщение о номере добавленной в
таблицу записи
• ~ оместите после элемента L i n k Buttonl компонент Label
с именем lbllnfo , в котором мы БУдем размещать сообщения
для пользователя о добавленной или Удаленной записи таблицы
Employees
• r;:;'в режиме Design вызовите встроенную панель источника
ObjectDa t aSou r cel и щелчком на ссылке Con f i g u re
Da t a So ur ce вызовите мастер конфигурации источника
данных. Проверьте правильность подключения методов во
вкладках SELECT и UPDAТE, затем ПОДЮlючите метод удаления во
ВЮlадке DELEТE

m
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET
ОП!iqUrС!JiJЫ!Юt.r<С UblCCtl);){;)!lour<:Cl
===-~_.11,"
Deflne DiltiI Methods

'RECТ ILf'DAТE IJJ'ERT [НЕТЕ I


O1oc€e а rne1hxJ 01 1he ыsПe о , oo;ect to = о",,,:е " i11 the DELETE с:реГ<ЬХ1 . тг... me1hxJ Sh:Ud асс"!'! а
"""roc!ы Iа- Goch I=flrray '-еу Iа- ttю dж:J ob]Oct а- а sn;;Ю "",.,-00< I'hoh t3 1he d "и cb:v! to ddoto .

о-.::.с..е а me1h:d:

l Ddct:EmРОУОО (1ltЗ2 empoyoeD)

• ~ осле щелчка на кноп ке Finish откажите сь от пр едложения


скорректировать объект Gr idViewl
Mor",<;oN VI<"AI St"lI;o

~ Rеfiбtl FIeIds ifi1 кеУ5 h 'Э'К1УieW j '


====--
WOJ:j уоо lI<e to r ~ate the GI'dII" .... roUonliel.1з m dY-" keys ш n;J the selected dа:з ,о.х се schema?
WifTtlQ : Itis wf deete aII ex~tn;J roUffi 1'teIds.

• u;.;rвызовите через свойство


ObjectDa t aSou r ce l . Dele t e Pa ra me te rs окно

визуального редактирования параметров команды удале ни я и


настройте е го так
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET
",aтc t" r <.Х> 1 С< I ЮП Lditor
==~ 211<1

[rn = tE "1'tyS tr r-ч т ~ Тг ,-"


Dcli>J tV~

Jnt'J2

,
Thoo JD 01 ~ сопW to (!<"I th" p-c,=rty,~ Irc.-n

• ~ыделите элемент ObjectDataSource l и через панель


Properties создайте обработчик
Ob J ectDa t aSou r cel Deletlng () АЛЯ события
Delet i ng , в котором мы БУдем п е рехватывать номер Удал яемой
из таблицы записи

в результате таких действий по конфигурированию элемента


ObjectDataSource l оболочка добавит в его дескриптор нужный
КОД (который, кстати , можно ввести и вручную без всяких визуальных
помощников)

<asp:O bjectDataSource ID="O bjectDataSource 1" runat= "server"


TypeName=''EmployeeDB'' Sеleс tМ е thоd="GеtAllEmpюуее s"
UрdаtеМеthоd='UрdаtеЕmрюуее"
DеletеМеtlюd="DеlеtеЕmрlоуее"
О пD е letlng= "О Ь jectDataS оигсе 1_De leting''>
<Update Parameters>
<asp:Parameter Name="emp loyeeID" Туре="IпtЗ 2" />
<asp:Parameter Name="firstName" Type="String" />
<asp:Parameter Name="lastN аmе" Type="String" />
<asp:Parameter Name="titleOfCourtesy" Type="S tring" />
<lUpdateParameters>
< DеletеРагашеtеrs >
<asp :ControlParameter Contro lID= "GridView1"
Name="employeeID " Туре="intЗ2" />
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

<lDe lete Parameters>


<!аsр :О Ьj ес tDаtаSо шсе >

Листинг Код , до б авленный в ObjectDataSourcel через


визуальные средства редактирования

Те п е р ь ско рр ект и руем управляющий столбец объекта Gr idV i ew l.


чтобы добавить в е го п ользовательский и нт ерфейс кнопку для
возможности удален ия запис и. Кнопку добав и м в форме гuперссыл кu
Link .

• ~ызовите встрое нный в и зуальный р едактор для объекта


GridViewl . Для этого щелкните на кнопке (пиктограмма
треугольника) в правом верхнем углу визуального пр едставления
объекта , а затем на ссылке Ed i t Со] uтns

GridView Tasks
Auto Format ...
Choose Data 5ource: IObjectDataSourcel : I
Conf>;Jcre Data Sol.fce" ,
Refresh Schema
Edit CoIu rms. ,

Add New 1Editthe GridView's columnsl


Г ЕпаЫе РiJ>;)IП(]

r;:r ЕпаЫе Ecitng

r;:r Епаыe DeleЬП>;J

Г ЕпаЫе Selecboo

Edit Те rтplates

• ~ы делите управляющий столбец " Изме н и ть" и в поле


CommandField properties установите з нач ения следующих

свойств
о ButtonType=L i n k
о Dеlе t еТе хt = " У д а л ить "

о Show DeleteButton= " Tr ue "


по
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Flelds
=====---'------:.1J~
Avaictie FoeIds : ComlТl<ГКf'ieId рrч::-егres:

.- ·т le!; FieI:1s),
13т Вc:<л:fieI::J
>""
~1.f..!.J

Acc~ss~"'*'r Т ""х!
ВuttmType
mТ1tiЮfCOJt~sу Сю::elIrnagel1l
mEmployeelD Сю::еГТехt Отмена
mFr slNJm e CaвeesV 3idati:n T, ~
~ CheckВoxFieI::J @ Cm1rolStylo
Ddetcl7'7&1
~I!I~4~!!I'IIIII!iI!i• • y ДafJ.1ТЬ
SeЮсtсd тcldз :
Ec1tIrmgeL\1
Ec1tТext Редакция
III mn!n S FooterSt)e
Ш см" FootorToxt
mФам1J11Я
rn Статус
. ~1Тb
t, ]--1о:,,,,,*,, I ~ 1

DeleteText
The text to ье dSpIзу&1 011 the delete butlal

Refresb mmэ

Вспомним, что в реляционных базах данных долж на п одцерживаться


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

ADO.NET отслеживает это положение автоматически, но е й н ужно


указать п ерв и чный ключ. Для этого служит параметр DataKeyNa mes
в элементе управления Gr i dViewl (поскольку мы планируем Удалять
запись через него) , в котором указывается строка с одни м именем
ключевого поля или строка со списком ключевых полей, разделенных
запятыми. В нашем случае первичным К//ЮЧОМ в таблице Employees
является поле Emp l oyee I D.

• ~ ереведи те редактор страницы в режи м Source и добав ьт е в


заголовок элеме н та Gr i dViewl параметр, назначающий
ключевое поле редактируемой таблицы
DataKeyNames= " EmployeeID "
о

• ~ыделите текстовую метку 1 Ь 1 1 n f о и сбросьте свойство


сохран ени я состояния EnableV i ewS t ate= " False ", чтобы
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

пр и каждом н овом зап р осе ее з н ач е ни е очищалось

На этом эта п декл аративной на стройки ст р а ницы за конч е н . Тепе р ь


нужно запол ни ть создан ные нами ранее об р аботч ики соответствующим
кодом .

• ~3а пол ните обработч ики событий так, чтобы окон ч ательный
код стр а ницы ObjectDataSourceFuJl aspx стал следующим

<%@ Page Language="C#" %>

<script runat= "server''>

protected void LinkButto nCClick(object sender, EventArgs е)


(
ЕmpюуееDВ db :::: new EmployeeDBO;
// Вставляем пустую запись и запоминаем ее номер
Session[''recordNumber''] ::::
db.InsertEmployee(new EmployeeDetails(O, '~', '~', "'));
// Обновляем страницу без полного ци кла,
Server. Transfer(Req uest.F ile Р а th);
}

protected void Page_Load(object sепdег, Еvе пtAгgs е)


{
if (Session[''recordNumber'1 != null)
(
IblIпfо.Техt = "Д обавлена за пись "
+ Session[''recordNumb er''] ToStringO;
5 essio п . Remove( ''record N uшЬег');
}
}

protected void ObjectDataSourcel_De)eting(object sender,


ObjectDataSourceMethodEventArgs е)
{
IblIпfо.Техt = "Удалена зап ись "
+ e. lnputParameters["employeeID'1.ToS tringO;
}
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</script>

<html xmIns='huр://www.wЗ.or&,1999/xhtml" >


<head runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id="form1" nmat="server''>
<div>
<аs р :ОЬjесtDаtа Sо шсе ID="ОЬjесtDаtа Sо шсе 1 " runat="server"
TypeN аmе= ''Employee DB'' SelectMethod= "GetAllEmployees"
UpdateMethod=''UpdateEmployee''
De lete М ethod = ''De lete Етр 10 уее"
О nDe leting=' 'О Ь j ectDa ta S ource 1_De leting">
<UpdateP arameters>
<asp:Parameter Name="employeeID " Туре="lпtЗ2" />
<asp:Parameter Name="firstName" Type="S tring" />
<asp:Parameter Name=''1astName'' Type="String" />
<asp:Parameter Name=''tideOfCourtesy'' Type="String" />
<lUpdateParameters>
< DeleteParameters>
<asp:Contro!Parameter ControllD="GridView1"
N ame="employeeID" Туре="intЗ2" />
<lDeleteParameters>
< /аsр:ОЬjесtDаtаSошсе >
<asp:GridView ID="GridView1" runat="server"
АutоGе пега tеСо lшnns ="Fаlsе" D аtа Sошсе ID="ОЬjесtDаtа Sо ш(
DataKeyN аmеs=''Еmрюуее ID ">
<Columns >
< asp:BourкlFiekl DаtаFiе ld =''Еmpюуее ID '' HeaderText="N:! n l
< asp:BourкlFiekl DataField =''FirstName'' Н е аd е гТеxt=' 'Имя '' /:
< asp:BourкlFiekl DataField =''LastName'' Н еаdегТехt="Фа мил
< asp:BourкlFiekl DataFie ld ='ТideO fCourtesy" HeaderText="C
< аsр:СопunaпdFiеkl
СапсеfТехt=''Отмеиа '' ЕditТехt=''Редакция''HeaderText="
ShowEditВutton='True" ShowHeader='True" UpdateText="
DеletеТеxt="Удалить" ShowDeleteButton= 'Тгие">
<HeaderStyle ВасkСоlог=''Rеd'' ForeColor=''Yellow'' />
</asp:CommandFiekl >
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</Co lumns>
</asp:GridView>
<asp:LinkButton ID=''LinkButtonl '' nmat= "selVer" ОпСliсk= ' 'LinkВt
Вставка
</asp:LinkButton>
< Ьг />
<asp:Label ID="lb Unfo " runat="selVer" ЕпаЫеViеwStа tе="Fаlsе" />
</div>
</fonn>
</body>
<lhtml>

Листинг Окончательный код страницы


ObjectDataSourceFull.aspx
• г;.:.=и сполните страницу ОЬjесtDаtаSошсеFulLаsрх и н асладитесь
тем, что она имеет функциональность пол ноц е нн ого редактора
таб лиц, тем более - Удале нных (Ах да Большой Билл, ах да мала-ц­
ц -а!). Один из экранов, ге н ерируемых на стороне п ользователя ,
БУдет таким

NQ п /п Имя Фамилия Статус Изменить

1 Nапсу Davolio Ms . Редакцияг.удалить

2 Andrew Fuller Dr. Р едакц и яг.удал ить

3 Janet Leverling Ms . Р едакц ияг.удалить

4 Margaret Peacock Mгs . Редакци яг.удал ить

5 Steven ВисЬаnaп Мг. Р едакц и яг.удал ить

б Michael Suyama Мг. Р едакц и яг.удал ить

7 Robert King Мг. Редакци яг.удал ить

8 Lаша Cal1ahan Ms . Р едакц и яг.удал ить

9 Владимир С н етков Доце н т 007 Редакци яг.удал ить

10 Редакци яг.удал ить

Вставка

Добавлена за пись 10

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Программное изменение запроса пользователя в

SqlDataSource

Ранее мы рассматривали пример


SqlDataSourceParameters . asp x выборки данных из таблицы в
зависимо сти от выбранного пользователем города. Первый источник
SqlDa taSource заполнял городами список, жестко привязанный с
помощью списювого свойства DataSourceID. Второй источник
SqlDa taSource отрабатывал один и тот же SQL ·запро с с разными
значениями параметра , полученными из списка в зависимости от

выбора пользователя.

в следующем примере попробуем расширить список добавлени е м в


него еще одного пункта и при выборе пользователем этого
добавленного эл емента списка изменить SQL·запрос. При вязку списка
К источнику данных SqlDataSource , а также изменение SQL ·
запроса выполним про грамм но.

• ~Сделайте копию страницы SqlDаtаSошсеРагаmеtегs.аsрх с


именем Sq l DataSourceChange . asp x и назначьте ее
стартовой
• Г;;:;=Выделите элемент Dr opDownList ID= " lstC itie s " и
очистите его свойство DataSource I D, тем самым мы отвяжем
список от источника данных
• IJ$Двойным щелчком на свободном месте WеЬ·формы создайте
обработчик загрузки страницы Page Load ()
• г;;.:;='Для второго источника SqlDataSource
ID= " sou rceE mployees " через панель Prop erties создайте
обработчик события Se l ecting
• г;.:;=Заполните обработчики юдом так, чтобы оюнчательное
описание страницы было следующим

<%@ Page L апguagе="С#" %>

<script nmat="server''>

protected void Page_Load(object sender, Еve пtAгgs е)


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

(
if (!this.lsPostВack)// Первый запрос
(
// Инициировать запрос и привязать результаты
lstСitiеs.DаtаSошсе:= sошсеЕmрlоуееСitiеs.Sеleсt(
DataSourceSelectArguments.Empty);
lstC ities.DataBindO;

// Добавить новый элемент в список


lstСitiеS.ltешs.Аdd(''Все города'');
lstCities.Selectedlndex:= IstСitiеs.ltеms.СОШ1t - 1;
}
}

vою sошсеЕmрюуееs_Sеlесting(оЬjесt sender,


SqIDаtаSошсеSеleсtingEvепtAгgs е)
(
if «string)e.Command.Parameters["@City'1.Value =:= ''Все города'')
(
// Очистить коллекцию параметров
e.Command.Parameters.ClearO;

// Изменить команду
e.Command.CommandText:= ''SELECT EmployeelD, FirstName, Lastf'
+ 'Тit1e, City FRQM Employees WHERE City!:="";
)
}
</script>

<html xmlns:=''httр://www.wЗ.огgl1999/xhtml'' >


<head nmat:="server">
<title>Untitled Page</tide>
</head >
<body>
< fопn id:="forml" runat:="server''>
<div>
< h2 > Выберите город < lh2>
<asp :SqIDаtаSошсе ID:="sошсеЕ mplоуееС ities" nmat:="server"
ConnectionString:="<%$ connectionStrings:Northwind % >"

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Р roviderN аmе= "S ystem. Data. S q lC liепt"


Sеleс tС оmmaпd ="SЕL ЕСТ
DI STINCT City FRQ M Ешрloуееs" />
< аsр:DгорDоwпList ID=''1stCities'' ruпаt="sеrvе г"
AutoP ostBack='True"
DataTextField="City" />

< h2 > Пр ож ив ающие сотру,цники < lh2>


< аsр:SqIDаtаSошсе ID="sошсеЕ mplоуееs" nmat="server"
Connectio nString="<%$ connectionStrings:Northwind % >"
Р roviderN аmе= "S ystem. Data. S q lC liепt"
SelectCommand="SELECT EmployeeID, FirstName, LastName,
TJtle, City FROM Employees WHERE C ity=@City"
Q nS е lecting= "sошсе Еmр loyees _ S е lecting">
<Se)ectP arameters>
<asp :ControlParameter N аmе= "City" Co ntrollD="lstCities"
PropertyName="SelectedValue" />
</SelectParameters >
</asp:Sq lDataSource>
<asp:GridView ID="GridViewl" runat="server"
DаtаSоuгсеID="sошсеЕmplоуееs" />
</div>
</foгш>
</body>
</html>

Листинг Охончательный .од страницы

SqlDataSourceChange.aspx

Приведенный пример демо нстрирует плохую практику

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


п одход к пр ивязке да нных. На больших страницах это может привести к
пуганице и возникновению ошибок, а также п лохой читабельности
кода . К тому же , ПОДставляемую команду желательно бы с пр ятать в
хранимой процедУРе.

Статический результат выполнения стра ницы SqIDataSourceChange.aspx


следующий

Выб ерите город


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

I Kp;!!ICHO~PCK ::::::J

Проживающие сотру,цниЮ1

EmployeeID FirstName LastName Tir/e City


9 Владимир Снетков Доцент ВАК Красноярск

т
(

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Интерфейсные элементы ADO.NET


Табличный элемент управле н ия да нн ыми GridVlt'w. Явное определение
столбцов в GridView. Форматирова ни е в GridView. Стили в GridView.

Программировать устал - перспективу потерял

Файлы к лекции Вы можете скачать здесь скачать:

httр :l/оkl . iпtШ . ruld ераrtmeпtJiпtеmеtJр rasp netJ 1 4/14.пр .

к развитым интерфейсным элементам пользователя, служащих для


управления даННblЛ1U и их представлением, относятся Gr i dVi e w,
Deta i lsVi ew и FormVi ew. Мы уже пр и менял и ранее н екоторые из
н их, но в этом разделе п оз н акомимся с ним и более подробно.

Таблич ный элемент управления данными GridView

Этот элемент ВЮJючает в себя широкий диа п азон встроенн ых средств ,


таких как выделение, разбие н ие на страницы, редакти рование ,
сортировка, фильтра ци я. Он может быть расширен п римен е ни ем
шаблонов . Гибкие настройки на этапе праектuравания позволяют
добиться решения мно гих задач без необходимости н апи са ни я кода в
обработчиках событи й. Gri dV i ew - это новый элемен т для ASP.NET
2.0, который заме ни л собой элемен т Da ta Gr i d из п редыдущей
версии.

Для обратной совместимости Da t aGr i d оставле н в ASP.NET 2.0,


хотя и убран по умолчанию из панели Too lbox. Сделать доступным
элемен т Da taGr i d можно, если выполни ть для любой ВЮIaДКИ панели
Toolbox командУ контекстного ме н ю Choose Items (добавить элементы)
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Choose Т oolbox Items ? Х

Ma n1:erJ.3ГtCe Tasks SSIS Data F ~w It:ems SSIS COn1]"ol F~w It:ems


,t.ET Frarrnwa-k Co rrpr!e n!:3 I С а.1 CompcnerTts

Мk:roso!t,AnaysrsServ k:es.A. , Mk:roso!t, ,!.л3"уsisServi, , Gtbal дss"

Мk:rosoft,AnaysrsServ k:es
Мk:roso!t,AnaysrsServ k:es
Mk:rosoft, ,!.л3"уsisServi, ,
Mk:rosoft, ,!.л3"уЪServi, ,
Gtb al дss"
Gtb al дss"
J
System, Wh oows,Fa-ms System ,Wh::bws,F a-" c:lprcga"
Sy::tem, Wh oows,FCfms System ,Wh::!ow::,FCf" c:lprcga"

, , System ,Wh::!ow::,FCf"

E.iter: fjЗta

г~taG<;~,~"", Imomnt L~ (Imomnt Сооо"у) ~owse."

Vегш п: 2,0,0,0

Cancel

Явное определение столбцов в GridView

Свойство AutoGenerateColu mns элемента Gr i dVi ew


установле но по умолчанию в состоян и е Тт ие . Чтобы его ОТЮIючить ,
н ужно явно указать в де ЮIаративны х нас тройках Gri dVi ew ат р ибyr
AutoGenerateColu mns= " False " . При ВЮIюченном свойстве
AutoGenerateColu mns элеме нт Gri dVi ew автоматически

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


в котором и х обнаруживает, и выстраивает их в табли ц у с заголовками
колонок, равными им е нам пол ей.

Мы можем явно на значить столбцы табли цы , qюрмируемой


Gr i dVi ew, опр едел яя и х заголовки, по рядок следова ни я, qюн , шрифг и
другие ас п екты отображения , скрывать или отображать. Есл и при этом
свойство Au t oGenerateColu mns остается ВЮIюч енны м, то в след за
явно определенными столбцами последуют автоматически
сген ерированные столб цы . Если свойство Au t oGenera t eColu mns

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

ОТКЛЮЧИТЬ И н е определить явно ни одного столбца , то GridView


ни чего не сгенерирует.

Каждый явно определенный столбец GridView может отн оси ться к


одному ИЗ типов, перечисленных в таблице.

Типы столбцов, явно определяемых в GridView


Тип Описание

Основной ти п , представляющий отображаемые


BoundField
данные поля

Столбец, представленый фrJaжками для


CheckBo x Field
отображения логических да нны х типа bi t
Отображает содержимое полей в форме
HyperLinkF i eld
2uперссЬ/лкu

Отображает графические данные и з дво и чно го


ImageField
поля

ButtonField Отображает содержимое полей в форме кнопок

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


Co mmandFie l d
редактирования

Специфицирует отображение множественных


полей , настраиваемых элементов управления и
Te mpla t eField произвольного НТМL, используя шаблон.
Обладает наибольшей гибкостью, но требует
больших ус илий в настройке

Для визуальной н астройки столбцов GridView пр една значено


диало гов ое окно Fields, которо е можно вызвать командой Edit Соlumns
(Add New Соlumn) через встроенную панель, щелкнув на кнопке с
пиктограммой треугольника в правом верхнем углу отображаемого на
Web-форме элемен та Gr idVi ew

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Flelds "*iJiJ
АvalЮle ftelds: Bc:u-кFieId lXoperties :

~= [!] :::J
. ИJ CheckВoxFieId
DаtcFспnatStrh;)
.iJ НyperLIi<.FieId S FooterStyIe
, tgJ ImageFieId
FooterText
dJ ВuttсП'ieId Незder 1rnagei..Xl
I!I-,g] Comm zn::1FieId I±J НeaderStyIe
.!Е TemplateFieId
НeaderText
Htrrl:lYode True
InsertVisbIe True
I±J Iterr6ty1e
N.LJispIayт ext
ReacOгfy Fase
SГю....tieader True
-
Sa-tEхlXеssia'l

НeadeгText
The text l'Iit!-il the header of ths field.

г Auto-generate fteIdS Convert Itis f!cld nto а Теrro!з1:eFicld

ос Са'УeI

Диалоговое окно Fields можно вызвать и по д ругому - щелкнугь на


свой ств е Со1 иmпз в п а нели Prop erties.

Все действия в диалоговом окне Fields запоминаются в дескрипторном


описании элемента Gr i dVi ew в разделе <Со 1 иmпз> , например

<asp :GridView ID="GridViewl" ruпаt= "server" АutоGе пе гаtеСоlumпs=''Fаlsе''>


< Со lumпs >
< аsр:ВоuпdField 1>
<asp:CheckBoxField 1>
< аsр:НурегLiпkField 1>
<asp:ImageField>
</asp:lmageFiek:l >
< аsр:ВuttопField Техt=''Вuttоп'' 1>
<asp:CommandField 1>
< asp :Теmp Ia te F ie ld > </asp :Теmp late F ie ld >
</Columns>
</asp:GridView>

Коллекцией столбцов можно управлять и программно , н а пример ,

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Gгю View 1. С о lumns[2 ]. Visible=true

скрывает третий столбец (нумерация с нуля). Скрытый столбец не


ге нерирует НТМL.

Если мы хотим сделать скролирующий Gri dVi ew внyrри Web-


страницы , то должн ы поместить его BHyrPb элемента Рапеl и
установить соответствующий размер панели и свойство
Panel . ScrollBa r s .

Элемент Gr i dVi e w падстраивается под источник данных , ю:порый


возвращает определенный набор столбцов. Если мы изменили
источник данных так, что он стал возвращать новый набор столбцов , то
команда Refresh Schema (обновить схему) встроенной панели GridView
вернет его в исходное состояние (регенерирует).

Свойства BoundFiekl
Свойство Описание

Имя поля элемента данных,


DataFi eld которое нужно отобразить в
данном столбце

Строка ф:Jрматирования, Удобная


DataFo rm atS t ri n g
для представления чисел и дат

Булев флаг включения строки


ApplyFormatl nE d it Mode
ф:Jрматирования

Текст заголовка , рисунок заголовка ,


Heade r Te x t ,
нижний колонтитул столбца. В
Heade r l mageUrl ,
нижний колонтитул можно
Foo t e r Te x t
помещать вычислимое выражение

Замыкает столбец от режима


ReadOn l y редактирования. Применяется , как
правило , к первичным ключам

Булев флаг ynравления


Inser t Vi sible
возможностью вставки

Скрывает столбец от ге н е рации


Vi s i ble
НТМL
В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

Определяет выражение, которое

SortE x pression может быть добавлено к запросу


для выполнения сортировки на

базе данного столбца

Булев флаг включения URL-


кодирования, при котором в
генерируемом НТМL управляющие
символы заменяются на ASCII.
Ht mlEncode
Делает генерируемый НТМL более
безопасным на клиентской стороне
и рекомеНдУется к применению как

можно чаще

Определяет текст, который будет


отображен в таблице на месте null-
Nu l lDisplayTe xt
значения (например ,
''неопределено'' )
Булев флаг. Если включен , то перед
подтверждением обновления в
Conve rt EmptyStr i ngToNul l конечном источнике данных все

пустые строки бу,цуг преобразованы


в пull-значения

ControlSty l e ,
Определяет стиль конкретного
Heade r Style ,
раздела отдельного столбца
Foote r Style , I t emSty l e

Ниже мы рассмотрим следующие разделы Gr i dVi ew:

1. Форматирование - определение внеlШlего вида отображаемых


данных

2. Сортировка - изменение порядка следования табличных значений


на экране пользователя в ответ на щелчки по заголовкам столбцов
з. Раскладка по страницам - разбиение вывода больших наборов
данных по отдельным страницам броузера
4. Шаблоны тонкая настройка большинства возможностей
Gr i dVi ew пугем определения шаблонов

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Форматирование в GridView

Элеме н т Gr i dVi ew и меет встроенные свойства управления


представлением генерируемой и м экранной таблицы в целом. К ним , в
том числе, относятся

• Ho riz onta l Al i gn - определяет выравнивание ячеек внугри

сетки экранной таблицы


• GridLines определяет видимость сетки генерируемой
экранной таблицы
• CellPadding , CellSpac i ng - определяют пр омежугки

между ячейками генерируемой сетки


• Capt i on , CaptionA l ign - определяет заголовок и его

выравнивание в верхней части экранной таблицы


• Сs s С 1а s s - устанавливает имя масса каскадной таблицы
стилей
• Стил и - рассмотрим далее ...

Форматирование полей в GridView

Каждый явно определяемый столбец Gr i dView имеет строку


форматирования в свойстве Dа taFo r ma tStr i ng . Форматные строки
состоят из заполнителя и спецификатора формата, заЮlюченного в
фигурные скобки.

Для иллюстрации материала нам понадобится тестовая ст р аница.

• г;.:.=СоздаЙте новое приложение командой FilelNewMeb Site с


именем WebSitelO

'"
В.М. СН"",,,В Про,раммupoвtJNШ' NQ ASP.NET

.1J~
T...-rpl ..,... Гf! ;:;:

~ ~ ~ ~
АЧ' r.ET \',00 ASP J-ET W3!J ж-sma l Vleb ЕrrjЖ)l Web
S ib SOfYEO S i'" stoc"" K~ S ib

[:'-0"'''' .. ,

01( Cd-<:" II

• г;;;?Скопируй те в катало г нов ого пр оекта файл Web .Config из


WebSite9 коман до й Website/Add Existing Item
• IJ$Создайте н овую стран ицу с объединенным кодом и имен ем
Gr idViewForma ted. aspx , которую заполни те так

<%@ Page Language=="C#" %>

<script runat== "server''>

strmg sql1 == "SELECT ТОР 3 * FROM Employees WHERE Ску<>' "


strmg sq12 == "SELECT ТОР 3 EmployeeID, FirstName, LastName, Тit
+ ''ВirthDаtе, City, HomePhone, "
+ ''Extension, Notes FROM Employees WHERE City<> "";
strmg sqlЗ == "SELECT ТОР 3 EmployeeID, FirstN аmе , BirthDate, Ext
+ ''FROM Employees WHERE Ску!== '''';

protected void Page_Load(object sender, EventArgs е)


{
Раgе.DаtаВiпdО;
}
</script>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<html xmIns= 'hup ://www.w3.or&,1999/xhtml" >


<head runat= "server''>
<tide > Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nшat= "sе rvег ''>
<div>
< аsр:SqlDаtaSошсе ID="Sq lDаtаSошсе 1" nшat="sе rvег "
SelectCommand= "<%# sqlЗ % >"
Provid erN ате= "system Da ы. Sq IC lient"
ConnectionS tring="<%$ ConnectionStrings:N orthwind %> ''>
<1as p:S q lDataS о шсе >
</div>
<asp:GridView ID="GridViewl " runat="server"
DаtаSошсеID= "S q lDаtаSошсе 1 ''>
</asp:GridView>
</fопn>
<lbody>
<lhtml>

Листинг. Тестовая страница GridViewFormated.aspx


• r;:;'и сполните страниц у GridViewFormated.aspx, чтобы получить
такой начальный результат

EmployeeID FirsrName BirthDate Exrension


1 Nancy 08.12.19480:00:00546 7
2 Andrew 19Ш.1952 0:00:00 345 7
3 Janet 30.08.19630:00:00 3355

в следующей таблице приведены спецификаторы формата ,


п рименяемые дл я п редставления чисел и дат

Спецификаторы формата для чи сел и дат

DataFormatString
Тип При мер результата
(варианты)

Денежный (О:С) $1,234.50


Десятич ны й (O:D) руб . 1234 руб .
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

(O:D руб.} 1234 руб.

Шаблон (0:#,###.# руб.} 1,234.5 руб.

Научный ( }
" О:Е 1.2345Е + 003
(экспоненциальныи)

(0:Е2} 12.345Е + 002

Процентный (О:Р}

Фиксированный
(O:F} 1234.5
десятичный

(O:FO} 1234

Дата и время по
06.15.2007 11:35:21
умолчанию

Дата (O:dd.MM.yyyy} 15.06.2007


(O:ddIМM/yyyy} 15/06/2007
(O:dddd - dd ММММ, Пятрица - 15 Июнь,
ууууг. } 2007 г.

(O:dd ММММ} 15 Июнь

(O:dd .MM. yyyy, dddd} 15.06.2007, Пятница

(O:dddd - dd ММММ, Пятрица - 15 Июнь,


Дата и время
ууууг. HH:mrn аа} 2007 г. 11:35 АМ
(O:dddd - dd ММММ, Пятрица - 15 Июнь,
ууууг. HH:mm:ss аа} 2007 г. 11:35:21 АМ
(O:dd.MM.yyyy, НН}
15.06.2007, 11 часов.
часов.

(O:dd.MM.yyyy, НН
15.06.2007, 11 часов.
часов.)

Общий (O:G}

Теперь нужно настроить Gri dV i ew l на предмет ф:Jрматирования


полей и проверять прив еденные спецификаторы. Учитывая, что в
таблице Employees поля B i rthDa t e и Ex tens i on датно е и
числовое соответственно, один из вариантов настройЮ1 Gr i dV i ewl
мог-бы быт ь таЮ1М

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<%@ Page Lапguagе="С#" %>

<script nmat="server''>

striпg sql1 = "SELECTTOP 3 >1< FROM Employees WHERE City<>"";


striпg sql2 = "SELECT ТО Р 3 EmployeeID, FirstName, LastName, Тitle , "
+ ''ВirthDаtе, C ity, НоmeРhопе , "
+ ''Ехtепsiоп, Notes FROM Employees WHERE City< >"";
striпg sqlЗ = "SELECT ТОР 3 EmployeeID, FirstName, BirthDate, Ехtепsiо п
+ ''FROM Employees WHERE City!= "";

protected void Page_Load(object sender, EventArgs е)


(
Page.DataBindO;
)
</script>

<html xmlns=''httр ://www.wЗ.огgl1999/xhtml''>


<head id= 'Head1" nmat="server">
<title>Untitled Page</title>
<lhead >
<body>
< fопn id="form1" ruпаt="sеrvег' '>
<div>
<asp :SqlDаtаSошсе ID="SqlDаtаSошсе 1" гuпаt="sеrvег"
Соnnесtiо пS tгiпg="< %$ Со nnесtiопStriпgs:Nо rthwiпd %>"
ProviderN аmе= "S ystem. Data. S q IС lient"
SelectCommand="<%# sqlЗ % >">
</asp:Sq lDataSource>
</div>
<asp:GridView ID="GridView1" runat="server"
DаtаSоuгсеID="SqlDаtаSошсе 1"
Auto GenerateCo lumпs=' 'F alse ''>
< Соluпms>
<asp :ВоuпdField DataField= "BirthDate"
DаtаFоrmatStriпg="{О:ddIММ /уууу } "
НеаdегТехt=''Родился''
ReadOnly='True" 1>
< аsр:ВоuпdField DаtаFiеld="Ехtепsiоп"

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

DataFormatString="{O:## ###.##} р."


Неаd егТехt=''ОЮJaД''
ReadOnly='True" />
</Соlumns>
</asp:GridView>
</form>
</body>
</html>

Листинг . Один из вариантов настройки GridViewl на странице


GridViewFormated.aspx

• ~3апустите страницу GгidViеwFопnatеd.аsрх и у6едитесь, что


описанное qюрматирование не работает!!!

Неудач ный НТМL ~в ывод

Родился Оклад

08 .1 2.1948 O:OOjJO 5467 р.

19.02.1952 O:OOjJO 3457 р.

30.08.1963 O:OOjJO 3355 р.


Я потратил полдн я на попытки добиться ус п еха в этом вопросе , но
описанный механизм qюрматирова ни я GridView у меня Bce~paB H O не
работает. Не работает и пример из MSDN . Просто замалчивать свое
фиаско я не захотел. Теперь слово за вами , уважаемые СТУденты .
Разберитесь в вопросе - может КТO~TO и за п устит.

Идем дальше ...

Стили в GridView

Gr id View пр едоставляет свойства для восьми стилей

qюрматирования, перечисленные в таблице. Э то не простые


однозначные свойства, а составные объекты , имеющие все
необходимые на стройки. Все они влияют на внешний ви д генерируемой
НТМL-сетки в целом.

Свойства стилей GridView


в.м. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

Свойства стилей Описание

Определяет стиль строки заголовков


Heade r Style
столбцов

RowStyle Определяет стиль каждой строки данных

Определяет стиль каждой четной строки


AlternatingRowStyle д
анных

Определяет стиль текущей выбранной


Se l ectedRowStyle
строки данных

Определяет стиль текущей строки данных,


Ed i tRowSty l e
находящейся в режиме редактирования

Конфигурирует стиль, используемый для


отображения одной пустой строки, когда
EmptyDataRowSty l e
привя занны й объект да нны х вообще не
содержит строк

Определяет стиль строки нижнего


Foote r Style колонтитула столбцов (
ShowFooter= t rue )
Определяет bhellD-lИЙ вид ссылок на

составные страницы , если ВЮIючено


PagerS t yle
постраничное разбиение (
Al l owPaging=t r ue )

Настройку стилей для таблицы в целом можно выполнить тр емя


способами:

1. В режиме Design через панель Propertles, выделив элемент


Gr i dVi ew. В этом случае создается стилевой дескри пт ор

<asp:GridView ID="GridView1" nmat="server"


DаtаSошсе ID = "Sq lD а tаSошсе 1"
АutоGепегаtеСо!шnns= "Fаlsе " >
<RowStyle BackColor=''Red '' Fо геСо !ог= ' 'Уеllоw'' НогizoпtаlAщ
</asp:GridView>

2. В режиме Sошсе через панель Properties, уста новив курсов в


заголовок открывающего дескр иптора Gr i dVi ew. В этом случае
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

создаются стилевые атрибугы этого дескри п тора

<asp:GridView ID="GridViewl " nmat= "server"


DаtаSошсе ID ="Sq lDаtаSошсе 1"
АutоGе пегаtе Со lшnns ="Fаlsе"
RowS tyle- Back С о 10 г= ''red''
RowS tyle- F oreC о 10 г= ''уе llo w"
RowS tyle- НorizoпtаlAlign="Сепtег" >
</asp:GridView>

з. в р еж и ме S ошсе , н абирая вручную либо сти левой дескриптор ,


либо уго ч няющие атрибугы. Подсказчик кода оболочки п оможет
п равильно настроить стилевые параметры.

Ан алогич н ым образом н астраиваются инди видуальные стил и столбцов


для случая , ко гда в Gr i dVi ew явно о п ределены столбцы .

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Серверные элементы управления

Web-элемент ynравления LiteraL Web -эл ементы ynравления ТаЫе ,


Tab leRow, TableCelL Web -э лемент ynравления lmage. Web - элемен т
ynравления lmageButton. Web - элемент yn р авления ImageButto n. Web-
элемент ynравления lmageMap. Расширение стан да ртного HotSpot.

Файлы к лекции Вы можете скачать здесь скачать:

http://o и. intШ . ruld epartmentJintemetJp rasp netJ 15/15.пр.

Ра ссм отрим н екоторые серверные элементы управления, которые


находятся в пр остранстве имен Sys t em . Web . UI. WebControls
библиотечной сборки
С:\WINN1\Мiсгоsоft.NЕТ\Fгаmework\v2.0.50727\S ystеm.WеЬ.dlL Все они
пр едставляют собой некоторую абстракцию , способ н ую генерировать
юшентский код (НТМL и JavaScript). Некоторые из этих элемен тов
отображаются на странице в режиме Design примерно так, как о ни будyr
пр едставлены пользователю , а некоторые просто визуализи руются

объектом, который при выполнении сгенерирует нужный клиентский


код в соответствии с его настройками . При этом неважно , БУдyr ли эти
элементы созданы и настроены в режиме пр оектирования, или в

режиме выполнения кодовой части страницы, написанной на С# . В


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

п омощью кода в зависимости от действий п ользователя , п олученных


сервером с обратн ой отсылкой PostBac k .

Web-элемент управления Litera!

Элемент управленияSys te m . Web . UI . WebCon trol s . Li teral


обладает слабой функциональностью. Он генерирует те г <span> и
ynaКOBbIBaeT в него т екст, пр исвоенный свойству Te x t . Э ТО значит, что
к выводимому содержимому нельзя приме ни ть никакие стили - оно
выводится как есть. Но элемент Li teral имеет свойство Mode,
п озволяющее уста нав ливать способ пр едварительной обработки
выводимого текста с помощью присво е ния значений из перечисления
System . Web . UI . WebControls . LiteralMode

Пеn еч исление I,jteralMode аля свойства Мode ;иемента упаавдеНIJЯ


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Litera/
Mode Значе ни е Text
Удаляет из текста неподцерживаемые броузером теги.
Transform
Если теги относятся к языку разметки НТМL или
о
XHTML , то содержимое текста не модифицируется

Pas sThrough Содержимое свойства Text передается броузеру без


= 1 изменений

Encode = 2 Управляющие символы кодируются в НТМL

Пример

• ~омандой меню FilelNewlWeb 5ке создайте Н ОВЫЙ Web-проект


===----'-.lI~

с3 ~
P<>r=.1 \fJob Errpty" Wob
5,~ 5t<f"R К( 5 ,."

5eafch On lre
Т" Щ' k!te , .. ,

Loc,",, :

CdJ:eI 11

• ~ ереименуйте в панели 50lutiоп Explorer созданную по


умолчанию страницу Default.aspx в MyLi te ral . азрх и Удалите
из п роекта п а п ку Арр _Оаы

• Г;;:;=Измените в начале страницы LiteraLaspx в директиве @ Page


значение параметра Inherits= " Defaul t " на

Inherits= " MyLiteral "

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• IJ$О ткрой те
файл MyLiteraL aspx.cs и изм е ни те имя м а сса
Defa u l t на My Ll t e r al
стр а ницы с

• ~О тредактируйт е обработчи к P age Load следую щим об р аз о м

using System;
using System.Data;
using Sуstеm.Сопfigurаtiоп;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using Sуstеm.WеЬ.U I .WеЬСопtrоls;
using Sуstеm.WеЬ.U I .WеЬСопtrоls.WеЬРаrts;
using Sуstеm.WеЬ.U I .НtmlСопtгоls;

риыic рапial class MyLiteral: System.Web.UI.Page


{
// Свойство для генерации тега < Ьг > </Ь г>
protected НtmlGепегiс С опtго l BR
{
get { геturп пеw НtmlGепегk: С опtrоl( 'Ъ г''); }
}

protected void Page_Load(object sепdег, ЕvепtAгgs е)


(
Literal literal = new LitегаЮ;
forml. С о ntro Is.Add(litera 1);
fuгml. C ontгo~ . Add(BR);
literaLMode = LitегаlМоdе . ТгаnsfоПll;
literaLText = @'Transform: < foпt size=6 >Привет студентам СФУ!
+ @"<script>alert(' Привет СТУде нтам кафедры "' ПМ и АСУ "

literal = new LitегаЮ;


forml. С о ntro Is.Add(litera 1);
fuгml. C ontгo~ . Add(BR);
literaLMode = LiteralМode . Pa ssТhro ugh;
literaLText = @''Р а ssТhrоugh: < fопtSize = 6 > Приветдоцентам С Ф
+ @"<script>alert(' Пр и вет до цен там кафедры "' 'ПМ и АСУ'"

literal = new LitегаЮ;


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

forml. С о ntro Is.Add(litera 1);


literaLMode = L ite raIМod e . Encode;
literaLText = @''Encode: <font size=6> Прив ет ректору С Ф У!< /fОI
+ @"<script>alert(' При вет заведующему кафедрой "'nM и А
}
}

Листинг . Класс изучения режимов элемента Literal

Хотя в разметочной части страницы мы код н е создавали , все р авно


р е н деринг стран ицы бу,цет следую щи м

~ Untitled Page - Мicrоsоft Internet Explorer

~
e Edt Y'r€W F.avrntes Toofs ~
+-в.аCk .......... Iij @J tJ:jO eaSear(h (!j FаУопtes ~ мediз G
Adctes<; 11I htI+J /!o::.am st 1О37!WеЬэtе ll;МyLlteral aspx

тгansfопn:Привет студентам сфу!

Рas,ТhrоughПривет доцентам сфу!


Encode: <fon! sizе~6>Привет ректору СфУ!</fопt><sсriрt>alеrt
(' Привет заведующему кафедрой "ПМ и АСУ" ')</script>

в коде используется функция а 1 е r t () кrшентско го языка JavaScript,


котор ая ге н ерирует окно сооб щений в броуэере. Для простоты , чтобы не
запугаться в д воины х кавычках, аргум е нт эт ой функции заключен в
оди н арные кавычки. Двойные ка вычки в л итеральной строке @" •.• "
заэкранирова ны также д войными кавы ч ками, как этого требует
синтаксис языка С#.

Последняя строка в коде HTML выглядит так

Encode: &lt;font size=6&gt; Прив ет ректору С ф У!&k;/fo пt& gt;&h;sс гipt&gt;а


&lt;/script&gt;

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

в ней левая угловая скобка заменена на & 1 t i, правая на & 9 t i , а


двойные кавычки на &quot;. Такой код для броузера БУдет безопасным ,
поскольку не даст выполниться вредоносным скриптам

злоумышленников, если код поступает от сомнительных источников.

Web-элементы управления ТаЫе, TableRow, ТаЫеСеll

Для позиционирования статических данных, рисунков и элементов


управления при меняются НТМL-дескрипторы (теrn) <table> . Их
можно создать с помощью элемента у правления Html ТаЫе , добавив
в дескриптор атрибуг runat= " se r ver ". Но для программного
формирования таблиц ' 'на лету" и заполнения и х да нными удоб но
использовать более развитые серверные элементы управления ТаЫе ,
Ta bl eRow и TableCell , с которыми мы сейчас и познакомимся.
Хотя их можно применять и для отображения статических данных.

Элементы управления ТаЫе , TableRow и TableCell не


сохраняют состояние после возврата формы на сервер и их нужно
восстанавливать заново программным способам, повторно выбирая
данные из источника. Альтернативным пугем для сохранения
состояния строк и ячеек является прим е н е ни е элементов управления

DataL i st и GridVi ew.

у элемента ТаЫе имеется свойство Rows , которое представляет


собой коллекцию объектов TableRow . Количество объектов в
коллекции равно количеству строк таблицы при рендеринге. В свою
очередь, каждый объект Ta bl eRow имеет коллекцию ячеек таблицы в
виде объектов TableCe l l , которые в динамическом режиме
за полняются данными через свойство TableCell . Te x t .

Приведем пример .

• ~Добавьте к текущему проекту командой Website/Add New ltem


новую страницу MyTable.aspx с отделенным кодом
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET
АМ ",",VJ Itpm - C·\Ch~ .. R()nk\WFА\дSP NFT? () ~ r..t: (VS i'.FT 'ХЮ5)\ 11) r""RPpHhlf' 'Jlf'МРНТh' V"I' .lJ~
Т""1""»>
Ii ; ,:::


l/Ii!IiIIIII
D
м.,,,• .- Pogo _"_
[!j]
ccrn-o l
КТ .....
00 Pogo
!i
Web S• ..,~e
~
С ",,,
~
stj i< SCe" t

,-&J,
"PP 1 ~a~ ",

Ц'Jj
-~
crnfgJa:I ",
~
~ F I Io
h'Schoma
х м..
iJ ~
То" Fil2
]j
R о=.л: о Fi'"

.
ij
SQ.- о..:..Ь=

Dазset -~,
flrd iof
i.I1I
5<00 M~
1t!J'
M:tJt:e I'Jeb
' ..m
o'!'l
\1\5(r"" Н е
~
,-,
~
J5Cfp~ "е

.-
[1::'" ~
I д forrn for Wo!:J ц" ь,,,,,,
,iJ!I .
IЭ (о) jjJ

~W I MIT~"'d'PX
L~: I V "'-"' I С f iJ '" p!io:e сWэ n "1Нае filo
Г Seloct гrвsOO<1"'9"

• ~ змените в файле MyTable .aspx.cs класс МуТаЫ е следУЮЩИМ


об р азом

using System;
using System. Data;
using Sуstеm.Сопfigurаtiоп;
using Sуstеm.Соllесtiо пs;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using Sуstеm.WеЬ.U I .WеЬСопtrо ls;
using Sуstеm.WеЬ.U I .WеЬСопtrо ls.Wе ЬРаrts ;
using Sуstеm.WеЬ.U I . НtmlСопtгоls ;

риыic рапia! class MyTable : System Web.UI.Page


(
сопst int rowMax = 5, со!Мах == 4 ;// Размеры табл ицы
// id=forml форма - р од ит ель в разметочной части страницы

protected void Page_Load(object sепdег, Еvе пtAгgs е)


{

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

// Формируем оглавление страницы в НТМL


Labe!labe! = пеw Label();
form!. С о ntгo ~. Add(labe 1);
LзЬеLТеxt:= "< h1 >Д инамическая таблица < /hl>";
LзЬеLFогеСо!or = System.Drawing.Co!or.Red;

// Формируем саму таблицу


System Wеь.uI.WеЬСопtгоls.Таblе tabIe:=
пеw Sуstеm.WеЬ.UI.WеЬСопtrоls.ТаblеО;// Создали таблицу
foгm1.сопtгоls.Аdd(taые;/ // Добавили в форму

// Настраиваем таблицу
table.BorderWidth := 1;// Рамка таблицы
table.Style. Value := "а ligп:=сепtег";
// Формируем строки
for (int row := О; row < rowMax; row++)
{
TableRow tr := пеw TabIeRowO;// Создал и строку
table.Rows.Add(tr);// Добавили в таблицу

// Продолжаем настраивать , доб авляя ячейки


for (int со! = О ; со! < со!Мах; со!++)
{
TableCell tc := пеw TableCell();// Создали ячейку
tr.Cells.Add(tc);// Добавили в строку

// На стр аиваем ячейку


tc.Text = string.Fоrmat("ячеЙка{ {{О}, {l} } } ",
row + 1, со! + 1);
tc.BorderWidth := 1;// Рамка ячейки
if (row % 2 :=:= 0)// Нечетные строки
tc.BackCo!or := SystemDrawing.Co!or.Moccasin;
else // Четные строки
tc.BackCo!or := SystemDrawing.Co!or.PowderB!ue;
}
}

// Горизонтальная черта
foгm1.Сопtгоls.Аdd(пеw HtmlGenericContro~ ''hr'1 );

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

// Подвал страницы
Lз Ь е!:= пеw Label();
form! .С о ntгo ~. Add(labe 1);
Lз Ь еLТеxt:= "< stго пg>Э то подвал страницы (цокольный этаж !:
)
}

Листинг . Класс динамического формирования таблицы

Р е н де р ин г этой стра ниц ы будет следую щи м

"';1 Untitled Page - Мicrоsоft Internet Explorer


-----------------------------
Fie Ed t View Favorites Tools Н€lp [
"ВасК ~ .. ~ 'о @J Gi! <t\ Sea- сh (Jjj Favcriteo (;rМed" (;, !<Э ~ /i;J l"1!
I ,& @

Динамическая таблица
ячейка{ 1,1} ячейка{ 1,2} ячейка{ 1,3} ячейка{ 1,4}
ячейка{2,l} ячейка{2,2} ячейка{2,3} ячейка{2,4}
ячейка{З,l} ячейка{3,2} ячейка{3,3} ячейка{3,4}
ячейка{ 4,1} ячейка{ 4,2} ячейка{ 4,3} ячейка{ 4,4}

ячейка{ 5,1} ячейка{ 5,2} ячейка{ 5,3} ячейка{ 5,4}

Это подвал страннцы (цокольный этаж !)

h u-met

П о п уг н о , для с п равЮ1 , н а п ом н им ц вета , и спол ьзуемые в Web:

R GB
Color Color Name RGB Value Color Color Name (
Value

,СО
В.М. С""",,,в

Ligh,Рiпk #FFB6C l _ LightSlateGray


Про,раммupoвtJNШ'

#778899 -
110 ASP.NET

Рiпk #FFCOCB _ Sla'eGгay #708090 -


_Сгimsоп #DC 143C _ DodgerBllle #IE90FF -
Lavend erBlush #FFFOF5 AliceBlue #FOF8FF -
_ PaleVioletRed #DB7093 _ SteeIВllle #4682В4 -
_ HotPink #FF69B4 Ligh'SkyBlue #87CEFA -
_ DeepPink #FF1493 SkyBlue #87СЕЕВ

- МеdiШllVюlеtRеd #С71585 _ DeepSkyBllle #OOBFFF -


_ Oгchid #DA70D6 Ligh'Blue #ADD8E6 -
Thisde #D8BFD8 PowderBlue #ВОЕОЕ6 -
Рlшn #DDAODD _ CadetBllle #5F9EAO

_ vюlеt #ЕЕ82ЕЕ Аzше #FOFFFF

_ Magenta #FFOOFF Ligh,Cyan #EOFFFF

_ Fllchsia #FFOOFF PaleTurqlloise #AFEEEE

_ DarkMagenta #8ВО08В _ Суаа #OOFFFF

_ Рш-рlе #800080 _ Aqua #OOFFFF

- МеdiШllОгсhid #ВА55DЗ - DarkTurqlloise #OOCEDl

- DarkViolet #9400 D3 - DarkSlateGray #2F4F4F

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

_ DarkOrchid #9932СС _ DarkCyan #008В8В

_ Ind igO #4ВО 082 _ Теаl #008080

_ BlueVio let #8А2ВЕ2 _ МеdiumТшquоisе #48D1CC

_ МеdiшnPшрlе #937 00В _ LightSeaGreen #2 0В2АА

_ МеdiШllSlatеВluе #7Вб8ЕЕ _ ТшqUОisе # 40ЕООО -


_ SlateBlue #БА5АС О Aquamarine #7FFF04 -
_ DarkSlateBlue #48 3 08В _ MediumAquamarine #ббС DАА
Lavend er #ЕБЕБFА _ МеdiumSргingGгееп #ООРА9А
GhostWhite #F8 F8FF MintCream #F5FFFA

_BJue #OOOOFF _ SpringGreen #00FF 7F

_ МеdiшnВluе #О ООО С О _ МеdiumSеаGгееп #3СВЗ7 1 -


_ MidnightВlue #191970 _ sеаGгееп #2Е8 В5 7

_ D a rkBlue #0 0008В Нопеуdеw #FOFFFO

_ Navy #000080 LightGreen #9 0ЕЕ90

_ RoyalВlue #41б9Еl PaleGreen #98FB98

_ СогпflowегВluе #б 495ЕО _ DагkSеаGгееп #8F BC8F

LightSteelВlue #ВОС40Е - LimeGгееп #32С DЗ2

Web-элемент управления Image


'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Элемент управления Sys te m. Web . UI . WebCon trol s . Image


является упаковкой для размещения рисунка на странице. При
рендеринге он генерирует НТМL - тег < i mg> с пара мет р ами ,
установле нны ми свойствами элемента. Свойство Image . I mageU r l
задает пугь к изображению , которое хр ани тся на сервере и которое
затем броуэер за про сит при получени и тега <i mg src= " I mageUrl "
/> , сгенерированного элементом Image . Свойств о
Ima ge . Al terna teTe x t генерирует атри буг аl t всплывающей
подскйзки или текст на месте неУдачно загруженного рисунка. Эту же
функцию выполняет булево свойство
Ima ge . Genera t e Emp t yAl te rna teTe x t . которое ВЮlючает

гене р ацию атрибуга аl t в том случае, если и зоб р ажение будет п устым.

Элеме н т Image не распознает событие Cl i ck , для этого служат


элементы ImageBu t ton и Image Map . К тому же последние
отслеживают координаты точки курсора относительно изображения, на
которую пришелся щелчок мыши.

Свойство Image . I mageAl i gn ждет одно из з начений одноименного


п еречисления Sys tem . Web . U1 . WebCon t r o l s . ImageA l i gn , с
помощью которого задается режим выравнивания изображения
относительно других объектов рендеринга страницы.

Свойство Image . Descr i pt i onUrl позволяет привязать к

и зоб р ажению страницу, где находятся сведения об изображении в


текстовом или звуковом представлении. Используется в случае, если

страница готовится для людей со слабым зрением.

Приведем пример .

• ~Добавьте к текущему проекту командой Website/Add New ltem


новую страницу Mylmage.aspx с отделенным кодом

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

.1J~
T<><rp!= ri ; ,:::


lIII:!IiIIIII
D
м.",,..- Pogo
I!]
_ с_

ccrn-o l
~
КТf.1.. Pogo
!i
W еЬ5.п~е
~
Ck!"
~
sry., SCe" t

,-&1,
"«, I ~ a ~ ,,,
-
~
crn~gJ"~I",
в1
)(]VL F,Io
!JIj
X ~ Schotm
~
То" Fil2
J'j
ROЮ'JC. Fi'e
ij
SQ.-o.:..b=

[НJ
Оа135е ! -,~
11rd ...
~
s.te M~
i]r"
с

M: tJl:e I'Jeb
'.m
~
\1\5(rl): ":е
;.
~
е_,
~
J5Cr\X "е

~'
I~ form for WoI:J ц" ь:ion<
~> "I"~
, ,~
-.~,=.=,--------------------------------,I

СI,=~=,=
,,:----------iJ-::l
. '" p!io:e сООе n "V"ae fie
Г Seю mзste< 1'39"

Сд'<:eI 11

• ~ панепи So lution Ехрюгег выделите ст р аницу Mylmage.aspx и


вы п ол ни те команду ме н ю Website/Set As Start Page, чтобы сделать
страницу стартовой
• ~Для корневого узла проекта в панели Solution Explorer вызовите
контекстное меню и командой New Fo lder добавьте катало г lmages
• ~ панели So lution Ехрюгег выделите папку lmages и командой
Website/Add Existlng ltem добавьте к про екту два рисунка из нашего
катало га Pictures (и ли из любого друго го и сточ ни ка), например ,
DOGВIG.png и DOGPLANE.png
• ~ змените в файле Mylmage .aspx.cs класс MyI mage следУЮЩИМ
образом

using System;
using System.Data;
using System.Configuration;
using System.Collectio ns;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebContro ls;
using System.Web.UI.WebContro ls.WebParts;

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

using System.Web.UI.HtmlControls;

риыic рапia l class MyImage : System Web.UI.Page


(
Image image;

protected void Page_Load(object sепdег, ЕvепtAгgs е)


{
/lRespo nse .С leагСопtепtО;

/lPасфаСОВblваем элемеНТbI ДЛ Я отюIИка


if (!Page.I s Po stВack)// ПеРВblЙ запрос
(
image :::: new ImageO;
image.ImageUrl:::: "~ lImagе sIDОGВIG.рпg";
imagе.АhегпаtеТехt == "Отклик сервера на пеРВblЙ запрос";
forml. C ontrols.Add(image );
imagе . ЕпаЫеViewS tа tе:::: false;
}
else // Обратная ОТСblлка
(
image :::: new Ima geO;
image .ImageUrl :::: "~ lImage sIDOGPLANE.png";
imagе.АhегпаtеТехt :::: "Отклик сервера на обратную ОТСblЛКУ
forml. C ontrols.Add(image );
imagе.ЕпаЫеViewStаtе :::: fals e;
}

foгml. С опtгоls.Аdd(пеw НtmlGеneгiсС опtго~ ' Ъг' ')) ;

Button submit :::: new ButtonO;


submit.Text:::: ' 'Po stВack '';
forml . С о ntro Is. Add(sub шit);
suЬmit.ТооШр :::: 'Э то кнопка Submit";
}
}

Листинг . Класс MyImage


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Обрат и те внима ни е, что значек " ~ " (тильда) в знач е нии свойства
ImageU r 1 означает корневой каталог п риложения ( н о н е сайта root).

Рендеринг этой страницы при первом за п росе БУдет следУЮЩИМ:

11 Untitled Page - Мicrоsоft Internet Explorer:


FMe Edlt y~w Favorites ТОols Help
Back ........... о t2.\ search ~ Favorites
: 1037 ;WebSite 11,f.1ylmage.aspx т

PostBack

Оопе

Web- элемент управления ImageB utton

Этот серверный WеЬ~элемент управления совмещает в себе свойства


элемен та Image и кнопки , т.е. генерирует рисунок, который является
чувствительным к щелчку мы ши и и нициир ует обратную отсылку на
сервер. Кроме то го, событие щелчка мыши на кrIИе нт е п е редает с
обратной отсылкой в об р аботч и к сервер н ой стороны коорди наты мыши
относи тельн о лево го верхнего угла рисунка в броуэере.
,ее
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Приведем пример .

• ~Добавьте, как и ранее , к текущему п роекту страницу с именем


Mylmage B ut ton . asp x с отделенным кодом. Сделайте ее
стартовой и заполни те масс MylmageBut t on следУЮЩИМ
КОДОМ

us iпg System;
us iпg System.Data;
us iпg Systеm. Со пfigша tiоп;
us iпg System. Collections;
us iпg System. Web;
us iпg System.Web .Security;
us iпg System. Web.UI;
us iпg System. Web. UI. WebControls;
us iпg System.Web.UI.WebControls. WebParts;
us iпg System. Web.UI.HtmlControls;

public partial class MyImageButton: System. Web.UI.Page


(
lmageButton imageButton;

protected void Page_Load(object sender, EventArgs е)


(
imageButton:= new lmageButtonO;
fo пnl. С о пtrо Is.Add( ima ge В utto п);
imageButtOn.lmageUrl:= "~ lImagesIDOGBIG.png";
imagеВuttоп.АltегпаtеТехt:= ''Э то рисунок-кнопка";
imageButton.Clk:k +:= new lma gеС liсkЕve пtНапdleг(imagеВuttоп_Сlick);

11 Настр о йка р амки рисунка


imageButton.BorderWidth:= 7;
imagеВuttоп.ВordегСоЮг:= Sys tеm.Dга w iпg.СоЮг. Rеd ;
imageButton.BorderStyle := BorderStyle.DoubIe;
}

void imageButton_Click(object sепd ег, lmageC lickEventArgs е)


(

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

imageButton.AlternateText:= Striпg.Fоrmat(
''Координаты щелчка: ({О}, {l} )", е.Х, е.У);
}
}

Листинг Класс MyImageButton

Рендеринг это й страницы при очередном щелчке на р и сунке будет


следующим :

~) Untitled Page - Мicrоsоft Internet Explorer


File Edt View Favorites Tools l-\elp
Ш Fаvоritеs

htqo:/,1осаlrюst: 1О37(WеЮtе lljMyImageButton.aspx •

Оопе

Обратите в н имание на способ на стр ойки рамки ри сунка .

Web-элемент управления ImageMap

в НТМL существует понятие карты изображений (image mар), когда


од ин и тот же рисунок, отображаемый в брауэере, дел и тся на отдел ьные

,ее
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

чувствительные к щелчкам мыши зоны ( hot spots - горячие пятна). При


щелчке поль зователя на одной из этих горячих зо н броузер инициирует
обратную отсылку с закрепл е нным за зоной URL. Таким образом , из
од ного рисунка мы можем сделать несколько Submit -кно пок Карту
изображений иногда на зывают навигационн ой панелью (Navigation
Ваг)

Вот при мер рисунка, размеченного условно на отдельные


пря моугольны е области.

(0,0) (162,0) (324,0)_ _.....1


Х

1 2
(0,94) 1--_----'-
(1_6--'
2,'--
94-'.)+-_ _ _----1 (324,94)

(0,188) (162,188) (324,188)

Давайте вначале рассмотрим прим е н е ни е карты изображений в


статическом варианте страниц саЙ та .

• Г;;:;-Добав ьте к корневому узлу проекта статическую страницу с


именем I mageMap . h tт и сделайте ее стартовой командой Set
At Start Page контекстного меню страницы

,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET
АМ ",",VJ Itpm - C'\Ch~ .. R()nk\WFА\дSP NFT? () ~ r..t: (VS i'.FT 'ХЮ5)\ 11) r""RPpHhlf' 'Jlf'МРНТh' V"I' .lJ~
Ii ; ,:::

-
Т""1""»>

ш! D [!j]
_ с_ I !i ~ ~
I'lob Form • .- Pogo
м.,,, Wob S• ..,~e С",,, stj i< SCe" t
ccrn-o l

,-&J,
"PP 1 ~a~ ",

Ц'Jj
-~
crnfgJa:I",
~
~F , ", X~
h'iJ
Schoma
~
То" Fil2
]j
R о=.л: о Fi'"
ij
SQ.- о..:..Ь=

Dазset -~,
flrd iof
i.I1I
5<00 M~
1t!J'
M:tJt:e I'Jeb
' ..m
o'!'l
\1\5(r"" Н е
~
"
,-,
~
J5Cfp~ "е

.-
[1::'" ~ ,iJ!I
Iдn ктм.. Р'9' thot ''''' h:Wo , I"",t-""" codo
.
IЭ (о) jjJ

~w I] ~.htm

<Q'
, • iJ г р """~
, >!p3I&e '"
Г~~ 'tRr r""e

• ~Добавьте в папку Images проекта рисунок I magеМар.рпg (из


пр ила гаемого каталога Рiс tше s )
• ~3аполните страницу lmageMap.htm следУЮЩИМ кодом

<html xmIns= ' huр ://www.wЗ.or&,1 999/xhtml" >


<head>
<tide >Untitled Page</tide>
<lhead>
<body>
<form ю ="foгm1 " nmat="selVer''>
<div>
<!-- Описание навигационной пан ел и -->
< шар id=''N ауВаг " паme=''NаvВаг''>
< агеа а k="Один" coords= ''O, О, 162,94" hrеf= "опе,htm" shap
< агеа а k="Два" coords="162, О, 324, 94" href= ''two.htm'' s hщ
< агеа а k='Тр и " coords=''O, 94, 162, 188" href= "three.htm" s h~
< агеа а k=''Четыре'' coords="162, 94, 321, 188" hrеf= "foШ.hu
</maр >

<!-- Исп ользова ни е навигационной п а нел и -- >


<img аh=' 'Навигационная пан ель" bordeF''O'' src="lmagesllm:
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</div>
</fonn>
</body>
<lhtml>

Листинг. НТМL - код статической страницы ImageMap.htm


• Г;;:;-Добавьте к корневому узлу проекта еще ч етыре статических
ст р аницы

о one.htm
о two.htm
о three.htm
о foш.htm
• Г;:;==Заполните каж.цую из страниц соответствующим текстом по
пр иведенному об ра зц у

<html>
<head>
<tide >Untitled Dосuшепt</title >
<meta http-еquiv= "С опtепt-Туре " сопtепt= " tех tJhtшl; charset=window!
<lhead>
<body>
<h1 >
Стра ница вызвана по щелчку на горячей зо не 1
<lhl >
</body>
<lhtml>

Листинг Образец текста для страницы one.htm первой


горячей зоны

• ~Запустите страницу lmageMap.hun и испытай те ее

функциональность

Рендеринг страни цы lmageMap .hun БУдет таким


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

11 Untitled Page - Мicrоsоft Internet Explorer


FMe Edlt y~w Favorites ТОols Help
............. о ~ Gj Et\ search ~ Favorites
:1037jWеЬSitеllЛmagеМар.htm ~

1 2

Мы ВИ ДИМ , что страница функционирует, но мы н е можим постр ои ть


дл я нее сложную логику, по скольку серве р ом она не обрабатывается , а
посылается как есть один р аз. З ат ем в бр оузере вызываются
привязанные к горячим З0 нам файлы. Здес ь на выручку при ходи т
серверный we b-з леме нт I mageMap , который по зволяет организовать
полноценную навигацию по сайту (с пров еркам и п аролей и всех других
нужных дел на стороне сервера). На выходе он БУдет генерировать
такой-же клиен тски й HTML -КОd , который мы только что рассмотрел и.

При рен деринге эл емент управления ImageMap ген ер ирует тег < i тg

use map= " #myMap " /> и тег <тар id= " myMap "
пате= " ту М ар " > с вложе нными элементам и <area> . Элем ент
управления I mageMap им еет слеДующие свойства

С войства элемента lmageMap


Свойство Описание

Enabled ВЮlючает или ВЫЮJючает рендеринг элемента

m
В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

HotSpo t s Содержи т коллекцию до ч ерних объектов HotSpot ,


определяющих горячие зо ны

Виртуальное свойство , кото р ое устанав л ива ет для


дочер ни х элеме нтов HotSpot ( гор яч и х зо н)

пов еде ни е п о умолча нию и может быть в них


пер ео пр еделено. Ожидает одно из з н аче ний
одноименного перечисления

Sys t em . Web . UI . WebControls . HotSpo tM ode :

• Inact i ve = 3- никак н е реаrnрует на

щелчок мыlШ1

• Nav i gate 1- вызвать страницу связанного

HotSpo tM ode URL


• No t Set = О - пов еде ние уста н авливается

дочерн и м и элементами самостоятельно (по


умолча нию ) . Если и дочер ни е элементы не
п ереопределяют это свойство , то используется
пов еде ни е по умолча нию - вызов страницы по

URL
• PostBac k = 2 - при щелчке пользователя

прос то инициировать обратную отсылку для


анализа сервером

Виртуально е свойство , устанавливаю щее по


умолчанию для своих до ч ерних элементов HotSpot
Target окно или фрейм, ку,ца сервер должен прислать отклик
на щелчек пользователя . В каждом HotSpot оно может
быт ь индивидуально п ерео пр еделено

Дочерние для I mageMap эл ементы управления HotSpot также и меют


свои свойства HotSpotMode , имеющие преоритет н а.ц родительским
HotSpotMode . Если мы хотим , чтобы это свойство принималось от
родительского элеме н та, то в дочер н ем элемен те Ho t Spot н ужно

установи ть значение HotSpot Mode=NotSet . Если в родительском и


дочернем элементах уста новл ено значение HotSpot Mode=NotSet,

то HotSpo t дочер н е го элеме н та работает в режиме Navi ga te .


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

в приведенной таблице под объектами масса HotSpo t коллекции


HotSpots подразумеваются три разновидности объектов ,
произведенных его прямыми потомками:

• Объекты класса CircleHotSpot HotSpot


• Объекты класса Re ctangleHo t Spot HotSpot
• Объекты класса Po l ygonHo t Spot Ho t Spot

Именно они ответственны за генерацию тега <area> с нужными


параметрами, которые устанавливаются в свойствах объектов этих
массов. Других геометрических примитивов для опред еления горячих
зон элемента Image Map в библиотеке .NET Framework 2.0 не
предусмотрено.

Общие свойства КIlaccoв наследуются от HotSpot и представлены в


таблице

Общие свойства , наследуемые от HotSpot


Свойство Описание

Содержит одиночный символ (горячую мавишу),


AccessKey который составляет вместе с Alt мавиатурную
комбинацию прямого вызова вместо щелчка мыши

Текст, отображающийся на месте рисунка при


Al terna teTe x t невозможности его загрузки или всплывающую

подсказку (генерирует атрибуг аl t тега < img> )


Задает реакцию Ho t Spot на щелчок мыши.
Переопределяет такое же свойство родительского

I mage Map . Если в HotSpo t установлено


HotSpotMode=Inacti ve , то этот HotSpo t
никак не реагирует на щелчки мыши. Они
HotSpo tM ode
применяются для частичного закрытия активных

зон при создании интеракmивносmи сложной


конфигурации. Закрывающий неактивный
HotSpot должен находиться впереди активного в

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


NavigateUrl URL перехода по щелчку мышью на HotSpot
в.м. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

Строка, идентифицирующая HotSpot среди


PostBackVa l ue аргументов события Cl i c k, п ередаваемая серверу
как одноименное свойство в объекте класса
I mage MapEventArgs
Определяет очередность получения фокуеа
TabInde x конкретного элемента среди коллекции HotSpot в

I mage Map
Виртуальное свойство, устанавливающее для
Target HotSpot окно и л и фрейм, КУда се рв е р должен
nриелать отклик на щелчек пользователя.

Приведем пример.

• ~Добавьте к nро екту в каталог lmages (из nрилагаемого каталога


Pictures) рисунок НоtSроt.рпg, который имеет следующий вид

230,51 280,51
зза , Б D

21 4,100 297,100

255,129 ЭО6, 155

0,219 177,219
320,241

• г;.:.='Добавьте к nроекту новую страницу с отделенным кодом и


именем MyImageMap . азрх . Заполн и те кодовую часть так

using System;
using System. Data;
using Sуstе m.Со пfigurаtiоп;
'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

using System.Collecllons;
using System.Web;
using Sуstеm.WеЬ.Sес шitу;
using System.Web.UI;
using System.Web.UI.WebContro ls;
using System.Web.UI.WebContro ls.WebParts;
using System.Web.UI.HtmJControls;

риыic рапial class MyImageMap : System Web. UI.Page


(
protected void Page_Load(object sепdег, ЕvепtAгgs е)
(
Ib! = new LаЬ еЮ;
fuгml.Contгo~.Add(Ib!);
IbLText := String.Empty;11 Очистили для трен ировки
Ilfопn1 . С о пtrо Is.Add( new Н tmlGenerk:Contro 1( 'Ъг''));

11 П одключа ем и настраиваем карту изображений


ImageMap imageMap := new ImageMapO;
imageMap.Enab)eViewState := false; 11 Отключили сохранение
11 состояния вида
imageMap.ImageUrl:= "~ llmagеslНоtSроt.рпg";
imageMap.AltemateText := 'Теометрич ес кий натюрмор т ";
imageMap.HotSpotMode := H o tSpo tМode.P ostВack;
11 Регистрируем два обработчика на одно событие
imageMap.Click += пеw Ima ge MapEve ntНandler(ima geMa p_ Click
imageMap.Click += пеw Ima ge MapEve ntНandler(ima geMa p_ Click:
form1.Controls.Add(imageMap );

11 Объявляем ссылки на горячие зон ы


RесtапgleНоtSроt rect;
РоlygопНоtS р о t star;
CircleHotSpot circle;

11 Создаем и настраиваем горячие зоны:


11 3везда
star := new po lygo nНot Spot();
imageMap.HotSpots.Add(star);
star.Coordinates:= ''255,0, 280,51, 336,60, 297, 100, 306,155,"

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

+ "255,129, 205,155, 214,100, 173,60, 230,51, 255,0";


star.PostВackValue := "зв езда";

// Описываем активный прямоугольник


rect:= пеw RесtапglеНоtSроtО;
rect.Left := О;
rect.Top:= 95;
rect.Right:= 177;
rect.Bottom == 219;
rect.PostBackValue = ' 'прямоуго льник'';

// Описываем неактивный частично закрывающий круг


CircleHotSpot cirShadow:= пеw CircleHotSpotO;
cirShadow.X == rect.Left + (rect.Right - rect.Left) / 2;
cirShadow.Y = rect.Top + (rect.Bottom - rect.Top) / 2;
cirShadow.Radius:= (cirShadow.Y - rect.Top) / 2;
cirShadow.PostBackValue = ' 'пустышка'';
cirShadow.HotSpotMode := НоtSроtМоdе.lпасtivе;

// Пустышка на переднем фоне , поэтому добавляем первой


imageMap.HotSpots.Add(cirShadow);
// Активный элемен т частично закрывается пустышкой
imageMap.HotSpots.Add(rect);

11 Круг
circle = new CircleHotSpotO;
image М ар. Н о tS pots. Add( circ le );
circle.X == 320;
circle.Y:= 241;
circle.Radius := 75;
circle.PostBackValue := ''круг'';

// Готовим фоновый пря моугольник для всей карты изображе


// Чтобы был фоновым, нужно в коллекцию добавлять после/
RесtапgleНоtSроt rectBack := new RectangleHotSpotO;
rectВack.Left := О;
rectВack.Top:= О;
rectВack .Right:=
395;
rectВack.Bottom:= 317;
m
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

image М ар. Но tS pots. Add (гectВac k);


rectВack.Po stBackValue == "фон";
}

// Первым зарегистрирован, первым и сработает


void imageMa p_Clickl(object sender, lmageMapEventArgs е)
{
if (e.PostBackVarue !:= "Фон ' )
IbLText :::: S tгing.Fоrma t(''Вы щелкнули на фигуре \"{ О} \"< Ьг >",
е .PostBackValue);
.Is.
IbLText := ''Вы прома зали!<Ьг>";
}

// Вторым зарегист рир ован, вторым и с р аботает


void imageMa p_Click2(object sender, lmageMapEventArgs е)
{
// Перестраховал ись только для тренировки,
// поскольку друго го элемента и не будет
lmageMap iшgМар := sender as lmageMap;
~ (imgМар == пиП)
геtшп;

// Печатаем список названии горячи х зон


for (int i := О; i < imgМар.НоtSроtS.С ОШ1t; i++ )
{
IbLText += String.Format("- {О} < Ьг>",
iшgМ ар. Но tS pots [Н. р ostBack Value );
}
}

Labellb~ // Для видимости в обработчиках объявили как поле


}

Листинг Код наложения на рисуно~ горячих зон в файле

MyImageMap.aspx.cs

Один И З откликов сервера на клиенте, есл и пользователь щел кн ет н а


пр ямоугольнике, БУдет выглядеть так
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

11 Untitled Page - Мicrоsоft Inteгnet Exploгeг


FMe Edlt V~W Fаvопtes Tools Нер

. Back т .. т 10 @1 GI ~ se"ch @J Favorites


.1037;WebSite lljМуImаg€Мар.зspх т

Вы щелкнули на фигуре "прямоуголышк"


- звезда
- ПУСThШIКа

- прямоуголышк
-круг

- фон

230,5 1 2ОО ,51


1 7 З ,во ЗЗб , 6 D

0, 95 177,95
2Н , 100 297,100

255,129 306,155
205,155

0,219 177,219
320,241

Обратите внимание, что разметочную часть страницы мы не


модифи цир овали, а все сформировали в ди на мическом режиме. Если
горячие зо ны должны частично закрывать друг друга, ВЮlючая

н еактивные зоны, то добавление объектов Ho t Spot в коллекц ию


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

HotSpots элемента упр а вленuя I mageMap долж но начинаться с

п ереднего плана по направлению к фону.

Задание для самостоятельного выполнения

Разработайте страниц)'; которая повторяла бы функциональность


рассмотренной нами ранее статической ст р аницы IшаgеМар. htm для
рисунка

(0 ,0) (162,0) (324,0)


- --+
1
Х

1 2
(0,94) 1-------'-
(1_6--'
2,'-94....:.)t--_ _ _-----i (324,94)

(0,188) (162,188) (324,188)

Срав ни те HTML-кod, сгенерованный активной ст р аницей, с HTML-


кодом статической страницы.

Расширение стандартного HotSpot

Ста ндартны еHotSpot MOryг генерировать только три разновидности


фигур:c ir cle , rectangle и polygon . Э то связано с ограничением
стандартного НТМL-дескрuпmара <area> , у которого атрибуг shape
может принимать только одно из тр ех знач е ний " circle ", " rect " ,
" роlу " . Однако на этой основе можно создать более сложные и
разнообразные фигуры , р асширяя соответствующим об р азом класс

,,,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

стан дартного HotSpot .

Рассмотрим при мер, в котором создадим расширение , способное


ге нерировать актив ный участок, сов п адающий с равнобедренным
треугольником. Модель треугольника описывается ц ентраль н ой точкой ,
шириной и высотой .

• IJ$С оздайте новую стр аницу с разделен ным кодом и им ен ем


ImageMapE xt . asp x
• ~3аполните кодовую часть следующим содержимым

usiпg System;
usiпg System.Data;
usiпg Systеm.Со пfigша tiоп;
usiпg System.Collections;
usiпg System. Web;
usiпg System. Web.Security;
usiпg System.Web.UI;
usiпg System. Web.UI. WebControls;
usiпg System. Web. UI. WebControls. WebParts;
usiпg System. Web.UI.HtmlControls;

public partial class lmageMapExt: System Web .UI.Page


(
protected void Page_Load(object sender, EventArgs е)
(
Ibl = new LаЬеЮ;
10 nnl .С о ntro Is.Add(1b 1);
lbLText :::: Striпg.Еmрtу;// О чи сти л и для тре ниро вки

// ПОДЮIюч аем и настраиваем ка рту изображений


lmageMap imageMap :::: new lmageMapO;
imageMap.EnableViewState :::: false; // ОТЮIючили сохра н е ни е
// состояния ви да
imageMap.lmageUrl :::: "~ /lmage srrriangleHotSpot. png";
imagеМар .н о tSро tМ оdе :::: HotSpotM ode.PostBac k;
// Регистрируем об р аботч ик события щелчка
imageMap.C lkk += new ImageMapEventHandler(imageMap_Clkk l);
fо пnl .Сопtrоls.Аdd(imagеМар );

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

11 Создаем горячую зо ну в форме тр еуголь ни ка


TriangleHot5pot triangle := new TriangleHot5pot();
image М ар. Н ot5 pots. Add( tria ngle );
triangle. Width = 200;
triangle.Height = 300;
triangle.X = 100;
triangle. Y:= 150;
triangle.Po stВackValue:= "гр еуголь ник";
}

Lab e llЫ;

VОЮ imageMap_Click1(object send er, ImageMapEventArgs е)


(
lbL Text = 5tring.Fопrnt(''Вы щелкнули на фигуре \"{О} \"<br>",
e.PostВackValue);
}
}

11 Для сохранения з нач е ний СВОЙСТВ используем словарь состояния вид


public class TriangleHot5pot: System.Web.UI.WebControls.HotSpot
(
public TriangleHotS potO
(
Width = Height = Х = у = О;
tШs.AltеmаtеТеxt:= ''Рав н обедренный тр еуголь ник";
)

11 Свойств а
public шt Width
(
get { геtшп (int)VIew5tate['Width'1; }
set { View5tate['Width'1:= value; }
}

public шt Height
(
get { геtшп (int)VIеw5tatе[''Неight'']; }

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

set { ViеwStatе[''Неight'1 = vallle; }


}

11 Координаты центральной точки треугольника


public int Х
(
get { rеtшп (int)ViewState["X'1; )
set { ViewState["X'1 = vallle; }
}

public int У
(
get { rеtшп (int)ViewState[''Y'1; )
set { ViewState[''Y'1 = vallle; }
}

11 3начение атри буга shape дескриптора <area >


protected override string MarkllpName
(
get { rеtшп "poly"; }
}

11 3начение атри буга coords дескриптора <area>


public override string GetCoordinatesO
(
11 Координаты верхнего угла
int topX = Х;
inttopY=Y- Height / 2;

11 Координаты левого угла


int IeftX = Х - Width / 2;
int )efty = У + Height 1 2;

11 Координаты п р авого угла


int гightX = Х + Width / 2;
int rightY = У + Height 1 2;

Stгing stг = S tгing.Foгmat(" (O), (l) ", toрХ, toр у);


stг += "," + Stгing.Foгmat("(O},(l}", IeftX, lefty);

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

str += "," + String.Format("{O},{l }", гightX , гightY) ;

return str;
}
}

Листинг Расширение стандартного HotSpot

Р енде ринг стра ницы будет следую щи м

11 Untitled Page - Мicrоsоft Iп ..


Fie Edit View Favorites

http:!~ocallOst

Равнобедренный треУТОЛЫ-fИК

'"'"
м

2 О

'"
В.М. С""",,,в Про,раммuрова Nue"aASP.NET

~T I@) ГJ ,
С не т'0$ /
- j (

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Работа с файлами и каталогами

Работа с файловой с ист емой. Классы Directory и File.

Файлы к лекции Вы можете скачать здесь скачать:

httр :l/оkl.iпtШ. ruld е р аrtmeпtJiпtеmеtJр rasp netJ 1 6/16.пр.


Требуется особая осторожность в прим енении рассматриваемых ниже
стредств , чтобы случайно не уничтожить н ужную инфор мацию на
Вашем компьютере!!!

Несомненно , база данных являются наилучшим способом хр анения


инфо рмации. Они обеспечивают достyn к данным большому количеству
пользователей одновременно и с максимальным быстродействием .
Такие данные , организованные в базу данных, н азывают
структурированными. Но иногда может потребоваться более простой
способ хранения информации, а также получение обзорных сведений о
файловой системе компьютера. Для таких случаев в библиотеке .NET
Framework имеется достаточное кол ич ество классов, которые можно
использовать как в локальных, так и в Web-приложениях. Познакомимся
с ни ми.

Работа с файловой системой

Простейшим уровнем файловых операций является получение


инфо рмации о файлах и каталогах, смена каталогов, получение
сведений о размерности файлов , времени создания , режиме достynа ,
удалени я , переименования , копирования и т.д . без их открытия. Для
этого имеются следующие библиотеч ны е классы пространства и мен
Sys tem . 10 ( i npu t , Ои tpu t ) сборки mscor lib . dll :

1. Directory, File - предоставляют статические методы для


сбора информации о файлах и катало гах локально го компьюте р а
или сервера

2. Drive1nfo, Directory1nfo , Fi l elnfo


пр едоставляют методы и свойства экзем п ляров для тех же ц елей

Вторая грynпа массов работает быстрее , поскольку выполняет проверку


безо па сно сти только однажды , при создани и экземпляра масса. Первая

,ее
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

группа не требует создания экземпляров , но выполняет проверку


безо п асн ости при каждом вызове метода .

Классы Directory и File

Эти массы имеют ст атические методы, приведенные в таблицах .


Если есть методы чтения Get , то есть и методы установки Set ,
которы е в таблице не указаны.

Некоторые методы класса Directory


Метод Описание

Создает катало г вместе с указан ны м


CreateD ir ectory()
пугем

Удаляет п устой каталог, если второй

необязательный параметр не указан или


De le te() равен false . Если второй параметр
указан и равен true , то удаляет катало г
со всем содержимым

Возвращает флаг существования


Exists()
катало га

Возвращают структуру Da teT ime ,


GetCreationTime() ,
которая содержит время создания
GetLastAccessTi me(),
каталога , время последнего чтения или
GetLastWriteTime()
за пи с и

Возвращает массив строк, по одн ой на


каждый подкаталог, файл или
устройство в указанном каталоге (в
GetDirectories(),
зависимости от используемого метода) .
GetFiles () ,
Методы мо гуг принимать второй
GetLogicalDrives()
параметр , задающий фильтр п оиска
(например , Му* . t хti Му???* ;
*Му.ехе; .. .)
Анализирует переданн ую строку и
GetParent() возвращает и мя родительского
каталога
В.М. С""",,,в Про'раммupoвtJNШ' 110 ASP.NET
Возвращает текущий каталог с пол ным
GetCurrentDirectory()
путем

Принимает два строки - исходный


каталог и целевой каталог с пол ными
путями. Перемещает исходный каталог
Move ( )
в указанное место в предела х одного

д искового устройства (иначе , -


копирует)

Возвращает объект со списком контроля


GetAccessContro l ()
до ступа Windows
Некоторые методы кл асса File
Метод Описание

Копирует од ин файл в другой с


возможной заменой существующего
Сору 11
файла (если задан третий
необязательный параметр true )
Удаляет указанный файл, но не
De l ete() возбуждает ИСЮIючение , если файл не
найден

Проверяет существование файла и


Exists()
возвращает флаг

GetAttr i butes() Возвращает атрибугы указанного файла

GetCreationTime() Возвращают структуру Da teTime,


GetLas t AccessTi me(), которая содержит время создания файла,
GetLas t WriteTime() время последнего чтения или записи

Перемещает или переименовывает


Move ( )
файлы

Create ()
Создают файл
CreateText()
Ореп(), OpenText()
Открывают файл , открывают только для
OpenRead () ,
чтения , открывают только для записи
OpenWrite ()
ReadAllText() Читают весь файл и возвращают его
ReadAllLines(), содержимое в виде строки , массива строк

ReadAllBytes() или массива байт


,ее
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Пишуг весь файл за один прием ,


WriteAIIText(),
использую принятую строку, массив
WriteAIILines()
строк или массив байт. Если файл
WriteAIIBytes ()
существует, то он перезапи с ывается

Возвращает объект со списком контроля


GetAccessControl()
доступа Windows

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Карты сайта

Определение карты саЙта. Декларативная привязка к карте саЙта.


Навигация с использованием мастер-страни ц. Программное управление
картой саЙта. Навигация с использованием фреймов.

Файлы к лекции Вы можете скачать здесь скачать:

httр :l/оkl.iпtllit.гuldераrtmeпtJiпtеmеtJргаsрпеtJ17 /17 .пр.

Навигация является необходимым средством пуг ешествия по сайту


Навигацию можно обеспечить разными средствами , но в ASP.NET 2.0
существует специализированное средство навигации с большими
функциональными возможностями - карты саЙта. Новая модель карты
сайта позволяет определить структуру навигации и связать ее с
пол нофункциональными элементами управления. Она существенно
упрощает задачу программиста по разработке и сопровождению гибких
средств навигации и состоит из следующих частеk

1. Файл Web.sitemap с описанием структуры навигации на языке XML


(как в базах данных: сами данные)
2. Элементы управления S i teMapDataSou r ce и

XmlS i teMapProv i der ДЛЯ преобразования описания

структуры навигации в объектную людель (как в базах данных:


поставщик и источник данных)
з. Элементы управления TreeVi ew, Мели и Si teMapPa th ,
непосредственно взаимодействующие с пользователем при
выполнении навигации (как в базах да нны х: элементы
отображения и редактирования данных)

Определение карты сайта

Описание структуры навигации следует начинать с создания карты


сайта, которая может быть представлена единств е нны м для
при ложения ХМL-файлом со стандартным именем Web . s i t emap .
Чтобы создать заготовку этого сайта , выполните следующее

• r;.:.=в пан ели Solution Ехрюгег выделите корень дерева сайта и


через контекстное меню вызовите мастер Add N ew Item.

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Установите шабло н в значение S i te Мар и щелкните на кнопке


Add
АМ ",",VJ Itpm - C·\Ch~ .. R(юk\WFА\дSP NFT? () R. r..t: (VS NFT 'ХЮ5)\ lб) С!"'/lCТRЯ НЯRИГ"'1 \ .lJ~
Т""'pJ""'"
Ii ; ,:::
ш! D _ с_ [!j] 00 !jj] ~ ~
I'iob For m м., , :е,- Pogo КП1.. Р ogo Wob S• ..,~e С ", ,, st'j lo SCe" t
ccrn-o l

,-&J,
"PP 1 ~a ~ ",
-
~
crnf l;JJa>J",
ВJ
~ F I Io ХМ-
illJ
sm.= То"
~
Fi"
~
ROЮ'JC . Fi» SQ.-
ij
Doi"""_

1m
Dазse t -~,
Н"....:Н"..

l!IiIII!I
1t!J'
M:tJr:e I'JOO
' ..m
~
\1\5(r"" F,:e
lf..i1
е_ ,
~
J5Cf1' ~ "е

.-
ri='"
Iд fi:.. LI>.ю !IJ cc~," ~
~
,"10 ~
,iJ!I IЭ
",- ф1 jjJ

~W I Web , ' i~
"?'
, • iJ г р """~
, sepзr&е Iе
Г ~~ ' WT""~

Оболочка создаст заготовку карты сайта с парным XML ~ deCKpunmOpoм


<s i teMap> . . . </siteMap> и вложенными дескрипторами узлов
<s i teMapNode> . Дескриптор <s i teMap> п одцерживается
одноименным массом Sys te m. Web . S i teMap , который
обеспечивает достyn к иерархическому п редставлению сайта для
выполнения навигации . З аготовка файла Web .sitemap будет выглядеть так

<?xml version="l .O" encoding=''utf-B ''?>


<siteMap xmlns= ''http ://schemas.microso ft. comlAspN et/S iteMap- F ile - l . О " >
<siteMapNode ш l="" title="" description="''>
<siteMapNode шl="" title="" descriptio n="" />
<siteM apNode шl="" title="" descriptio n="" />
</siteMapNode>
</siteMap>

После создания заготовЮ1 файла Web. sitemap ее н ужно правильно


скорректировать, чтобы она соответствовала структуре саЙта. При этом
н ужн о соблюсти два обязательных условия:
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

1. С айт д олж е н начинаться с одного Ю)рневого узла


2. Все узлы карты сайта должны иметь уникальные URL

От этого зависит пр ав ильн ая р абота класса-поставщика


XmlSiteMapProvider , Ю)торый непосредственно считывает и
расшифровывает информацию из файла Web.sitemap. Для считывания
инфо рмации из файла друго го формата потребуется д ругой
н естандартный п оставщик.

Корневой узел и все последую щие вложенные в него родительские


(раскрывающиеся) узлы иерархичесЮ) го дерева карты сай та должны
быть представл ены п арными дескрипторами <5 i teMapNode> ...
</s it eMapNode> . Листья дерева можно представить
самозакрывающимся (одиночным) дескриптором <5 i teMapNode> .

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


и ерархию стра ниц сайта неЮ)торой Ю)мпании по кате гор иям

Домой (Default. aspx)


То.ары (P ro ~UC\$ . ао рх)

А ппаратура (H. rdware.a.px)


П ро граммы (Software.aspx )
Услу ги (SeГV lces . aspx)
Обучение (Тг а iпiпg . аsр:х )

КоноультаЦИ\1 (Consuning.aspx)
П оддержка (SuppM .aspx )

• r;.:.=СЮ)рр ект ирУЙте заготовку файла Web .sitemap, созданного нами


р а нее , следующим образом

<7xml version= "1.0" encoding=''utf-8'' 7>


<siteMap xmIns=''http://schemas.microsoft.comlAspN etJSiteMap- РПе-1.0
<siteMapN ode url="~lDefauh.aspx " tidе="Д омой "
dеsсгiptioп=' 'Корневой узел (домашияя CTP ~
<siteMapN ode url="~lP roducts.aspx" title='TOBa pbI "
dеsсгiptioп=' 'Что мы продаем">
<siteMapN ode uгl="~ lНагdwаге.аsрх" tide="AnnapaTyp
dеsсгiptioп=' 'Компьютеры и комплектую щи
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<siteMapNode url="~/Software.aspx " tidе= ' Программы


dеsсгiptio п=' Программное обеспечение кш.
</siteMa pN ode>
<siteMapNode url="~ /Servk:es . aspx" title= "Услуги "
dеsсгiptio п=' 'Наши услуги' '>
<siteMapNode url="~!Гraining.aspx" title='Обучен и е"
dеsсгiptio п="Обучение nрограммированию
<siteMapN ode uгl="~/С опsulting.аsрх" titlе=''Ко н сультаl
dеsсгiptio п=' 'Консультации по эксnлуатаЦИ I
<siteMapN ode url="~/S upport.aspx" tit1е =' Подцержка "
dеsсгiptioп=' Помощь в сопровожде нии nр е
</siteMa pN ode>
</siteMapN ode>
</siteMap >

Листинг Пример определеНИА карты сайта в файле

Web. si temap

ДекларilТИВНая привязка к карте сайта

Создание в приложении файла Web.sitemap в корне виртуального


каталога автоматически инициирует запуск поставщика

XmlSiteMapProvider . Его задача заключается в uзвлеченuu данных


карты сайта и заполнении этими да нными экземпляра класса
Si teMapDa taSource, который далее можно подключать для
генерации HTML -кoda отображения карты сайта к таким элементам , как
Мели, TreeView и SiteMapPath . Технологическая цепочка
извлечения и отображения да нных об иерархии страниц сайта
nриведена на рисунке
в м С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Определ ение К 8 РТ Ы С8 йта во


фа й пе -lWеЬ.si1еmар

!
Иэan ечение Да н н ых иЗ файла
web.sitemap с помо щью
п остав щ ик а XmlSiteМapP rovider

!
заполнение постав щ ико м
XmISiteMappro . . .ider обьекта
ИСТО Ч НИl(а дан., ы:х

SiteмapDataSOurc.e

!
Эл еме нты уп~anен и я Мenц,
TreeView, SiteMapPath для
генерации НТМL, отобр;э жен l.tЯ
ка рты сайта на стороне клиента

Навигация с использованием мастер-страниц

Реализуем эту цепочку ДЛЯ нашего прим ера, в котором ДЛЯ организации
меха ни зма навигации применим мастер-страницы.

• r;.:.=через контекстное меню панели Solutlon Explorer добавьте к


корню Web-дерева сайта п а пку с им е н ем Maste r Pages , в
которой разместим ша блон ДЛЯ страниц , определяемых
пар аметр омURL узлов дерева карты сай та
• ~ыделите папку MasterPages и добавьте в н ее фай л
MasterPage.master коман д ой Website/Add New Item, сбросив фrJажок
создания файла отделенного кода

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

.lJ~
Т""1""»>
Ii ; ,:::
ш!
• _ с_ [!j] 00 !i ~ ..
~
I'lob Form "#М4 КП1..Рogo Wob S• ..,~e С",,, stj i< SCe" t
ccrn-o l

&J
с _,

"PP 1 ~a~ ",

Ц'Jj
-
~
crnfgJa:I",
~
:>o:M-F,Io X~
h'iJ
Schoma
~
То" Fil2
]j
R о=.л: о Fi'"

.
ij
SQ.- о..:..Ь=

Dазset -~,
flrd iof
i.I1I
5<00 M~
1t!J'
M:tJt:e I'Jeb
' ..m
o'!'l
\1\5(r"" Н е
~
,_ о
~
J5Cfp~ "е

Iд м",,/о< P"J" fo-lМ>b A~ l t.tbrr>


~W "I~~'~
~~'~
,"~.m~'
~b~----------------------------CI

iJ Г Рlio:есWэ r1 "1Нае fi lo
Г Ч>..-t 'wr е

СЛ:eI 11

• ~3аполните мастер-страницу MasterPage.master следУЮЩИМ


КОДОМ

<%@ Master Language="C#" % >

<script runat= "server''>

protected void Page_lnit(object sender, EventArgs е)


{
if (Session["index"] != null)
{
// Восстанавливаем состояние радиосписка
RadioButtonListl.Selectedlndex = (int)Sе ss юп[ "indех"];
)
.Is.
{
RadioButtonListl.Selectedlndex = О;
}

Se lectedlnd exC hanged(null, EventArgs.Empty);


}
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

protected void Selected IndexC hanged(obj ect sender, EventArgs е)


{
if (RadioButtonList1.SelectedIndex == О)
{
TreeView1.VlSible = true;
Menu1 .VlSible = fal5e;
}
.Is.
{
TreeView1.VlSible = fals e;
Menu1 .VlSible = true;
}

// За помина ем состояние радиосписка


Session["index"] = RadioButtonList1.SelectedIndex;
}

</script>

<html XmInS= ' huр ://www.wЗ.or!j'1999/xhtml' '>


<head runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="form1" nmat="server''>
<div style=''text-align: center">
<h1 style="colo r: Red''>
Прим ер использования ка рты сайта
<1h1>
<table border= "1" width= "1 00% ''>
Чг>

<td colspan=''2'' style=''text-align: center; background-color: Sil


<!-- Сюда помещаются элементы ynравления навигаu
<asp:SiteMapPath ID="S iteMap Path1 " runat= "server">
<CurrentN odeTemplate>
<i>< b style="co lor: Blue">
<asp:Label ID='1.abel1 " runat="server"
Text='<%# Eval(''tide'') % >'>
,ОС
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</asp:Label>
< Ii>< /Ь >
</С uпепtNоdеТеmрlatе >
</asp:5 iteMa pPath>
</td >
</tr>
Чг>

<td style=''width: 25 0р х; vе rtk:аl-аligп : top; background-colc


<!-- Сюда помещаются элеме н ты управления навИI
<asp:TreeView ID='TreeViewl " runat="selVer"
5 е lectedN od е 5 tyle- Font- Во k:l = ''true''
5 е lectedN od е 5 tyle- F ont- 1talic= ''true''
Dаtа 50шсе ID="5itеМа рDа ta 50шсеl" />
<asp:Menu ID='Menul " runat="server" Orientation='Hor
DynamicMenuItem5 tyle- ВасkСоюг= ''Yellow''
Dаtа 50шсе ID="5itеМа рDа ta 50urсеl" />
</td >
<td stуle='''е rtiса l-а ligп: top ; background-color: Aqua''>
<!-- Сюда помещаются стр аницы , подгружаемые п<
<asp:ContentPlaceHok:ler ID="ContentPlace Hok:lerl " run
</td >
</tr>
</table>
<asp:5iteMapData50urce ID="5 itеМарDаtа50шсе 1" runat="sen
< Ьг />
<asp:RadioButtonList ID=''RadioButtonListl '' runat="server" Autc
О п5 е lected IndexC ha nged = "5 е lected IndexC hапgеd
Border5 tyle= "5 о lid" Во rderC о 10 г= ''Red ''>
<asp:ListItem> Использовать Тгее View</asp:ListItem>
<asp:ListItem> Использовать Мепu</аsр:ListItеm>
</asp:RadioButtonList>
</div>
</fonn>
</body>
<lhtml>

Листинг Код мастер - страницы MasterPaqe.master

в при веденном ша блоне мы о пр еделил и заголовок и таблиц)';


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

состоящую из д вух строк и двух столбцов. С тол б цы верхн ей строки мы


объединили и поместили в н ее элеме н т S i teMapPa th отоб р ажения
пуги и т екущего положения пользователя из вкrJaДКИ Navigatio n панели
Toolbox.

В левом столб ц е табли цы мы разместили элемен ты отображения карты


сайта и упра вл ения навигацией TreeViewl и Menul из вкладки
Navigation п а нел и Toolbox. В право м столбце мы за резерв иров ал и место
для загрузки стра ниц с содержим ы м, которые по атр и бугу
Con ten tP l aceHolde r 1 D дескриптора

<asp:Content ID="Contentl " ContentPlaceHok:lerID="Co ntentPlaceHok:lerl " RI

</asp:Content>

будуг ссылаться на это место.

Вслед за табл ицей (или в любом другом мест е) мы разместили


н еот об р ажаемый объект источника данных S i te MapDataSource l.
который привязали к элеме н там TreeV i ewl и Menul через его
свойство Dа taSou r ce 1 D. Ниже разместили с пи сок радиокнопок,
ч тоб ы дать возможность пользователю мен ять элеме н ты навигации.
Сво йс тва столбцов таблицы настроили так, чтобы содержимое
размещалось с самого н ачала, а в верхней стр оке - по среди н е.

В резул ьтате получится такой внеlШlИЙ вид ма стер-стран ицы в режиме


Des i gn

'"
в м С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

.... MasterPages/MasterPage.master I ~ Х'

.=J
Пример использования
~

карты саита
ffi
I itootNode > ParentNode > Curreni Node -.J
[lI:l в домой Content:PlaceНoldeг -
8 Товары Content:PlaceНokjeг 1

Аппаратура
ПРО'РаАIМЫ
8 Услуги
Обучение
Консультапин
По.ц;а:ержка

r
омой


lSlteМapDataSource - SiteM~ataSource 1~

r Использовать Tree View


("' Использовать Menu

в блоке скри п тов мы орга ни зовали механизм сохра н е ни я состояния


списка между сеан с ами приложения , а также механизм смены

элементов навигации . Как только мы один из элементов навигации


скрываем , он перестает ге н ерировать соответствующий HTML-кod. В
шаблоне Cur r entNodeTe mpla t e элемента S i teMapPath мы
связали текстовую метку Label с атрибугом t i tle т екущего узла
карты сайта , опред еленной в файле Web.sitema p.

Теп е рь н ужн о создать сами страницы с содержимым , п одгружа е мым


совместно с шаблоном п о щелчкам на узлах де рева карты саЙта.

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• ~ панели Solution Exp lorer щелкн и те правой кнопкой мыши на


шабло н е MasterPage.master и выполни те коман ду кон текстного
меню Add Content Page, чтобы создать за готовку страницы
содержимого Default.aspx. Повторите это действие , чтобы создать
8 за готовок таких страни ц
• r;:;nрисвойте этим страницам и мена согласно ХМL- файлу карты
сайта Web . s i temap :

1. De f au l t . азр х
2 . Produc t s . asp x
з. Hardware . asp x
4 . So f tware . asp x
5. Services . asp x
б. Train i ng . азр х
7. Consul t i ng . asp x
8 . Suppo rt . азр х
• Г;;:;=Отредактируйте содержимое созданных заготовок страниц
следУЮЩИМ образом
Пр и мерное напол н ен и е страниц содержимо

<%@ Page Lа пguagе="С#" МаstегРаgеFilе="~lМаstегl


1ide=''Untided Pa ge" %>

<аsр:Со пtепt I D=''Сопtепtl'' nmat="Server"


Default.aspx
С опtепtР \асеН о Иег ш = "С onte ntP \а се Н о lder 1 '~
Э ТО содержимое начальной (домашней) стр аниu
где расположен титульный лист и Apyrne ' 'приб с
< /аsр:Сопtепt>

<%@ Page Lапguagе="С#" МаstегРаgеFilе="~lМаstегl


1ide=''Untided Page" %>

<аsр:С опtепt I D="Сопtепtl" nmat="Server"


Products.aspx
С опtе пtР \асе Н о Иег ш = "С onte ntP \а се Н о lder 1 '~

Э ТО содержимое страницы Products.aspx,


где расхваливаются товары, которые мы продае,

< /аsр:Сопtепt>

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<%@ Page Lапguagе="С# " МаstегРаgеFilе= "~ lМаstегl


1idе='Uпtidеd Page" %>

< аsр:Сопtепt ID="Сопtепtl" nmat="Server"


Hardware.aspx СопtепtРlaсеНоk:lегID= "СопtепtРlaсеНоldегl'~
Это содержимое страницы Hardware.aspx,
где перечислены компьютеры и комплектующие

которыми мы торгуем (спекулируем)


</аsр:Сопtепt>

<%@ Page Lапguagе="С# " МаstегРаgеFilе= "~ lМаstегl


1idе='Uпtidеd Page" %>

< аsр:Сопtепt ID=''Сопtепtl '' nmat="Server"


Software.aspx С опtепtР IaceH о Иег ш= "С onte пtР lace Н о lder 1 '~

Э то содержимое страницы Software.aspx,


на которой мы расхваливаем программное обеCI
сворованное у других, но выдаваемое за свое

</аsр:Сопtепt>

<%@ Page Lапguagе="С# " МаstегРаgеFilе= "~ lМаstегl


1idе='Uпtidеd Page" %>

< аsр:Сопtепt ID=''Сопtепtl '' nmat="Server"


С опtепtР lace Н о Иег ш= "С onte пtР lace Н о lder 1 '~
SeIVices.aspx
Э то содержимое страницы Services.aspx,
на которой мы хвастаемся , что все можем и
в беде не покинем, а сами только и думаем ,
как бы обобрать до нитки
</аsр:Сопtепt>

<%@ Page Lапguagе="С# " МаstегРаgеFilе= "~ lМаstегl

1idе='Uпtidеd Page" %>

ее,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<asp:Co ntent ID="Content l " nmat="Server"


Тгаiniпg. аsрх С ontentP \асе Н о Иег 10= "С onte ntP \асе Н о lder 1'~
ЭТО содержимое страницы Тгаiniпg.аsрх,
на которой мы популярно объясняем для невеж,l
почему ЗеМЛЯ квадратная

</asp:Content>

<%@ Page Language="C#" MasterPageFile="~lМasterI


1ide=''Untided Page" %>

<asp:Content ID=''Content l '' nmat="Server"


Соnsultiпg.аsрх
С ontentP \асеН о Иег 10= "С onte ntP \асе Н о lder 1'~
ЭТО содержимое страницы Consulting.aspx,
где мы проводим консультации с наurn:ми Юlиен~

</asp:Content>

<%@ Page Language="C#" MasterPageFile="~lМasterI


1ide=''Untided Page" %>

<asp:Co ntent ID="Contentl " nmat="Server"


Support. aspx С ontentP \асе Н о Иег 10= "С onte ntP \асе Н о lder 1'~
ЭТО содержимое страницы Support. aspx,
на которой мы оказываем подцержку в сопрово)!

программного обеспе ч ения


</asp:Content>

• ~ п а н ел и Solution Ехрюгег п еремести т е созданные файлы


содержимого из каталога MasterPages в коре нь сайта
• ~Запусти те приложе ни е и и с п ы тайте е го функц и ональ н ость

Резул ьтат для двух вар и а н тов БУдет пр имерно таким

ее,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

~) untitled Page - Мicrоsоft Internet Explorer


--.....;...;

~
iI€ Edt View Favaites Tods 1-ie\J
..:-. Back .- ...... о. @J с:! \f\ sea-ch Ш FаVСХites @j rvвia

1:1 http:/;'осзhхt: 10 35(WebSite lб/ссп:;Liti-q ,зspх


Ado::t-ess 1

При мер использования


карты сайта
Домой > Ус > Консульm(Щuu
а Домой то содержимое стршпщы:

~ TOBapы Consulting.aвpx, где мы npоводим


AшIаратура онсулъТЗЦJШ С нarrш:ми

Программы ентами

8 Услуги

ОбучеЮ!е
Консультации
Под,.цержка KOrf: JЬтацж m экm атации

го Использовать TreeView
r Использовать Menu

11) http:/;Ьсst-юst: 1О35JWеЬSitое16/СonsU~,З$РХ п ггr~ Loc' "",се!

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

~) untitled Page - Мicrоsоft Internet Explorer


- -.....;...;

~
Ie E,jt VI€W Favaites Tods 1-j.Ф
..:-. Back .- ...... о. @J с:! \f\ sea-ch Ш FаVСХltes @j rvвia
Ado::t-ess Il:J http !;'осзhхt 1О3s!WеЬSitеlб!СcпsLiti-q.LpХ

При мер использования


карты сайта

> содержимое стрamщы:

~ ~~~~~::~гд
: e
: МЫ
::~::
( B
~ ~
' ~:]
слуш • Обучение с нaпmми
Консультации

КОНСУ JЬТ3..\ Ж го эr::с атацVlfl

r Использовать TreeView
со" Использовать Мепп

li(j http:/;bcshJst: lОЗSJWеЬSit",16/Сorrзu~ ,Э$РХ пггr~ (оса п"","

Элеме н т Si teMapPa th удобен для отображения текущего положения


пользователя в иерархической ц е поч ке, а также для быстрого
n еремеще ни я вверх к корневому узлу. Но для возможности nеремещения
вниз по иерархии карты сайта е го все гда нужно комбинировать с
другими элементами ynравления навигацией. Вот некоторые свойства ,
влияющие на внешний вид элемента Si teMapPa th

Некоторые свойства масса SiteMapPath


Свойств о Описание

Устанавливает длину отображаемой


и ера рхич еской цепочки. По
ParentLevelsDisplayed умолчанию равен - 1, означающий,
что будуг nоказаны все родительские
узлы

Устанавливает порядок ото бражен ия

ее,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

узлов:

• Roo tT oCu rren t - слева

на пр аво от Ю)р н ево го к


PathDirect i on
т екущему

• Cu rren tToRoot - слева

н а пр аво от текущего к

Ю) р невому

О п ределяет раздели тел ь между


отоб р ажаемыми узлами. П о
PathSeparator
умолчанию равен с и мволу" >"
(больше)

При включе ни и в значение t rue


RenderCurrentNodeAsL i nk отоб р ажает текущий узел как
2uперссылку

Отключ ает всnлывающuе подсказкu


н ад узлам и ие р архичесЮ)й ц е п очки ,

о п ределяем ы е з н ач ениям и атр и буга


ShowToo 1 Tips description в о п иса ни и узлов
файла Web.sitemap. По умол ч анию
и меет з н ач ение true -

всплывающие подсказкu включ ены

Прог раммное управлени е картой сайта

Как мы знаем, узлы карт ы сайта имеют, в том числе, свойства Ur 1 ,


Ti tle и Description. И ме нн о эти основные свойства и создает
мастер оболочки в файле Web.sitemap. Есл и узел и меет атрибуг Ur 1 , то
пользователь щелчЮ)м на н ем может п ереходи ть к связа нн ой стра н и ц е .
Если в каЮ)м-то узле атрибуг Ur 1 о п устить, то узел по-преж н ему будет

отоб р ажаться в иерархии дерева, но не бу,цет действовать как


2uперссылка.

До сих п ор мы р ассматривали взаимодействие с картой сайта без Ю)да .


Но это взаимодействие можно осуществлят ь и пр о грамм н о. В классе
Si teMap , п редставляющем карту в ц елом, ос н ов н ые статические

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

свойства Roo t Node и CurrentNode содержат ссылки на корневой и


текущий узлы карты сайта как эюемпляры масса Si teMapNode .
Любой д ругой произвольный узел, например , ' 'Ко н сультации '', можно
н айти по его URL таким кодом

SiteMa pN ode find Node := SiteMap.Provider.FindSiteMa pN оdе(' ЧСоns uhing.а

Далее с помощью свойств


ParentNode , Chi1dNodes ,
Ne x tS i bl i ng и Prev i ousSibl i ng эюемпляров масса

Si teMapNode можно получить прorраммный достyn к соседн им


узлам иерархии карты саЙта.

Некоторые свойства масса SiteMapNode


Свойство О пи са ни е

С одержит ссылку на родительский п о отношению к


РагепtN ode текущему (най ден ному) узел. В корневом узле
возвращается nu 11 - ссылка

ChildNodes С одержит ссылку на коллекцию дочерних узлов

Б улево свойство, возвращающее t r ue , если узел имеет


HasC hild Nod es
дочерние узлы, и н аче, fa1se , если этолuст дерева

Возвращает ссылку на предыдУЩИЙ узел того же уров н я


(родственный узел) , иначе n u 1 1, если этот узел
РгеviоusSibliпg
единстве нн ый. Родственными называются узлы ,
имеющие одного и того же родителя

Возвращает ссылку на следующий родствен н ый узел,


N extSibling
иначе n u 11 , если этот узел еди н ственный

На п ример , следующий об р аботчик щелчка кно п ки можно использовать


для п е рехода к странице , связанной с родительским , по отношению к
текущему, узлом

Res ропsе .Redirect(S ite Мар . С шгепtN od е. Р агепtN ode. Url);

Для примера модифицируем наше приложение так, чтобы динамически


извлекать инqюрмацию из текуще го узла карты сайта и отображать ее на
странице .

,ОС
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• IJ$Добавьте в мастер-странице MasterPage.master к таблице


cBepJO' еще одн у строку с объед иненными столбцами и размести те
в ней последовательно д ве текстовых метки Label с им е на ми
lblT i tle и lblDescription . Код этого фрагм е нта будет
таким

<tr>
<td colspan=''2'' style=''text-align: center''>
<asp:Label ID="lbrгn:1e " runat= "server" 1>
: &nbsp;
<asp:Label ID="lblDescription" nmat= "server" 1>
</td >
</tr>

• r;:;='Добавьте в мастер-странице MasterPage.master к таблице


снизу еще одн у строку с объединенными столб ца ми и размести те
в ней по следовательно два элеме н та LinkButton с им е на ми
lnkPrevious и lnkNe xt. Код это го фр а гмента БУдет таким

<tr>
<td colspan=''2'' style=''text-align: center''>
<asp:LinkButton ID=''lnkPrevious'' runat= "server" Text="< Назад " f;
&nbsp;&nbsp;&nbsp;
<asp:LinkButton ID=''lnkNext'' runat= "server" Техt= ' 'Вперед >" 1>
</td >
</tr>

• ~Добавьте в блок скриптов следУЮЩИЙ код

protected void Page_ Load(object sender, EventArgs е)


{
II Информация о текущем узле
Ibmde.Text = SitеМар.С шге пtNоdе.Тidе;
IbIDescription.Text = S iteMap. C urrentN ode .Description;

II Управлени е кнопкой ''Назад''


if (SiteMap. CurrentNode.PreviousSibling! = пulI)
{
InkPrevious.PostBack Url = S iteMap.CurrentN ode .PreviousS ibling.l
ее,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

IпkРrеviо us. ЕпаЫе d = true;


}
.Is.
IпkРrеviо us.ЕпаЬlе d = fa lse;

// Управл ен и е кнопкой ' 'Вп е р ед''


if ( S itеМ а р. С urrе пtN оdе .N еxtSibliпg ! = пull)
{
Iпk N еxt . Р оstВас kUrl = s itеМар . С urrепtN ode.N еxtS ibliпg. U rl;
IпkN еxt . ЕпаЫеd = true;
}
.Is.
Iпk N еxt . ЕпаЬled = fals e;
}

• u;.;rЗа п устите прилож ени е и убедитесь, чт о появи л ась н о в а я


функциональн ость и вс е ра бота ет!! !

Ин те рфей с пользова теля после новы х и зме н е ний БУдет таки м

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

~) untitled Page - Мicrоsоft Internet Explorer


--.....;...;

При мер использования


~

карты саита

КонсультaцIШ: КонсультaцIШ по эксruryатaцIШ

дОМОЙ > Услуш > КOIц:ультацuu

в ДОМОЙ то содержимое страницы

~ TOBapы Consu1ting.aspx, где мы прово


Аппаратура онсультации С Hanm:мн

Программы ентзми

о Услуги
ОбучеЮIе
Коnсульmацuи
По,цдержка

< Назад Вперед >

r. Использовать TreeView
r Использовать Мепп

Навигация с использованием фреймов

Для пользователей, броуэеры которых подце рживают фреймы ,


организовать ийвuгацuю можно иным способом. Фреймы позволяют в
одном окне броузера отобразить с р азу не сколько самостоятельных
НТМL-до кумен то в , размещенных в отдельных файлах. И мен н о поэто му
они очень удобн ы для создания нави га ционной п ан ел и саЙ та .

Стра ница , которая БУдет размечена фреймам и и отображать до ч е рние

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

документы , на зывается ynравляющеЙ. Чаще всего она является


шаблоном , не содержащим своего отображаемого текста. Механизм
фреймов подце ржива ется большинством современных броузеров и
относится к чистому НТМL. Некоторые элементы кодирования фреймов
прив едены в таблице

Некоторые элементы кодирования фреймов

Элемент Описание

<frameset> Определяет число фреймов и их размеры. Он дели т


окно броузера или фрейм (в случае вложенных
</frameset> фреймов) на строки и столбцы

Атрибуг дескриптора <frameset> . 3адает число


строк в броузере и ли фрейме (в случае вложенных
фреймов) для размещения фреймов, а также их высоту
Возможные варианты деления:

• Цело е число - интерпретируется как количество


nикселов

• Цело е число с символом %- интерпретируется


как проц е нты от разделяемой области
• Символ * - ин терпретир уется как оставшееся
rows прос транство

• Цело е число с символом * - интерпретируется


как оставшееся пространство с весом

Например, код <frameset rows"""70, 20 %, *


2* " > ... </ frameset> определяет в окне4
строки сверху вниз: первая строка будет высотой 70
nикселов; вторая займет 20% свободной области ,
оставшейся от первой строки; п оследние две строки
поделят остальное в пропорциях 1/3 и 2/3
соответств е нно

Атрибуг дескриптора < frameset> . По аналогии с


атрибугом rOW$ дели т область на столбцы и
cols определяет их размеры в порядке следования в списке

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

слева направо

Необязательный атр и буг дескриптора < framese t>,


frameborder который определяет наличие рамки в до ч ерних
фреймах. Принимает значения" уе s " или" по "

Дескриптор, дочерний для <frameset> , и


<frame> о пр еделяющий содержимое текущего фрейма. Н е
имеет закрывающе го дескриптора .

Атр и буг дескриптора <frame> . Определяет URL


src
отображаемого в текущем фрейме докуме нта.

Атр и буг дескриптора <frame> . Определяет имя


фрейма для ц елевой за гр узки в н его н ового докуме нта,
адресуемо го щелчком пользователя в управляющем

докуме н те на ссылке с до пол нительным атр и бугом


target . Если ссылка н е содерж ит ат ри буга targe t,
то новый документ загружается во фрейм, где б ы ла
па т е рас положена ссылка. Есл и все ссылки на
управляющей странице долж ны выводить адресуемые
докуме н ты в одном и том же фрейме , то вместо
добавлен и я атрибуга ta rge t с одинако вым
з нач ением в каждую ссылку можно в р аздел <head>
страни цы , где содержатся ссылки , добавить
дескриптор <base tаrgеt= " Имя фрейма " >

Атр и буг дескриптора <frame> . Управляет


видимостью п олос пр округки . Может иметь
следУЮщие значения:

• scrolling= " auto " - автомати ческое


появл е ни е полос п рокругки , если содержимое

scrolling докуме н та не помещается в фрейме. При


отсугствии атрибуга это режим по умол чани ю
• scrolling= " yes " - полосы прокрутки

при сугствуют п остоянно

• scrolling= " no " - полосы прокрутки н е

по являются даже при необходимости

Атр и буг дескриптора <frame> . Наличие это го

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

noresize атрибуга запрещает пользователю изменение размеров


фрейма посредством интерактивного перетаскивания
границ

Дескриптор, не имеющий атрибугов. О н ВЮlючает в


себя ко н тейнер <body> . .. </ body>, внугри
<noframes> которого может содержаться альтернативный текст
или 2uперссЬ/лки на случай, если броуэер пользователя
</no frame s> не поддерживает фреймы. Для броуэеров,
подцерживающи х фреймы , содержимое дескриптора
не отображается

Прив едем примеры.

< ШОСТУРЕ НТМL PUBLIC "- /IWЗС/IDТD НТМL4.01 FгameseUIEN" 'I1n]


<html>
<head >
<title>Untitled Document</title>
< mеы http -еquiv="Со пtе пt-Туре" content=''textlhtml; charset=windows-1251 ">
<lhead>

<frameset rows="70%, *">


< frашеsеt cols="*, *, *''>
<frame src =' 'Docl.htm'' name="Framel" scrolling=''no'' noresize>
<frame src =''Doc2.htm'' паmе='ОРгате2" scrolling="auto''>
<frame src =' 'Doc3.htm'' name="Frame3" scrolling="auto''>
</frameset>
< frашеsеt cols="*,*">
<frame src =''Doc4.htm'' name="Framel" scrolling=''no'' noresize>
<frame src =''Doc5.htm'' name="Frame2" scrolling="auto''>
</frameset>
</frameset>
< поfrашеs >
<body>
<lbody>
</noframes >
<lhtml>

Листинг Пример 1 управляющей НТМL -с траницы с фреймами


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

11 Untitled Document - Мicrоsоft Internet Explorer


Fie Edit View Favorites Tools Нер

Back . . . . ID @] (:1f ~ S€"ch t±J Favorites ~ Meaa


:\Tmp\DocFrameset.htm .... rPGo

Страница 1 Страница 2 Страннца 3

Страница 4 Страница 5
Computer

Р езул ьтат в ып ол н е ни я П р и ме р а 1

< !DO CТYPE НТМL PUBLIC "- /IWЗС /IDТD НТМL4.01 FгameseUIEN" 'I1n]
<html>
<head >
< titlе>Uпtitled D осumепt </titlе >
< mеы http -еquiv="Со пtе пt-Туре" content=''textlhtml; charset=windows-1251 ">
</head>

<frame set cols="55%, *''>


< frаП1еsе t rows=''*, *, *">
<frame src =''Docl.htm'' паmе="F гаmel " sс rolling=''по'' пorеsize >
<frame src =''Doc2.htm'' паmе=''Fгаme2'' scrolling="auto ''>
<frame src =''Doc3.htm'' паmе="Fгаme3" scrolling="auto ''>
</frameset>
< frаП1еsе t rows=''*, *''>
<frame src =''Doc4.htm'' паmе="F гаmel " sс rolling=''по'' пorеsize >
<frame src =''Doc5.htm'' паmе="Fгаme2" scrolling="auto''>
</frameset>
</frameset>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

< поfrаmes >


<body>
<Jbody>
< /поfrаmes >
</html>

Листинг Пример 2 управляющей НТМL - страницы с фреймами

11Untitled Document - Мicrоsоft Internet Explorer


---------------------------------
FMe Edlt V~W Fаvопtes Tools Нер

Back т .... 10 l1J GI ~ se"ch ш Favorites (jjJIMeda


:\Tmp\DOcFrameset,htm .. !fi'GJ

Страница 1 Страница 4

Страница 2
Страница 5
Страница 3

Оо,", Computer

Результат выполнения При мера 2

Приведем пример использования фреймов в создании нави гацио нн ой


панели сайта для случая неактивной НТМL- ст р аницы.

• r;:;'вызовите для корневого узла проекта ко н текстное меню и


командой Add New ltеmдобавьте к про екту (шаблон НТМL Page ) 4
НТМL - стран ицы содержимого с и менами
о Docl . htm
о Doc 2 . htm
о DOC 3 . htm
о Doc 4.htm
• r;.:.=п ОДПИlllИте эти стран ицы соответствующим текстом в их
'"
в.м. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

де скрипторах <body>
• Г;;:;n одоб н ым же образом создайте страницу с имен ем
Na v i ga te . h tm , содержащую ссы л ки на ст р аницы содержимого,

и за п ол ни те ее следующим кодом

<html xmIns= ' huр ://www.wЗ.or!j'1999/xhtml" >


<head >
<tide >Untitled Page</tide>
<lhead>
<body>
<h1 align="center">
Навигационная панель < lhl >
<table border= ''O '' width="100%''>
<tr>
чЬ>
<а href=''Docl.htm'' target=''DocView''> Документ 1 </a>
</th>
чЬ>
<а href=''Doc2.htm'' target=''DocView''> Документ 2 </a>
</th>
чЬ>
< а hrеf=''Dос З .htm'' target=''DocView''> Документ 3 </a>
</th>
чЬ>
<а href= ''Doc4.htm'' target=''DocView''> Документ 4 </a>
</th>
</tr>
</tabIe>
<lbody>
<lhtml>

Листинг. НТМL -код файла Navigate.htm


• Г;:;=С оздай те в корне виртуального каталога н овую ynравляющую
НТМ L · стран ицу с и менем FramesCont r o l. htm дл я
размещения фреймов , назначьте ее стартовой и заполни те
следУЮЩИМ кодом

<html>
<head >
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<tide >Untitled Dосuшепt</title >


<meta content=''textlhtml; charset=windows-1251" http -еquiv="Со пtеn
<lhead>

<frameset гоws="ЗО%, *">


< frаше паme =''F гашеl ''
scrolling="no" src="Navigate.htm''>
< frаше
name=''DocView'' scrolling="auto " src=''Doc l.htm''>
</frameset>
<lhtml>

Листинг. НТМL - код страницы FramesControl.htm


• ~Запустите страни цу и получ ите ~ующий ~ультат""....,.~o;'il
-::1 Untitled Document - Мicrоsоft Internet Explorer
FIe Ecit Vf€w Favorites Tools нер

Ada-ess 1.

Навигационная панель

До"'умент 1 До"'умент 2 До"'умент 3 ДОIo;:умент 4

Документ 3

Г-Г-Г- I Loca Iп!тmеt


в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• ~дали те в документе Navigate.hUn атрибyrы


target , а в
заголовоч н ой ч асти эт ой же страни цы Navigate. hUn доб авьте
де скриптор <Ьазе target= " DocView " > . Убедитесь, чт о
навигация ра бота ет без изм ен ений

Теперь, когда мы по з нако м или сь с фреймами , на стала пора исп ол ь зов ать
и х в совокупности с картой саЙта. Мы не будем с и л ьно усложн ять
задачу и готовить дл я сс ы лок новы е страницы. Вос п ользуемся
готовыми стр а ница м и , которые ранее о пр едел или в файле Web.sitemap.
Р езул ьтат будет немного н еказисты м, но вполн е пр оиллюстрирует
испол ьз овани е фр еймов .

• IJ$Добав ьт е в корень п риложения активную ст р аницу с им ен ем


FramesPage . азр х, в которой БУдyr располож ен ы фреймы ,
назначьте ее стартовой и зап олни те следую щим кодом

<%@ Page Language="C#" %>

<html xmIns='huр://www.wЗ.or!j'1999/xhtml" >


<head runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<frameset rows='70, >!о">
< frаше src='ТttlePage.aspx" 1>
< frашеsеt cols="30%, >!о">
<frame src="MenuPage.aspx" />
<frame name='MainFrame" src=''Default.aspx''>
</frameset>
</frameset>
<noframes>
<body>
< hl >Это управляющая страница-шаблон фреймов <lh l >
<lbody>
</noframes>
<lhtml>

Листинг Управляющая страница FramesPage . aspx


навигационной панели
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Мы создали шабло н фреймов и з двух стр ок Верхняя строка имеет


вы соту 70 пuкс елов, а оставшаяся часть занята нижней строкой ,
п оделенной на дв а столбца. Причем п ер вый столбе ц займет 30%
ширины окна броузера. Обратите внимание на структуру HTM L-
дескрипторов: дескриптор <body> прис угствует только в
альтернативном блоке для броузеро в, н е подцерживающи х фреймы. Мы
удалили из страницы код дескр ип торов <forт> и <div> ,
автоматичесЮ1 сген ер ированны й мастером. Стр аница с фре ймам и не
требует обработки на сервере и е й бы больше подошло расширение . htщ
но не будем мелочиться и оставим все как есть.

в п ер вый фрейм, ассо циир уемы й с верхн е й строкой, будет загр ужена
страница TrtlePage.aspx с про стым текстом заголовка. Во второй фрейм
пом естим страницу MenuPage.aspx, в которой будет р асполага ться
элемент TreeV i ew, связанный с файлом Web.sitemap карты саЙта. В
тр етий , именованный фрейм, и знач ал ьно бу,цет загружена го това я
дОЛ1QШ НЯЯ страница, а зат ем БУдУГ подгр уж аться дрyrnе готовые
страницы , выбир аемые поль зователем щелчком на узлах карты саЙ та .

• ~Создайте новую ст р ани цу без файла отделенного кода с


именем Т i tle Page . asp x и заполните ее следУЮЩИМ кодом

<%@ Page Language="C#" %>

<html xmIns =' huр ://www.wЗ.or&,1 999/xhtml" >


<head runat="server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nшa t="sе rvе г ''>
<div style=''text- align:center''>
< h2 >Эт о за гол ов ок п а н ел и н а вигации <1h2>
</div>
</fOmI>
<lbody>
<lhtml>

Листинг Страница TitlePage.aspx с TelCCTOM заголовха


первого фрейма
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• IJ$Создайте новую страницу без файла отделе нн ого кода с


именем MenuPa ge . азрх и заполните ее следующим кодом

<%@ Page Language="C#" %>

<html xmIns='huр ://www.wЗ.or!j'1999/xhtml" >


<head runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nmat="server''>
<div>
<asp:TreeView ID='TreeViewl " runat="server"
DаtаSо шсе ID=''SitеМа рDаta Sошсе 1"
5 е lectedN od е 5 tyle- F о nt- Во k:l = ''true''
SelectedN odeStyle- F ont- Italic=''true''
Тагgеt=''МаinFгаme'' />

< а s р :sitеМарDа taSошсе ID="S itеМар Dаtа Sошсе 1" runat="server


</div>
</fопn>
<lbody>
<lhtml>

Листинг . Страница MenuPage.aspx с элементами TreeView


и SiteMapDataSource
Обрати те внимание на атрибуг Target= " Mai nFrame "
элемента TreeView, который устанав ливает для всех ссылок
узлов дерев а оди н и тот же именованный фрейм страницы
FгашеsРаgе . аsрх .
• ~ ротестируйте навигацию с использова ни ем фреймов

Результат в н ешне будет примерно таЮ1М


--1.
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

~ Untltled Page - MICrosoft Internet Explorer


- -.....;...;

~
Edt Vfew Favoot es TcoIs НеР
.... Back ... ...... 10 Ш ~ Ii3Seach [';J Favootes '1]i' Мeda с,1 ~ ... d ~ ~ .,. о
Ad<:tess 111 http://ocahJst :1035/WebSte 16;fra mesPcqo,aspx 3 .> ", 1
Это затоловок панеJlll Н3ВIff3ЦИИ


13 ДОМОЙ
Gi Товары При мер
AmIаратура
Программы использования
13 Услуги
Обучеюrе карты сайта
Консультации
Поддержка Консулыaцrш: Консультaцrш по
эксruryатaцrш

омой> Ус > КОН 'Льтацuu

в Домой о содер жимое

8 Товары страющы

AmIаратура Consulting.aspx,
Програм:мы де мы пров о дим

8 Услуги онсулътации С

Обучеюrе arшши

Консультации ентзмн

Поддержка

< Назад Вперед>

r- Использовать TreeView
r Использовать Меnи

liI ГГГ ~ Lосal lltrаr.et

Во фрейм с содержимым загружаются созда н ные нами ра н ее стра н ицы


с готовым управле ни ем только для того, чтобы упростить иллюстрац и ю
рассматриваемой темы. Они, в свою очередь, также с п особны
соде р жать полноце н ные элемен ты управле ни я. За гружаемая в третий
фрейм страни ца соде р жи мо го под гружает связанную с ней ма стер­
страницу вместе с ис п олняемым кодом С#, р ас п оложе нн ым в блоке
скриптов.

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Обратите внимание, что при смене содержимого третьего фр ейма


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

FramesPage.aspx. Это один из недостатков механизма фреймов ,


способный ввести пользователя в заблужде ние. Есть и другие
недостатки. В связи с этим , технологию фреймов рекомендуют
использовать только тогда , когда она действ итель но необходима.
Альтернативный прием навигации с использованием мастер-страниц
является более современным, хотя и генерирует больший объем
пересылаемого HTML-Koda.

т
(

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Безопасность

Аугентификация с ПОМОЩЬЮ форм. Сертификаты. Настройка режи ма


ауге н тификации форм. Хранение Удостоверений в ко н фигурационном
файле. Про граммное добавление п ользователей в ко н фи гурационный
файл . Создание стра н ицы регист р ации. Хеширование паролей в
Web .co nfig. Закрепле ни е за браузером п остоян н ой аугентификации форм .
Аугентификация с п омощью AP I Memberstllp. Создание хра ни лища
удостоверений . Добавле н ие в хранилище БД новых пользователей через
угилиту WPJ'. Создание и удале н ие пользователей. Извлечение из
хранилища списков пользователей . Конфигурирование поставщика
SqlМemberstllpProvider. Об н овление пользователей в хранилище .

Аутентификация с помощью форм

Файлы к лекции Вы можете скачать здесь скачать:

httр :J/оkl . iпtШ . ruld ераrtmeпtliпtеmеtlр rasp netl 18/18.пр .

Безопасность ВЮlючает в себя ряд меро п риятий , необходимых для


п редотвращения несанкционированного доступа к сайту и защиты
информации. Сюда входят аугентификация (распознавание) и
авторизация (управление правами доступа к важным ресурсам)
п ользователя , шифрование, хэширование и цифровые подписи. Для
все го этого ASP.NET содержит целый арсенал средств и их
использован ие нужно п ланировать с самого начала разработки
п риложения , чтобы максимально смягчить п отенциальн ую угрозу атак
н а саЙт. При этом нужно всегда п омнить, что надежн ость системы в
целом определяется надежн остью ее самого слабого звена.

Основные задачи п о защите сайта следУЮщие:

1. Аугентификация - опознавание источника сообщений по схеме


"свой-чужой" с целью уста н овить, является ли пользователь
зарегистрированным н а сайте или анонимным. Примером может
служить п роверка п ро п уска п ри входе в организацию

2. Авторизация - определение уров н я п ол н омочий по до п уску к


важн ой информации и выполнению над ней определенных
действий. Примером может быть допуск к определенным
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

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

з. Конфиденциальность - изоляция данных одного пользователя от


любого вида доступа со стороны д ругих пользователей.
Обеспечивается с помощью шифрования данных в каналах связи и
в местах постоянного или временного хранения

4. Целостность - защита данных от и зме нений в результате


неавторизованного вмешательства

Ауге нтификация нового пользователя начинается с его регистрации.


Пользователю предлагается страница регистрации с текстов ыми
полями , ч е рез которую у него запрашиваются некоторые

идентификационные данные. По этим да нным создается и сохраняется


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

За регистрировавшем уся пользователю может быть отослан некоторый


Юlюч, который в дальнейшем будет служить дополнительным условием
при доступе к сайту

Теперь при за просе ограниченного ресурса пользов атель предъявит


свое Удостоверение , которое система верифицирует и примет решение:
если у,цостоверение пользователя п одтверждается, ему предоставляется

доступ к Web-pecypcy, иначе БУдет предложе на регистрация. Процесс


аугентификации может выглядеть примерно так

за прос
ПQЛ ЬЮ 8Эт enь
о rp W"l\4 ч еt-t-1 0ГQ
а yr ент ltф.., цмрован
ресурса

Нот

в приложениях ASP.NET ауге нтификация может быть реализована


QЦним из следующих способов:


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

1. Аyrентификация с ПОМОЩЬЮ форм - поддерживается классом


Sys t em . Web . Secu ri ty . FormsAuthen ti cationModu l e
2. Аyrентификация Windows поддерживается классом
Sys t em . Web . Secu ri ty . WindowsAuthenticationModu J
3. Аyrентификация с помощью паспортов - п оддерживается классом
Sys t em . Web . Secu ri ty . Passpo r tAuthen ti cationModl
4. С пециализированная аyrентификация п оддерживается

внебиблиотечными классами сторонних производителей или


самодельным классом

Системы коммуникации шифруются с помощью системы SSL (Secure


Sockets Layer - уровень защищенных сокетов) . Поскольку система SS L
является службой (lntemet I пfопnatioп Services
IlS службы
информационной п оддержки
Intemet) и работает под Н1ТР , то
специально коммуникации нам шифровать н е нужно - все пересылки
шифрует сама служба. Единственное отличие - адрес запроса ,
защищенный SSL, начи на ется н е с http ://, а с https :l/. И трафик SS L
п роходит не через порт 80 для обычных запросов , а через порт 443.

Сертификаты

Обычно сервер, которому клиент собирается пересылать важные


данные , маркируется сертификатом. Сертификат - это некоторый
па спо рт сервера, п одтверждающий тот факт, что ему можно дове рять.
Организация, которой принадлежи т сервер, п риобретает сертификат у
известного центра серт ификации СА (Certificare Authority) и
инсталирует его на своем Web-сервере.

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


сайты:

• Thawte - ссылка: http://www.thawte.com


• VегiSigп - ссылка: httр :l/www. vегisigп.соm

Инсталированный на сервере сертификат содержит следУЮЩУЮ


информацию:

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

• Серий ный номер сертификата


• Имя , название организации и адрес держателя се ртификата
• Даты проверки сертификата
• Открытый ключ, который БУдет рассылаться клиентам для
шифрования симметричного Кf/юча сеанса

Клиент (браузер) доверяет СА и поэтому готов доверять подписанной


СА инф:Jрмации. В свою очередь, СА сохраняет инф:Jрмацию о каждом
зарегистрированном пользователе. Начало работы по защищенному
каналу связи начинается так:

1. Браузер посылает запрос на соединение с сервером


2. В отв ет сервер присылает свой сертификат
з. Браузер запрашивает из центра сертификации оригинал
поступившего се ртификата и сравнивает его с присланным
сервером

4. Если инф:Jрмация в сертификатах совпадает, браузер считает


адресуемый сервер заслуживающим доверия и решается на
соединение. Он генерирует случайным образом симметричный
ключ шифрования подходящей для него длины, шифрует его
присланным в сертификате открытым ключом и отсылает серверу
s. Сервер получ ает от браузера зашифрованный КЛЮЧ сеанса и
р асшифровывает его своим закрытым Кf/ючом. После этого у
сервера и браузера есть одинаковый секретный Кf/юч, с ПОМ ОЩЬЮ
которого они готовы применять симметричное шифрование к
п ересылаемой друг другу инф:Jрмации на протяжении всего
текущего сеанса

Аутентификация форм

Аугентификация (распознавание) на основе ф:Jрм реализуется в


пространстве имен Sys te m. Web . Secur i ty классами :

• Fo r msAuthent i cat i onModule


• Fo r msAuthent i cat i on
• Fo r msAuthent i cat i onEventArgs
• Fo r msAuthent i cat i onTicket
• Fo r msldentity
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Выбор этого режима уста нав ливается только в одном еди нственном
месте - конфигурацuонном файле web.config корневого катал ога сайта с
по мощью элемента

<authentk:ation mоdе=''Fопns'' />

Аугентификацию форм можно выполнять и с помощью API-


интерфейсов Me mbe r ship и Roles (об этом позже).

Аугентификация форм основана на удостоверениях (мандатах) , в


которых хра ни тся информация о зарегистрированном пользователе .
Мандаты хр анятся на сервере в базе данных зашифрованными и
n ересылаются при каждом запросе в сооkiе-наборах. ASP.NET при
каждом запросе обрабатывает со оkiе-набор и задает по нему уровень
безопасно сти запроса.

Для реализации аугентификации форм нужно выллнитьb следующее:

• Настроить режим аугентификации форм в файле web.config


• Настроить службу IlS для разрешения анонимною доступа к
виртуальному каталогу

• Настроить ASP.NET для ограничения доступа к защищенным


катало гам

• С оздать страницу регистрации

Настройка режима аутентификации форм

В файле web.config виртуального корневого каталога сайта необходимо


определ ить нужные пар аметры аугентификации , как свойства масса
System . Web . Conf i gurat i on . Fo r msAuthentica ti onCon f i~

и з следУЮще го набора:

Опции аугентификации форм в файле web.config


Значение по
Опция ОnисаНI1
умолчанию

Имя cookie-Ha
НТГР для

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

использован и

аугентификац ]
При работе Н е
одном сервер(

н ескольких

Name . ASP XAUTH n риложений (


н абору
безоnасн ости
каждого

n риложения f

задать уникал]

имя для

гарантирован ]

изоляции

Определяет
страницу

ре гистрации

п ользователя
Log in Url log i n . asp x
запросе

защищенной
страницы ( 1(
вход в систем

Время жизни
сооkiе-набора

безоnасн ости
минугах. Если
установлен ре

скользящего

устаревания и

п ериод междУ

соседними

запросами н е

n ревысит это]

Ti meout 30 таймауга , то
ASP.NET обнс
метку времею

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

сооkiе-наборе
если простой
пр евыс ит

установлен ны

таймауг, БУдет
затребова на н
регистрация

п ользователя

Включает реж
скользящего

устаревания с

н абора
безопасн ости .
это м режиме I
Sl i dingExp i ration false устаревания п

каждом зап ро,

будет сбрасыв
если очереднс

пр остой не
пр евыс и т ука ;

знач ение Tim


Указывает спе
п ересылки
Cookieless UseDeviceProf i le
удоставеренИJ

п ользователя

Задает уровен
безо п асн ости
сооkiе-наборо
аугентификаЦ I

• None -
шифров
не

подпись

• EncrYl
Protect i on All
- только
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

шифров
• Validc
- только

подпись

• All -
шифров
подпись

При включею
требует перед.
через SSL . Есл
н е активиров;:
RequireSSL false
сервере, то

аугентификаЦ I
форм работап
будет

Разрешает
п ереадреса ЦИ I

междУ

при ложениям

использовани

аугентификаЦ I
EnableCrossAppRedirects false
фоРМ. Оба
при ложения

должны опир.

на одно и то )t

хранилище

удостоверениi

Указывает стр
на которую

направля ется

пользователь

успе llllЮЙ
регистрации,
DefaultUrl default . aspx
он напрямую

запросил стра
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

ре гистра ци и ,

указа нн ую в

Log in Ur l
Может укаЗ Ы Е
хает , в р амка:

кото р о го люб(
Doma i n п усто п р и ложе н ие r-.
и с п ол ьз овать

и те же eookie
н абор ы

П угь для eoak


н аборов.
Path /
Р екоме н дуето
умолчан и ю

П ереч и сле н ные свойства уста н ав л иваются как атр и буг ы доче р него
дескр ип то р а <forms> се кции <a u thent i cat i on mode= " Fo rm s "
/> . Вот п ример и спол ьз ован ия полно го набора этих а тр ибугов в фа йле
web .config

<?xml version="l .O" encoding=''utf-8'? >


< сопfigшаtio п >
<system.web>
< сошр ila tiо п debug=''true'' />
< аuthепtk:аtioп шоdе=''Fоrшs''>
< fоrшs
name="MyCookieName"
IogiпU rl= ''М yLo giп . asp х"
timeout="20"
slkl iпgЕхр iratio п= ''true''
cookie1ess="AutoDetect"
protection="All"
requireS S L="false"
е паЬ!ее rossAp р Red irects= "false"
defauhUrl= "М yDefault.aspx"
domain=''''
path="/"
1>

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</authentication>
</system.web>
</сопfigшаtioп>

Листинг Настройка режима аутентификации форм

Хранени е удостов ерений в конфигурационном файле

Хоть это и не самый лучший способ хр анения удостоверений


пользователей , зато самый пр остой . Вообще, удостоверения мож н о
хра нить где угодно , только н уж н о предусмотреть соответствующий код
их сравнения с введе нн ыми на стра ниц е регистрации да нными. Если
удостоверения хра нятся в файле web .config, то их н уж н о п омещать в
до ч ерний для <forms> дескри п тор <creden ti als> . Вот при мер
для трех п ользователей

< ?оо version="l .O" encoding=''utf-B'? >


< сопfigшаtioп>
<system.web>
<compilation debug=''true'' 1>
< аuthепtk:аtioп mode=''Forms''>
< fо ш1S
name="MyCookieName"
IoginU rl= ''М yLo gin. asp х"
timeout= '2 0"
slid ingExp iratio п= ''true''
cookieless="AutoDetect"
protection="All"
requireSS L="false"
епаЬ!еС rossAp р Red irects= "false"
de fault Url= "М yDe fa ult. aspx"
domain=''''
path="I"
>
< сгеdепtials passwordFormat="Clear''>
< шег name="Admin" password='Root" 1>
< шег name=''Petja'' раsswогd="Ха-ха" 1>
< шег name='Vasja" раsswогd="Хо-хо" 1>
ю,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<!credentials>
<!forms >
<!authentication>
<!system.web>
<!сопfigша tioп>

Листинг . Пример хранения удостоверений в хонфигурационном


файле

Упражнение 1

Ра ссм отри м при мер ограничения доступа к страницам сайта с

п омощью аyrен тификации форм и хранением удосто вер ен ий в

конфигурацuонном файле.

Программное добавлени е пользователей в

конфигурационный файл

Пол ьзователе й в конфuгурационный файл можно добавлят ь как


декларативно, н еп осредственно редактируя секцию <credentials> ,
так и пр о граммно.

• IJ$Создайте пустой про е кт Web-приложе ни я командой


FilelNewlWeb Site
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

=====----'---.lI~
T..-rР:~"" Гf! ;-;:


АЧ'
~
r.ET \',,,,
Sib

Seach Onlre
~
А5Р J-ET W3!J
S Of V tO
ж-sma l
Si.,
~
Sb:."
Vleb
K~

-
Т " Щ' kI'= " ,

• г;;.:;='Добавьте к п риложению конфuгурацuонный файл Web.config,


выполнив командуWеЬsitе/Аd d New Item

=====----.lI~
Т""1"=
f:; ;:;:
~

~
~C

Vleb Fa m
D
МOsR Р,,?,

-= [!j]
c crn-ol

~
~
КТf,\, Р,,?,

j,'jj
~
Web Sf(, t e

~
!'.j
C"'SS

j'jJ [j
с _,
)OJVL F,", Xf,\, 5chotm Т е " Fie Rею:хсе Fle SQ.. C<I:ab.>,.,
ДPP I E'~"

1m ~
-, ~ 11@' i [jJ
00
~
JScrv Fi;'
D,bSot
~.
Siw М"I' М:Ы"I'!ОЬ

\ 'В3c r ipt Fi:g
"-'
111=: ~'
I~ fl:е LSOO tD [~e l'ie~ ~~ I ~atrn
,,\Ji
"'tIrQ$
~ ~ ro ~

~~ Iw,;, , [сП'3
L""",,,,e I~" iJ г р >се "odo 1 ""р" "" filo
Г ~юm>ter=е

• Г;:;==Заполните конфuгурацuонныu файл следующим кодом


- ~.
11

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<?xml version="l .O" encoding=''utf-8'?>


<сопfigшаtiо п>
<system.web >
<соmрilatюп debug=''true'' 1>
<authentication mode="Forms''>
<forms
пате=''М yCookieN аmе"
10 ginU rl='M yLogin.aspx"
d е fa ultU rl=' 'м yDe fault.asp х"
protection="All"
timeout=''20''
path="I"
requireS SL= "false"
slid ingExp ira ПО п=' 'tПJе "
cookieless="AutoDetect"
dom.ain=""
епа Ь lе С rossApp Red irects= "false ">
<credentials passwordFormat=''Clear''>
<user name="Admin" password=''Root'' 1>
<user name =''Петя '' раsswогd=''Уф&.аmр;Уф'' 1>
<user name=''Вася'' password='!$-*?'" 1>
</credentials>
</fопns>
</authentication>
</system. web >
< /соnfigшаtiоп>

Листинг . Код хонфигурационного файла

• IJ$Добавьте к проекту страницу без отделе нного кода с им ен ем


Log i n A ddUs er s . asp x и заполните ее следУЮЩИМ кодом

<%@ Page Language="C#" %>


<%@ Import Nа mеs р асе=''Systе m.WеЬ. Сопfigшаtiоп'' %>

<script runat= "server''>

protected уою btnAddUsers_ C lick(object sender, EventArgs е)


{
11 УчеТНbl е зап иси ДЛЯ новых аугентифицироваННblХ пользов

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

string[,] authUsers := {
{''userl'', "passwordl "},
{''user2'', "password2 "},
{''usегЗ'', "раsswordЗ "}
};

// Загрузить содержимое корневого Web.config


Configuration mуСопбg:= Systеm.WеЬ.Сопfigшаtiоп.
WеЬСопfigшаtiоnМапаgег.ОрепWеЬСопfiguгаtioп("~/' ');

// Найти содержимое секции system.web


ConfigurationSectionGroup systemWeb:= myConfig.SectionGroups['

// Найти содержимое секции authentk:ation


System. Web .Configuration.AuthenticationSection authSec :=
(5 ystem. Web. С о пfigша tio n.Authentk:atio nS есооп)
s ystemWeb . 5 есоо ns ["authentica оо п"];

// Установить параметр раsswordFопnat


authSec.F orms.Credentials.PasswordFormat := System. Web.Configu

// Добавить новых пользователей


for (int i:= О; i < authUsers.Length / 2; i+ +)
а uthS ес. F о гшs. С redentials. U sers. Add( new 5 ystem. Web. С о пfigш
authUsers[~ О], authUsers[~ 1}));

// Обновить файл Web .config


myConfig.SaveO;

// ОТСblлаем сообщен ие
IblUsersResult.Text:= ' 'Новые пользователи добавле ны!!! ";
}
</script>

<html xmIns='huр://www.wЗ.or&,1999/xhtml" >


<head runat:= "server''>
<tide > Untitled Page</tide>
<lhead>
<body>
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<form ю= "foгml " nmat= "selVer''>


<div style=''text-align: center''>
< h1 >Адм инистративная страница добавления учетных за пис е~
<р>

<asp:Button ID ='Ъ tnAdd Usеrs" runat= "selVer" Теxt= "Д обавить "
<р>
<asp:Label ID="lb IUsersResult" гuпаt="sе lVег"></аsр:LаЬеl></р ;;;
</div>
</fonn>
<lbody>
<lhtml>

Листинг. Страница LoginAddUsers.aspx


Обрати те в ни мание . Чтобы не и с п ользовать дл инн ые и мена
классов в стра н и ц ах с совмещенным кодом, можно подключи ть

вначале ст р аницы директиву

<%@ Import Nаmеsрасе="Systеm.WеЬ.Сопfigшаtiоп" %>

• ~ режиме редактирования страницы LoginAddUsers.aspx


вы п ол ни те командУ FileNiew in Browser

Эта страница программно добавит новых пользователей в файл


Web .co nfig. Также бу;цуг скорректирова н ы имена старых п ользователей
п угем п риведения символов к нижнему регистру Но это не
существенно, поскольку ASP.NET п ри срав н ени и имен реrnстр
символов не учи тывает.

• Г;;:;-Добавьте в конфигурационный файл блок авторизации ,


запрещающий достyn всем анонимным пользователям, чтобы
окончательный вид файла стал таким

<?xml version= "l.O" encoding=''utf-8'?>


< сопfigшаtiоп>
<system.web >
<compilation debug=''true'' 1>
<authentication mode="Forms''>
<forms
паmе=' 'М yCookieN аmе "

ю,
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

10 ginU rl= ' М yLogin.aspx"


d е fa ultU rl=' М yDe fault.asp х "
protecnon= "All"
timeout= ''20''
path= "I"
reqllireSSL="false"
slid ingExp ira по п=' 'tПJе "
cookieless= "AutoDetect"
domain=""
епа Ь leC rossAp р Red irects= "false ">
<credentials passwordFormat=''Clear''>
<user name= "admin" password='R oot" 1>
<user name =''nетя'' раsswогd=''Уф&аmр;Уф'' 1>
<user name =''вася'' password="!$-*?&quot;" 1>
<user naте ='ше гl " password="passwordl " 1>
<user naте ='ше г2 " password="password2 " 1>
<user name= ''usе гЗ'' раsswогd ="раsswогdЗ " 1>
</credentials>
</fопns >
</authenncanon>
< аuthогizatюп>
<deny users='?"I>
</authorizanon>
</system. web>
</configuranon>

Листинг. Окончательный вид файла Web.config


• г;.:.='Добавьте к проекту две стран и цы без отделенн ого кода с
име н ами Default . asp x и MyDefault . asp x со следУЮ ЩИ М

КОДОМ

<%@ Page Language="C#" %>

<script runat= "server''>

protected void SignO utAction_Click(object sender, EventArgs е)


(
11 Уни чт ожить сооkie-набор
F о rmsAuthe пос а по п. 5 ignО ut();

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

II Направить на страницу регистрации


IIF опnsАuthепtk:аtio п. Red irectTo Lo giпР ageO;
}
</script>

<html xmIns= ' huр ://www. wЗ.or&,1999/xhtml" >


<head ruпаt= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id= "forml " nшat= "sе rvег ''>
<div>
<hl >
Страни ца с ограниченным доступом Defauh.aspx<lhl >
<р>

< аsр:Вuttоп ID ="SigпО utAс tiоп" runat="server"


Теxt= "Отменить регистрацию " ОпСliсk= "S ignОutAсtiоп_СIicI
< аsр:НурегLiпk ID ='НурегLiпkl " runat="server"
N avigateUrl= "~lМyDefault.aspx "> На страницу MyDefauh.aspx.
<Ias р:Н ур erLink> </p>
</div>
</fоПll>
</body>
<lhtml>

Листинг. Страница Default.aspx

<%@ Page Lапguаgе ="С#" %>

<script ruпаt= "server''>

protected void SignО utAсtioп_Сliсk(оЬjесt sепdе г, ЕvепtAгgs е)


{
II Уни чт ожить сооkie - набор
F о rmsAuthe пtk:а оо п. S igпО иЮ;
II Направить на страницу регистрации
IIF опnsАuthепtk:аtio п. Red irectTo Lo giпР ageO;
}
</script>

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<html XmInS= ' huр ://www.wЗ.or!j'1999/xhtml' '>


<head id =' 'Неаdl '' runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id ="forml " nmat="server''>
<div>
<hl >
Стра ница с ограниченным до ступом MyDefault.aspx<lhl :
< р>

<asp:Button ID="SignO utAction" nmat="server"


OnClick= "S ignOutAction_Clk:k" Text= "Отменить р еги ст р ац
< а s р:Нуре гLink ID =''НурегLinkl '' nmat="server"
N avigateUrl= "~lDefauh.aspx' '> На страницу Default.aspx.. .
<Ias р:Н ур erLink > </p>
</div>
</fonn>
<lbody>
<lhtml>

Листинг. Страница MyDefault.aspx

Создание страницы регистрации

Страница регистрации предоставляет пользователю интерфейс для


вв ода имени и пароля , принимает и х и сравнивает с Удостоверениями ,

хранящимися на сервере. Если удостоверения хранятся прямо в


конфuгурацuонном файле , их извлечение и проверка достаточно
просты. Не намного сложнее извлекать Удостоверения , хранящиеся в
любом другом внешнем хранилище.

Страница регистрации долж на вютючать в себя поля ввода дл я


получения от пользователя данных удостоверения. Для проверки
достоверности по льзо вательских данн ых необходимо использовать
валuдаmоры , генерирующие нужный JavaScript -код на ютиенте, а также
выполняющие проверку на сервере.

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• IJ$Создайте новую страницу с имен ем MyLogin . aspx без


отд еленного кода

• ~3аполните страницу элементами управления и настройте их


соглас н о таблице

Таблица свойств интерфейсной части стран

Элемент Свойство

Рапеl 10 Maj

BorderColor Si J
BorderStyle Ri(

Te xt Box 10 Us'

RequiredFieldValidator 10 Us'

ControlToValidate Us€

Display Dy!

Не ,
ErrorMessage
пол

Тооl Tip Пус

Text *

RegularExpressionValidator IO Us'

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

ControlToValidate Us'

Display

ErrorMessage Нев

Дог
Тооl Tip
и п,

ValidationExpression [а-

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Text *

TextBox 10 Pa~

TextMode Pa~

RequiredFieldValidator 10 PW(

ControlToValidate Pa~

Display Dy!

ErrorMessage Не :

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Тооl Tip Пус

Text *

RegularExpressionVal i dator IO PW(

ControlToValidate Pa~

Display

ErrorMessage Нев

Ие"
Тооl Tip
сим

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

ValidationE x pression ~: ~

Text *

Button 10 Ви !

Text Отг

Label 10 lbJ

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Интерфейсная часть страницы MyLogin.aspx в режиме проектирования


будет такой

MyLogin.aspx I т Х'

~
Введите свои имя и пароль

~
Имя пользователя: r [
~ .

Пароль: r I~
Отправить
IEI
I
lblResult]]
• Е1ТОГ message 1.
• Е1ТОГ message 2.

Код страницы MyLogin.aspx будет таким

<%@ Page L апguagе="С#" Епа ыlv iеwst аtе=''fаlsе '' %>

<script nmat= "server''>

protected void Lо ginAсtioп_Сliсk(оЬjес t sепdег, Еvе пtAгgs е)


(
this.ValidateO;// И с полнить вали даторы на сервере
if(!this.IsValid)// Оценить флаг достов ер нос ти
геturп;// Отправить назад как есть

// Изв ле чь из wеЬ.сопfig и сравн и ть с введенны м


if (F опnsАuthепtk:аtioп. Authentica te(UsemameText. Text, Р asswo rdText. Те

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

if (F опnsАuthепtk:аtioп. Authentica te(UsemameText. Text, Р asswo rdText.Те


(
11 Создать временный сооkiе-набор (второй параметр false),
11 записать в него метку ауге нтифи кац ии и п ере направить
11 на и сход ную за прошенную страни ц у или MyDefault.aspx
FопnsАuthепtk:аtioп. Red irectF romLoginP а ge(Usemame Text. Text, fa IseJ
}
e~e
(
HtmlGenerk:Control message = new HtmlGenerk:Control() ;
message.lnnerHtml = "< h2 sty1e='color: Red'>HeBepHoe имя и л и пар е
fo пn1 . С о пио Is.Add( messa ge );
}
}
</script>

<html xm1ns=''httр ://www.wЗ.огgl1999/xhtml''>


<head id= 'Head1" nmat="server">
<title>Untitled Page</tide>
<lhead>
<body>
< fо пn id="fопn1 " runat="server''>
<div style=''text-align: center">
<h2 >
Введите свои имя и пароль < lh2>
<asp:Panel ID='MainPanel" runat="server" BorderColot="Silver"
BorderStyle= 'Ridge"
BorderWidth=''2px'' Height= ''90 р х'' Width="412 px''>
<table bord er=''O'' cellpadding="S" cellspacing=''O '' style=''width: 100<7
<tr>
<td >
&nbsp;&nbsp;&nbsp;
</td>
<td align= "right" hеight="4З" style=''width: 1б 7рх' '>
Имя&пЬsр;пользователя: </td >
<td >
&nbsp; < asp:TextВox ID='UsemameText" ruпаt="sеrvег" 1>
</td>
<td >

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

runat= "server" Сопtrоrrо Validate= "UsemameText"


Display= ''Dynamic''
ErrorMessage= 'He заполнено поле 'Имя пользователя
ТооШр='Пустое п оле ввода ''> *
</аsр:RеqШrеdFiеklVаlidаtor>
< asp :RegularЕхр rеssio п Valida to r ID= 'U sernameValid ator"
runat= "server" Сопtrоrrо Validate= 'UsemameText"
Disp lay=''Dynamic'' ErrorMessage="HeBepHoe и мя польз
ТооШр="Допуст имы буквы, цифры , пробелы и подч€
VаlidаtiопЕхрrеssiоп= ' la- яА- я \wl J* ''>*
</asp:RegularExpressionValidator>
</td>
</tr>
<tr>
<td >
&пЬ sр;&пЬsр;&пЬsр ;
</td>
<td align="right" hеight="4З" style=''width: lб 7 рх' '>
&пЬ sр;Пароль: </td >
<td >
&nb sp; < asp:TextВox ID=''PasswordText'' runat="server"
TextМode=''Password'' 1>
</td>
<td >
<asp:RequiredFieklValidator ID=''PwdRequiredValidator''
runat= "server" Сопtrоrrо Validate= "PasswordText"
Disp lay=''Dynamic'' ErrorMessage=' He запол н е но поле "
ТооШр='Пустое п оле ввода ''> *
</аsр:RеqШrеdFiеklVаlidаtor>
<asp:RegularExpressionValidator ID=''PwdValidator'' runat="s
С о ntro rro Validate= ' 'Р asswo rdText"
Disp lay=''Dynamic'' ЕrrоrМеssаgе =' 'Неверный пароль "
тооrпр= ' испо л ьзуются н еДо п уст и мые символы "
VаlidаtiопЕхрrеssiоп='(а - яА - я \wl ! "$&amp ;/O=\-?\*]*'>*
</asp:RegularExpressionValidator>
</td>
</tr>
</table>
< а sр:Вuttоп ID= 'Buttonl " runat= "server" Теxt= "Отправить "

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

<aspButton ID='Buttonl " runat="server" Теxt="Отпр авить"


OnClick=''LoginAction_Click'' />
</asp:Pane!>
<asp:Labe! ID=''1bIResuh'' runat="server" />
</div>
<asp:ValidationSummary ID='ValidationSummaryl " runat="server" />
</form>
</body>
</html>

Листинг Код страницы регистрации MyLoqin.aspx

При такой инфраструктуре аугентификации любо й п ользователь ,


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

Хеширование паролей в Web.config

в нашем файле Web .config до настоящего момента п ароли хранились в


виде открытого текста . В таком виде они ле гко уязвимы со стороны
пр одвинугых пользователей , а также со сторо ны административного
п ерсонала сервера . Их было бы желательно защитить. На этот случай
п редусмотрена возможность хеширования, которая заЮlючается в

п редварительн ой обработке исходного текста некоторой функцией ,


выход которой невозможно восстановить в обратн ую сторону.

в секции <c r eden t i als> имеется параметр pas swordFo r ma t. Он


п редназначен для указания ASP.NET, в каком ф:Jрмате хран ятся значения
па ролей и какой алгоритм хеширования к ним применялся. Есл и пароли
п редварительн о хешированы и сохранены в таком виде в

конфигурационном файле, то AS P.NET п ри получ е нии пароля от


п ользователя также его хеширует, прежде чем сравнить с храняшимся на

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Параметр passwordFo r ma t может п ринимать одно из трех


следующи х значе н ий:

• Clea r - пароль не хешuрован и пользовател ьский пароль н ужно


с р авнивать без предвари тельн ого хеширования
• MD5 - пароль хеширован алгоритмом MD5 и перед с р ав н е ни ем
присланный п ользовательзователем п ароль хешировать тем же
алгоритмом

• S НА 1 - для хеширования применять алгоритм SHAl

Для п редварительного хеширования п аролей в Web.config при ме н яется


следующий метод

str iпg hashed Pwd = FопnsАuthепtiсаtio п . На shP аsswогdF огStо гiпgl пСо пfigFile (

• ~Добавьте к проекту страницу HashPasswordPage.aspx и


наполните ее следующим кодом

<%@ Page Language="C#" % >

<script runat= "server''>

protected void btnН ashed P wd_ Click(o bj ect send er, EventArgs е)
(
// З агрузи ть содерж и мое кор н е в о го Web.config
Сопбgигайоп mуС опбg = Systе m. WеЬ.С опfigша tiоп.
WеЬ С опfigша tiоnМ апаgег.О р е пWеЬСопfiguга tio п("~/' ');

// Н ай ти соде р жи мое се кци и system.web


СопfiguгаtiопSесtю пG гоu р systemWeb := myConfig.SectionGroups['

// Н ай ти соде р жи мое се кци и authentk:ation


System. Web. Configuratio n.AuthenticationSectio n authSec =
(5 ystem Web. С о пfigша tio п.Аuthепtk:аtЮ nS ес йо п)
systemWeb. 5 ections ["authentica йО п"];

// Уста н о ви т ь п а ра метр р аssword Fопna t, сооб ща ю щий , что б ы


authSec. Forms.Credentials. Password Format := System. Web.Co nfiglJ

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

аuthSес.Fогms.Сгеdепtials.РаsswordFогmat = System. WеЬ.Сопfigu

// Извл екаем из коллекции Users старые имен а и пароли


int count:= аuthSес.Fогms.Сгеdепtials.Usеrs.Соuпt;
string[] пате = пеw string[count];
string[] clearTextPwd := new s tring[со uпt] ;
inti=O;
foreach (Sуstет.WеЬ.Сопfigurаtioп.FогmsАuthепtiсаtiопUsег user ir
{
па те П] = usег.Nаше;
clearTextPwd[i] := user.Password;
i++ ;
}

// Очищаем коллекцию Users


authS ес. F о гшs. С геdепtials. U sers. С lear();

// Добавляем старые имен а и новые хе шированны е парол и


for (i:= О; i < соuпt; i++)
{
// Хешируем исходный пароль
string hashedPwd := FоrmsАuthепtiсаtiоп.НаshPаsswordForStогiI
// Добавляем в коллекцию Users
а uthS ес. F о гшs. С геdепtials. U sers. Add(
new S ystem. Web. С onfiguratio п. F о mlSAuthenticatio пUsег( naт(
}

// Обновляем файл WеЬ .сопfig


myConfig.S aveO;

// Отсылаем сообще ни е
IblНashResult.Text := "Хе lШfровани е завер шено . <Ьг /> "
+ 'Пов торно не выполнять - будет хе ш н а хеш!!!";
}
</script>

<html xmIns='huр://www.wЗ.or&,1 999/xhtml" >


<head ruпаt:= "server">
<tide > Untitled Page</tide>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<form id ="forml " nшat="sе lVе г ''>


<div style=''text-align: ce nter''>
< h1 > Адм ини страт и вн ая стра ни ца хе ши рован и я паролей в Web
<р>

<asp:Button I D =' Ъ tnН аshе dРwd " nшat="sе lVе г " ОпС liсk =' ЪtnН.
<р>
<asp:Label I D="lb lН a shRe s ult " runat="server"></asp:Label></p>
</div>
</fonn>
</body>
<lhtml>

Ли с тинг Код с траницы Has hPas s wo rdPage . aspx


хеширования пар олей в Web . c o n f ig
• г;.:.=вы п олните стран ицу HashPasswordPage .aspx, но только один
р а з , чтобы п овто рно н е хе ши ровать уже хе шuраванны е п ароли

в резул ьтате мы п олуч и м вари а н т конфu гурацu о нно г о файл а с


хешuрованнымu паролями

<?xml version="l .O" encoding=''utf-B'? >


< с опfigшаtio п >
<system.web>
<compilatio n debug=''true'' />
<authentk:ation mode=' 'Forms''>
<fo rms
name="MyCookieN ame"
IoginU rl= ' 'М yLo gin.asp х"
de fault Url= "М уО е fa ult. aspx"
protection="All"
timeout='20 "
path="/"
requireS S L="false"
slid ingExp iratio п= ''true''
cookieless="AutoDetect"
domain=''''
е паЬ!е С rossAp р Red irects= "false "
>
<credentials passwordFormat="M D5''>

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

>
< сгеdепtials
passwordFormat="MD5''>
< шег name="admin" раsswогd='FАОЗЕВб88АD8ААlDВ59ЗDЗ:
< шег паmе=''петя'' раsswогd="ВБЗ974ЕЗЕЕ7ВО920FЕ24DFВ81
< шег па mе =''в ася '' раsswогd="44D4В2D42Е8ЗОВЕОDD4ЗЕб8З
< шег name=''userl '' раssword="7СБА180ВЗБ89бАОА8СО278ТЕ
< шег name=''user2'' раssword="БСВ75FБ52А9В52798ЕВбСF2~
< шег па mе =''usегЗ'' раssword="819ВОб4ЗDбВ89DС9В579FDFI
<!credentials>
<!forms >
<!а итеппса tioп >
<authorization>
<deny users='?"!>
<!authorization>
<!system.web>
<!сопfigшаtioп>

Листинг Файл Web. config после выполнения процедуры

хеширования паролей

Исходные пароли, вводимые пользователями при регистрации ,

остались прежними. Но в конфuгурацuонном файле они теперь


храняться как хешuраванные по алгоритму МО5 и являются
бесполезными для злоумьшmенников. Зама же система при
аугентификации при вод ит исходные пароли п е ред сравнением к
хешированному виду по тому же самому алгоритму. Если исходный и
оригинальный пароли правильные , то их хеши БУдУГ совпадать.

Закрепление за браузером постоянной аутентификации


форм

До сих пор мы использовали вр еменн ые сооkiе-наборы аугентификации


для конкретного пользователя , которые действуют только на период
сеанса и сразу Удаляются браузером после е го завершения. ЭТО
обеспечивает разумную безопасность. Но иногда может потребоваться
закрепить аугентификацию не за пользователем , а за браузером. В этом
случае при первой р е гистрации пользователя можно разрешить ему
создать на браузере постоянный сооkiе-набор, по которому бы узнавался

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Постоянные сооkiе-набор можно создать

• в странице р е ги ст рации при перво й посещении пользователя


установкой второго параметра в значение t rue (вместо false )
в методе

Fо rmsAuthe ntica tion.Red irectFro mLо ginP age( строка, true);

• в любом другом месте открытого сеанса выполнением метода

Fо rmsAuthe ntica tio п. S etAuthC 00 kie( стр о ка, true);

• в любом другом месте открытого сеанса выполнением кода

HttpCookie authCookie = FопnsАuthепtk:аtioп . GеtAuthСооkiе(строка,


trus. Respo nse .С 00 kies. Add( а uthC 00 kie );

Установленный таким способом сооkiе-набор будет существовать на


компьютере пользователя "вечно ", если только мы не Удалим его
методом

F опnsАuthепtiсаtio п. S igпО utO;

Можно такж е изменить временной статус постоянного сооkiе-набора на


л юбой странице. Покаж ем это

• г;;.:;='Добавьте к проекту страницу ModifyPersistentCookieAuth.aspx


без файла отдел е нного кода и заполните ее так

<%@ Page Language="C#" EnableViewState=''fulse'' %>

<script ruпаt= "server''>

Labe! message;

protected void Page_Load(object sепdеr, ЕvепtArgs е)


(
// Дескриптор цент р ирования
HtmlGenericCo ntro ! сепtеr = new НtmlGепеriсСопtroЧ "се пtеr'');
forml . С о ntro Is.Add( сепtеr);
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

HtmlGenericControl center = new НtmlGепегiсСопtroЧ"сепtег');


forml. С о ntro Is. Add( center);

// Текстовая метка с заголовкам


Labellabel = new LаЬеЮ;
center.Controls.Add(label);
IabeL Text = "< Ы> Закрепить аугентификацию за браузером< /lli

// Кнопки
Button createP ersistentCookie = new ButtonO;
center. С о ntro Is. Add( create Р ers istentC 00 kie );
createPersistentCookieText = "Создат ь бессроч ный AuthCookie'
createPersistentCookie.Click += new EventHandler(createPersistent
center.Controls.Add(new НtmlGепегiсСопtгоЧ'Ъг'));

Button createTemporaryCookie == new ButtonO;


center. С о ntro Is. Add( createTemporaryC 00 kie );
createTemporaryCookie.Text == "Создать срочный AuthCookie";
createTemporaryCookie.Click += new EventНandler(createTempor<
center.Controls.Add(new НtmlGепегiсСопtгоЧ'Ъг'));

Button deleteCookie = new ButtonO;


center. С о ntro Is. Add( d е leteC 00 kie );
deleteCookie.Text = ''Удал и т ь AuthCookie";
deleteCookie.Click += new EventHandler(deleteCookie_ Click);
center.Controls.Add(new НtmlGепегiсСопtгоЧ'Ъг'));

// Текстовая метка с сообщением


message = new LаЬеЮ ;
center. С о ntro Is. Add( message );
message.Text = String.Empty;
}

void createPersistentCookie_Clk:k(object serкler, EventArgs е)


{
// Создать бессрочный cookie
HttpCookie authCookie = FопnsАuthепtk:аtioп.GеtAuthСооkiе(''хх'

// Отослать на браузер

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

// Сообщить пользователю
message.Text = ''Бессрочный AuthCookie создан!";
}

void createTemporaryCookie_Click(object sender, EventArgs е)


(
// Создать бессрочный cookie
HttpCookie authCookie = FопnsАuthепtk:аtioп.GеtAuthСооkiе(''хх'

// Настроить его как временный сроком на 10 дней


authCookie.Expires = DateTJI11e.Now.AddDays(10);

// Отослать на браузер
tШs. Response .С 00 kies. Add( а итС 00 kie );

// Сообщить пользователю
message.Text = ''Сро чный AuthCookie создан!";
}

void deleteCookie_Click(object sender, EventArgs е)


{
// Удалить сооkie-набор реrnстрации
Fо rmsAuthe ntk:a по п. S ignО иЮ;

// Сообщить пользователю
message.Text = "AuthCookie )'Дален!";
}
</script>

<html xmIns='huр://www.wЗ.or&,1999/xhtml" >


<head runat= "server''>
<nde >Untitled Page</nde>
<lhead>
<body>
<form id ="form1" nшat="sеrvег''>
</fопn>
</body>
<lhtml>
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<lhtml>

Листинг Страница создания на браузере постоянного


сооkiе - набора аутентификации

Интерфейс стра ницы в режиме выполнения БУдет таким

...} Uпtitlеd Page - Microsoft Internet Explorer

Favcrites
h~ :/ ~осatюst: 10 34/'N ebSite 20 ;МodfyPerSistentcookieAutll, зsрх

ЗакреIПIТЬ аутентификацию за
броузером

Создать бессрочный AJJthCookle

Создать срочный AuthCookie

г УдаЛИТ6 AuthCookJe

Бессрочный AuthCookie создан'

Local in1Yanet

При закре п лении сооkiе · набора за браузером при соединении с сайтом


страница регистрации пользователю предъявляться не БУдет, пока не
зако н чится срок действия (если сооkiе-набор срочный).
В.М. С""",,,в Про,раммupoвtJNШ' "О ASP.NET

~~~~

т
j

(
Аутентификация с помощью АР! Membership

AP I МеmЬегsШр является готовой инфраструктурой в ASP.NET,


пр едназначе нн ой для организации ynравле ни я аутентификацией
пользователей. Он базируется на аугентификации форм , поэтому
конфигурировать ауге н тификаци ю в Web.config нужно точно также, как
при аугентификации форм. Единстве нн ое отличие , ч то хр анение
п ользователей будет осуществляться не в конфигурационном файле, а в
базе данны х . И для ynравления задействуются классы МетЬе r shi р.

Ч аще всего к корневому каталогу сай та до п уска ются все ананимные


п ользователи без ре ги ст р ации, а защи ще нны е ресурсы , требующие
аугентификацию , размещаются в подкаталогах со своим и файлами
Web .co nfig. Есл и кто-то за пр ашивает защи щенный ресурс из п одкатало га ,
система автоматичесЮ1 п е ренаправляет п ользователя на ст р аницу

регистрации.

Для исп ользова ния API Memberstllp нужно выполнитиь следующие


шаrn:

1. С конфигурировать ауг е нтифика цию форм в корневом каталоге


прил оже ния и авторизацию в защи щенных катало гах

2. Создать и н астроить базу данных для хра н е ни я удостоверений


пользователей

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

З. Занести в хра нилище пользователей


4. Создать страницу ре п!Стр а ции

Создание хранилища удостоверений

SQL Server 2005 создает базы дан ны х и работает с ними как с


отдельными файлами с р ас шир е ни ем .mdf. По умол ч а нию эти фа йла
размещаются в каталоге

C:\Program Filеs\Мiсrоsоft SQ L Sеrvе r\МSSQL.l\МSSQ L\Dаta

Мы сами можем в ручную создать файл базы да нны х для хр ане ния
удостов ере ний и добави ть в нее табли цы с необходимыми полями. Н о
это может н е стыковаться с API МеmЬегsШр, п оскол ьку он ожидает базу
да нны х определенной структуры. К тому же н ужно БУдет пропи сывать в
конфигурационном файле строку соединени й с этой базой и другие
конфигурационные п араЛ1етры, н еобходимые для работы AP I
МеmЬегsШр. Более п рост ой вариант п редУсмотр ел и разработчики VlSual
Studio 2005, В ЮIючив п одце р жку Ме mЬ егsШр в утили ту Web Site
Administration Тоо! (WАТ). Нам те п ерь вообще ни чего делать н е нужно ,
поскольку база да нны х н ужной структур ы для хран е ни я удосто вере ни й
будет создана автоматически при п е р вом за п ус ке WAT, если в
конфигурационном файле прописана секция аут ентифи кации qюрм .

• IJ$Создайте новый пустой про ект коман дой FilelNewlWeb Site

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

=====----'---.lI~
T..-rР:~"" Гf! ;-;:


АЧ'
~
r.ET \',,,,
Sib

Seach Onlre
~
А5Р J-ET W3!J
S Of V tO
ж-sma l
Si.,
~
Vloo
Sb:." K~

-
Т " Щ' kI'= " ,

• г;;;?Откройте окно копирования проектов командой Website/Copy


Web Site и ско пи руйте в новый п устой проект часть файлов из
п редыдщегоo п роекта аугентификации с помощью qюрм

'"
В.М. СН"""'
""" ' ..",..;;;;;",__..,,~____________~П~,,,~,,;"~
;;"~_
;;;;~
"";,~.;
"~,,,
;, ~.N~'
;,'
,. _ C:\._~' \ _ "

""""ц " """",", ."'''''''*....... '",.".., ... _ _ '1

Тестовые страницы Default.aspx и MyDefauh.aspx из пред ы дущего


проекта , ско нфигурированные ДЛЯ пров ерки ауг е нтифи ка ции , будуг
следующими

<%@ Page Lапguagе="С#" %>

<script nmat="server''>

protected void SignОutAСllоп_Сlick(оЬjес t sender, ЕvепtAгgs е)


{
1/ Уничтожить сооkiе-набор
F опnsАuthепtiсаtЮп. 5 ignО utO;
1/ Направить на стра ницу регистрации
IfFormsAuthentication.RedirectToLoginPageO;
}
</script>

<html xmlns=''httр ://www.wЗ.огgl1999/xhtml'' >


<head nmat="server">
<title>Untitled Page</tide>
</head >
,СО
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<body>
< fопn kl="fопnl" runat="server''>
<div>
<Ы >
Стран ица с ограничеННblМ доступом Default.aspx<lhl >
<р>
<aspButton ID="S ignOutAction" runat="server"
Техt='Отменить реrnстрацию" ОпСliсk="SignОutAсtioп_Сliсk" />
<aspHyperLink ID='HyperLinkl" runat= "server"
N avigate Url= "~IМ yDefault.aspx"> На страницу MyDefault.aspx.. .
</aspHyperLink > </р >
</div>
</foпn>
<lbody>
</html>

Листинг Страница Default.aspx

<%@ Page Language="C#" % >

<script nmat="server''>

protected vokl SignOutAction_ Clk:k(object sender, EventArgs е)


{
// Уничтожи ть сооkiе-набор
F опnsАuthепtiсаtioп. 5 ignО utO;
// Направить на стра ницу реrnстрации
/fFormsAuthentication.RedirectToLoginPageO;
}
</script>

<html xmlns="httр ://www.wЗ.огgl1999/xhtml">


<head id= ' 'Неаdl'' nmat="server">
<title>Untitled Page</tide>
</head >
<body>
< fопn kl="fопnl" runat="server''>
<div>
<Ы >

ее,
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Стр аница с ограниченным достynом MyDefault.aspx</hl >


<р>

<aspButton ID=''SignOutAction'' runat="server"


OnClick="SignOutAction_Click" Техt="Отменить регис трац ию " I~
< аsр:НуреrLink ID=''Нуре rLinkl '' runat="server"
Naviga teUrl="~ lDefault.aspx"> На страницу Default.aspx ...
</аsр :НуреrLink > </р >
</div>
</form>
<lbody>
</html>

Листинг Страница MyDefault.aspx

Код страницы регистрации MyLogin.aspx мы рассмотрим чугь позже ,


вм е сте с введенными изменениями .

• IJ$Откройте в н овом пр оекте сЮ)пирова нны й файл web.config и


удал ите из не го секцию <c r edent i als> вместе с в н есенными

р анее п ользователями. При этом должна остаться секция


аугентификации форм
r
B.M.CH~
~;'~~~~~~;;~:::::::;;;:,;~
~псо dшg. 'utf - Э·7>

<8YH~ . ""'Ь~
......:::::-....';~~::~::::~~"~'~N~';'
<cCC) p~ l ~ t ~on d"Ьuч ="tr u ,," 1>-
~ a u th", n tic~ ~ion .. OO", _ ·~o e.~ · "

naIl~ = 'МyC oc> k i ~ J ictE~ '

109 i n U< 1_ 'Мy L Dg [n _ "~px "


de!aul tUr 1- 'ИуООr а u l t .aspx ·
protect io ~= 'All '
t :ш~о u~ _ "2 0<

requ ires 5 L= ' ta18E "


" l~d ingEx pH 8 t~on _ 't п,,'
cook i",l~ "_ 'J'лtо D~ t,,сt '

dC<l.а iп - · "

<~CC, ~n- i, - ~ ~o~c-..пcc ·'~c~.-. С-" М '" ",


_U~~_ "a ' ~ ' ~._ ' _J_" "~",,,-_l "'_'.03EG8E:.)8"J:.~DE:::r::D~_E:3QE:.) · ,
.-,, ~~ n ~ ~ · _'- ·n я' г, ~·· - . г, - '-- · I' У'_':"', '''У: "., ""1 1": .'",::"
'-"~C· n л --·'--.~"·' r,OCC-,IУ' - ' ·1 ,,'"" ",~,',n",:llJl 'f:t'f'П"с'- ''; " .',
-_U~~: [ldI ~- '. ,,~ ~C 1" ~~",,~: 1- ", ~б ~_l, ОЕ: 5 3 Q '::.J_~ 8': : :" Е ; LI~_,30E
-LL ~~ ' nd~ ~ _ _, ~ "~ ): С.,,,.: _ j_ ' _ :D -, ~ ,LJ~;"! DJC '~U~~LCf"" ul _ ~ -'С,
<,,~C~ n,O ~ ' _ -' -~C- r,cc'; "" ~i _ -'-IO"fi41' i',По' 'О, 0;0" "oГ-4"~-: "

~,' ~ - ~J"J_ ~_~l,,'

~/~ u th~ntlc~tlon ?
~аuth оri 2 аtiою

~ / ~utho c ; '~~ ion?

в результате конфuгурацuонный файл долже н стать таким

<?xml version="l .O" encoding=''utf-8 '?>


< со пfigша tioп xmlns= ''http://schemas.microso ft. соml . N etC опfigша tio n/У 2 .0">
<system.web>
<compilation debug= ''true '' />
<authentk:ation mоdе =' 'Fопns ''>
< fопns name='MyCookieName"
loginU rl= ' М yLo gin.asp х"
de Cault Url= "М уО е fault. aspx"
protection="All"
timeout=''2 0''
path="/"
requireSS L=" false"
stidingExpiration=''true''
cookieless="AutoDetect"
dornain= ""
е паЬ !еС rossApp Redirects= "false ">
</forms >

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</authentication>
<!-- Временно закомментировали, чтобы н е требовал регистр,
<authorization>
<deny users='?"I>
</authorization>
-->
</system. web>
</сопfigшаtioп>

Листинг Конфигурационный файл при хранении пользователей в


БД Membership

• ~3апустите угилиту WAT командой Website/ASP.NET


Сопfigшаtioп и об р атите внимание, как долго она запускается

Замечание. Эта угилита может н е запускаться, если абсолютный


пугь к созданному проекту име ет пробелы и л и Ю1риллицу. В этом
случае пер еместит е проект в другое место файловой системы
компьютера.

• r;.:.=в пан ели Sоlutiоп Exp lorer щелкните на кнопке Refresh

Мы видим, что угилита WAT так долго за п ускал ась пото му, что
добавила к про екту каталог App_Data (если до этого его еще не было) и
создала в нем базу да нны х ASPNETDB . MDF , готовую для хр анения
удостов ере ний и согласованную с API Membership

Solution Explorer .... -j:::] Х

ASPNEТDB МJF

ее,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• ~ n а н ели Solutio n Ехрюге г двоиным щелчком на файле


ASPNEТD8.MDF откройте соединение с это й базо й да нн ых и
ознакомтесь в nанели Server Explorer с ее структурой, т ипи ч н ой
дЛЯ SQ L Server

8'" DаЬ СотесЬon:::

[], ДSPNЕl1ЖМDF
~--- r:з Database Di.зgгаms
е·· ТаЫе:::
НJ ..· ~ aspneCAppkat:ions
$-- b:iJ аsрг.еСМ€mОО-sh!p
~ .. . r:J aspneCP aths
I±J ... Ej аsрnet_Регsоn.зlizаЬonAlIUsегs
НJ-­ ~ а s рneСРегsоn.з~zаЬon РегUs е г
$-- b:iJ aspr.eCPгofile
~ .. . 1m aspr.eCRoI€s
i±J ... Е3 aspneCSchemaVersionS
@-- b:iJ
~-­ m:::I aspnet_UsersInRoles
ю·· Е3
aspnet_WebEvent_Events
ffi·· Views
$-- L::1 Stored Procedures
щ- . L::1 Funcbons

ffi·· Sугюпуms

НJ--- Туре.:;
~--- Ез AssembIies

Такой с п особ хра н ен и я Удостовере ни й п ользова т елей в локальной базе


дан н ых вместе с n р и ложени ем очень Удобе н , поскольку п озволяет
nереме ща ть сай т в любое место серве р а или р азворачивать на любом
сервере без дополни тельн ых настроек подключ е н ия SQ L Server. Да и
структуру базы данных угили та WAT создала такой, какая н ужна
и н фрастр уктуре API Membership. Это знач и т, что все классы
Ме тЬе r shi Р БУдУГ согласова н ы с хр а н илищем Удостове р ений.
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Ути л и та WAT а втоматич ески создает хранил и ще удостовере н ий тол ько


в том случае, если об н а р ужи т в кор н евом конфuгурацuо н ном файле
секцию

<authentk:ation mоd е=' 'Fопns ''>

Если н а моме н т за п уска угил и ты WAT файл ко н фигура ции в корневом


каталоге п риложения отсугствует и ли в нем н ет секции

ауге н ти фи ка ции н а осн ове форм, то уги лита базу да нн ых н е создает.

Для то го, чтобы п роверить работос п особность созда нн ой локальн ой


базы да нн ых, выпол ни те следующее:

• ~3апусти те угили ту WAT кома н дой Website/ASP.NET


Сопfigшаtio п
• r;.:Fнa вкладке Ноше щелкните на гuперссылке Provider
Сопfigшаtio п, чтобы п ерейти на вкладку Provider
• ~ a вкладке Provider щелкните н а гuперссылке Select а single
provider for аП site management data
• ~ сге н е р ированн ом стр а н ицей
ManageConsolidatedProviders.aspx отклике щелкн ите на гuперссылке
Test

~ ASP.Net Web App~catlOn AdmllllstratlOn - Мicrosoft Internet Explorer


Ае Edt View Favootes TOJIs НеР

~ Seэ:сh (ij Favoo:es

Use th is page to select а p гovideг foг stoгing site management


data.

Provider
r. AspNetSqlProvider Test
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

В р езультате стра ница пришлет ответ, что созданная нами локальная


база да н н ы х функционирует нормально.

Важно отметить, что хоть уг и ли та WPJ' автоматически создала базу


да нны х для подцержки аутентификации пользователей сайта, но эту
базу мы можем р асширять и для использова ния в других ц елях,
добавляя в нее соответствующие таблицы и хранимые процедуры.
Среда испол н е ния ASP.NET БУдет н адежно защищать эту базу от
постороннего вмешательства.

Добавление в хранилище БД новых пользователей


через утилиту wкr

На да нно м эта п е мы р ассмотри м интерактивный способ добавления


пользователей с при ме нением угилиты WАт. В дальн е йшем можно
будет создать свои администра тивны е страницы для пр о грамм н ого
добавления польз ователе й в это хр анилище , используя классы
Membersh i p . При этом нужно помнить, что хр анилище
удостов ере ний БУдет размещаться н а удале нно м сервере и подцерживать
его мы будем как Удале нны е пользователи либо через WAT, л и бо через
собственные адми нистр атив ны е страницы, также хранящи еся на
сервере.

Для создания новы х ауге нтифицированны х поль зователе й через


угилиту WAT выполните следующее:

• r;.:.=в п анели Solution Explorer щелкните на пиктограмме ASP.NET


Сопfigша tioп, что бы за п уст ить угилиту WAT
• ~ ерейдите на ВЮJaДКУ Sесшitу и щелкните н а 2иперссылке
Create user

По яв и тся следУЮЩИЙ отклик угили ты WAT

ее,
В.М. С""",,,В

А.,

<-B.,J.
МХ."

ASP
EcI\
~
У,,",

..
Fмcr ш

~ :Q
Tcd:s f-I:tJ
[1J Gj , :dSM-сh ~f.v"",,, 13'""w C:f , ~ - Ы
- ---.;....;
i;;I ~ , D
CD h\tp: /Ao<;ohJ,t: 1129/щ), ,-.,twеЬrnпn"'''''СLrI:yIu,,,,,/illJ,,,,, ",,)х

Т- "icb Sitc Administration Тоо1


""'----
--,.
Про,раммupoвtJNШ' 110 ASP.NET

d9I2<I

Add а user Ьу entering the user's Ш, password, and e-mail


address о п tllis page.

Create User Roles

Sign Up for Your New Account Roles аге not enabIed.


User Name:
Pass\..... ord: г------­
ConArm Password: г------­
Е- mа i l: г-----
Security QuеstiОП: г-_ _ _ _ __
Security Answer:

I Creet~e User

~ Active User

Сообщение на страниц е предлагает ввести имя ПОЛЬЗ0 ваmеля , пароль с


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

в yrилите за полем ввода пароля закреплен вал uдаmор для контроля


соблюдения требований к строгости пароля. По умолчанию настройка
вали даторов пароля такая , что пароль должен им еть длину не менее 7
символов. Причем , как минимум один из символов должен быть
неалфавитно-цифровым , наприм е р , символ &. Э ТО обеспечивает
минимально необходимую строго сть пароля. Позднее мы рассмотрим ,
как в конфuгурацuонном файл е можно менять принятые по умолчанию
на стройки Membership, которые , в том числе , БУдyr влиять и на
поведе ние WАт.
ее,
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

• ~Заполните поля страницы для добавления в хран илище одного


по льзователя со следующими характеристиками

User Name: admin


Password: Root&Root
Соnfirm Password: Root&Root
E-mail: Dia/og-Sеrvk:е@List.гu

Sесшitу Qllesllon: У Вас продается славянский шкаф?

Sесшitу Answer: Шкаф уже продан , осталась только тумбочка!

и щелкните на кнопке Create User

После этого действия новый пользо ватель будет создан в базе данных.

• u;.;rв появившемся ОТЮJИке щелкните на кнопке Сопtirше, чтобы


вернугся к инт е рфейсу доба вл ения следующего пользователя,
либо закройте WAT

Страница регистрации

На да нном этапе для проверки ауг е нтификации с использованием API


Memb ership и хранилища БД мы воспользуемся страницей регистрации
MyLo gin.aspx, скопированной нами ранее из предыдущего проекта. Ее
нужно только немного модифицировать.

• ~ одифицируй:те страницу регистрации MyLogin.aspx, чтобы


код стал таким

<%@ Page Langllage="C#" EnableViewState=''fulse'' %>

<script гunat= "server''>

protected void LoginAcllon_Click(object sender, EventArgs е)


{
trus.ValidateO;11 Испол нить валидаторы на сервере
if (!this.lsValid)11 Оценить фrJаг достовер но сти
геtшп;11 Отправить назад как есть

,СО
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

// Извлечь из базы да нны х и сравнить с введенным


if (Membership. Validate User(UsemameText.Text, PasswordText. Те;;:
{
// Создать временный сооkie-набор (второй параметр falseJ
// за писать в него метку аугентификации и перенаправить
// на исходную запрошен ную страницу или MyDefault.aspx
// с созданием соосkiе-набора только на п ериод сеанса
F о rmsAuthe поса tio п. Red irectFro mLo giпР age(U sernameТе xt. Те XI
)
.Is.
{
HtmlGenericControl message = new НtmlGеneгiсСопtгоЮ;
message.InnerHtml = "< Ы style='color: Red'> Неверное имя ил!
fo гтl. С о ntro Is. Add (message );
}
}
</script>

<html XmInS= 'huр ://www.wЗ.or!j'1 999/xhtml' '>


<head id=''Неаdl'' runat="server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id="forml " nmat="selVer''>
<div style=''text-align: center">
<h2 >
Введите свои имя и пароль < 1h2 >
<asp:Panel ID='MainPanel" runat="selVer" BorderColor="Silver"
Bord erS tyle= ''Ridge''
BorderWidth="2px" Height=''90px'' Width= "4 1 2рх' '>
чаЫе border=''O'' ceUpadding="5" cellspacing=''O'' style=''width
чг>

<td>
&nbsp;&nbsp;&nbsp;
</td >
<td align=''right'' hеight= "4З" style= 'width: lб 7рх">
Имя & пЬ sр;пользователя : </td >
<td>
&nbsp; <asp:TextBox ID='UsernameText" nmat="seIVE

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

</td >
<td>
< asp :Req uired F ieldVa lida to r ID= 'U sername Req uired V<
runat= "server" С о ntro ГТо Validate=' U sегnaше Text"
Display=''Dynamic''
ErrorMessage='He заполнено поле ''Имя пользOI
тооrПр='nустое поле ввода"> *
</asp:RequiredFieldValidator>
< asp :RegularExp ressio nValidato r ID= 'U semame Valida I
runat= "server" С о ntro rro Validate= 'U sе гnaше Text"
Display=''Dynamic'' ЕггогМеssаgе=''Неверное имя
ТооГПр="Допустимы буквы , цифры , пробелы и
ValidationExpression="[a- яА- я \w l ]*''> *
</asp:RegularExpressionValidator>
</td >
</tr>
<tr>
<td>
&nbsp;&nbsp;&nbsp;
</td >
<td align=''right'' hеight="4З" style= 'width: lб 7рх">
&пЬsр;Пароль:</td >
<td>
&nbsp; <asp:TextBox ID=''PasswordText'' runat="serve
TextMode=''Password'' />
</td >
<td>
<asp:RequiredFieldValidator ID="PwdRequiredValidat(
runat= "server" С о ntro rro Validate= ''Р asswo rdText"
Display=''Dynamic'' ErrorMessage='He запол нено ]
ТооГПр='nустое поле ввода"> *
</asp:RequiredFieldValidator>
<asp:RegularExpressio nValidator ID=''PwdValidator'' n
СО ntro rro Validate= ''Р asswo rdText"
Display=''Dynamic'' ЕггогМеssаgе=''Неверный пар
ТооГПр=''Используются недопустимые симвош
Vаlidа tiоnEхргеssiоп='[а-яА- я \w l !"$&атр;/()= \- 7\
</asp:RegularExpressionValidator>
</td >

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</tr>
</tabIe>
< а s р:Вuttоп ID =''Вuttопl '' nmat="server" Техt='Отправить "
ОпСliсk= "LоginAс tiоп_ Сliсk" />
</asp:Panel>
<asp:Label ID="lb lResult" nmat= "server" />
</div>
<asp:ValidationSummary ID='ValidationS lll11I1liJryl" nmat= "server" /:
</fonn>
</body>
<lhtml>

Листинг. Код страницы регистрации MyLogin.aspx


• ~3апустите пр иложе ни е с любой стра ницы и введ ите учетную
запись, сохра н е нн ую нами р анее в базе дан ны х
User Name: admin
Password: Root&Root
• r;;;?c помощью угили ты WAT добавьте в хранилище еще несколько
по льзо вателей и убедитесь, что ауге нтификация на основе
Membership и хр анилища удостоверений в БД работает

При добавле нии новых п ользователей следует иметь ввиду, что имя
пользователя сохраняется в поле UserName реляцион н ой таблицы
aspnet Users и является основой для ф:J р мирован и я п оля Userld
как первиЧИО20 ключа. Поэтом у все пользователи д олжны иметь
уникальн ы е имена.

• ~ панели Server Explo rer установи те соедииение с базой данных


ASPNETDB
• ~Для таблиц aspnet Users и aspne t _ Me mbe r ship
выполните командУ Slюw ТаЫе Data контекст н ого меню
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

8 [j] Оаи СonП€Cооns


8· [1, ЛSРNEТDВ.МDF
i±J... Dаыbзsе Diag-ams
В··· Tables
riJ· 1m aspnet_ApplicabOns
~ . !EJ aspnet_Membership
i±J .. IEI aspneCPaths
~. I!!:J aspnet_Personalizat:ionAIIUsers
$. liI aspnet_Personalizat:iorf'erUser
i±J . !Е) aspnet_Proftle
i±J .. !ёI aspneCRoles
CiJ lIiI asDГlet S(;hеn1аV,~sюns
~ ..
i±J . Add NеwТюlе
!В ..
Лdd New Tr~ger
$. . LJ
~ ... LJ New QU€fY
I±J ... Оpen таЫе Demibon
m·· Smw Table Dаы
$. .
I±J ... Сору

Х Delete
[iJ Rе1Тesh
lШ!i Properties

После таки х действий откроются таблицы aspnet Users и


aspnet Membershlp, в кото ры х мож н о най ти инф:J р ма ц ию о
созд ан н ы х пользователях. Для то го , чтобы ув и дет ь структуру табли ц ,
следует вы п олн ить для ни х кома н ду Ор е п Та Ые De finition ко нтекстн ого
ме н ю.

Про г раммное уп р авле ни е аугентификаци ей с


В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

использованием АР ! Membership

Ин терфейс AP I Membersrup включает в себя следующие класс ы


п ространства имен Sys te m. Web . Secur i ty :

1. Membe r ship - статичесЮ1Й класс , имеющий ряд полезных


методов управления nОЛЬЗ0вателями

2. Membe r shipCreateUserE x ception исключение .


генерируемое ошибкой создания пользователя (н а п ример , с уже
существующим именем)
з. Membe r shipPasswordE x ception исключение п ри

невозможн ости извлечения пароля

4. Membe r shipUse r объект этого масса соде ржит всю

инqюрмацию о п ользователе и возвращается методом

Membe r ship . Ge t User()


S. Membe r shipUse r Col l ection - коллекция пользователей ,
извлекаемая методом Membe r ship . Ge t AIIUsers ( )

б. Membe r shipProvider - баэовый класс для п ос тавщиков


данных
7. Membe r shipProviderCollect i on - коллекция доступ ных
для при лож е н ия поставщиков н а да нной машине
8. SqlMembershipProv i de r - поставщик для работы с базами
да нных SQL Server
9. ActiveDi r ecto r yMe mbe r shipP r ov i der - по ставщик дл я
р аботы со службой АсПvе Directory
10. ActiveDirecto r yMe mbe r shipUse r масс подцержЮ1

по льзо вателя, ра с ширенный для р аботы со службой АсПvе


Directory

Ис п ользуя API Membersrup , можн о п рограмм н о ре шать, например ,


следую щие задачи:

• С оздание , редакти рование и удаление пользователей


• И звлечение с пи сков пользователей со вс е й п одроб н ой
инqюрмацией , занесенной при создании

Создани е и удаление пользователей

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

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

п ере гр уже н н ы е статические методы Cr eateUse r () и

DeleteUser( ) ЮJасса Membe r sh i p . Нуж но создать

адм инис тративны е страницы , содержащие тр ебуемые поля для ввода


инфо рма ции . Поля можно контролировать валид аторалш , хотя это и
н еобязатель но , поскольку пользов ат ься такими страницами придется
нам и мы будем твердо соблюдать правила ввода.

Метод CreateUser () и меет н есколько перегрузок, из которы х


простейшая принимает толь ко имя и пароль. В то же время более
пол ны е перегрузки тр ебуют ввода кон тр ольного вопроса и ответа на
н его. В самой полной nерегруlке метод CreateUser () содержит
эюемпляр п ереч и слен и я Membersh i pC r eateS t atus в качестве

выходного параметр а , поз воляющий про а н ализи р овать причин у


ошибки в случае ее возникновения. По умолча нию требуется применять
наи более полную п ерегрузку метода CreateUser () , ВЮJючающую
контрольный вопрос и ответ, чтоб ы избежать выброса ИСЮJючения
Membersh i pC r eateUse r Ex cep t i on .

Удале ни е пользователя в ыполн яется методом

Membersh i p . DeleteUser (st r ing) , которому п ередается в

качестве пар аметра имя пользователя. Польз о в ател ь безвозвра тн о


удаляется и з всех табл иц вместе со всей связанной с ни м инфор маци ей.

в качестве при мера создадим собственную страницу добавле ни я ,


и меющую а н ало гич ную функциональность с WAT, и отдельно страницу
удалени я поль зователя в БД. Для пр остоты эт и стр аниц ы мы
п еределаем из стран ицы регистр а ции MyLogin.aspx.

• г;.:.=Скопи рУЙте страницу MyLogin.aspx и присвойте копии и мя


AddUserMe mbership . asp x

Провайдер базы да нны х не добавляет новы х п ользователей, если


пароль имеет длину мен ее 7 символов и есл и среди ни х нет хотя бы
одного н еалфав и тно -цифро вого си мвола. Для проверки выполнения
этого условия, а также для тренир овки, закрепим за пол ем пар оля

кодируемый элеме н т пров ерки достове рн ост и Custo mVal i dato r . С


по мощью этого элемента реализуем проверку достов ер нос ти на ЮJиен те

и на се рв е р е .
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Неалфавитно-цифровые с и мволы пр едставим в виде АSСII-кодов


согласно следую щей та бл иц е

Набор неалфавитно­
цифр овых символов
ASCII
0123456789
о

1
2
3 ["#$%&'
4()* + . /
5
6 <=>? @
7
8
9 [ \ ] А _

10
11
12 { I } -

Строка АSСII-кодов н еалфавитно-цифров ы х с и мволов на JavaScript


будет такой:

уа г rюnAJphaпшnе г iсС hа га сtе rs S tring = 5 tring. frо шС hаrCоdе(33,34 ,3S,36,37,:


58,59,60,61 ,62,63,64,91,92,93,94,95, 123,124,125, 126);

• ~ еределай те интерфейсную и кодовую части стра ницы , чтобы


она стала такой

<%@ Page Language="C#" EnableViewS tate=''fu lse'' %>

<script runat= "server''>

protected уою Page_Load(object sender, EventArgs е)

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

{
// Вынесли из интерфейсной части из-за большой ширины ш
раsswогdVаlidаtог.ЕпогМеssаgе :=
''Пароль долже н иметь длину не менее 7 символов"
+ "и содержат ь хотя бы один н еалфав и тно -ц ифровой СИМЕ
}

protected void AddUserMembership_Click(object send er, EventArgs €


{
this.ValidateO;// Испол нить валидаторы на сервере
if (!this.lsValid)// Оценить фrJаг достовер но ст и
геtшп;// Отправить назад как есть

// Создаем эюемпляр перечисления


MembershipCreateStatus status ;

// Попы тка доб ави ть


try
(
Memb ership .C reate User(
usemame.Text,
password.Text,
email Text,
question.Text,
answer. Text,
true,
out status
);

IblResult.Text:= String.Empty;
switch (status)
{
case М embershipC геа te 5 tatus. Dup lica te UserN ате:
IblResultText := "Дублирован н ое и мя пользователя<Ьгf:::
goto default;
case М embershipC геа te 5 tatus. Ргоvid е гЕпо г:
IblResultText := "Ошибка П остав щика <Ьг/> ";
goto default;
default: // Даль ше ле нь анализировать
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

IblResuhText += ''пользователь не создан";


IblResuh.ForeColor = System.Drawing.Color.Red;
break;
case MembershipCreateStatus.Success:
// Выдаем успешную инф:Jрмацию
IblResuhText == ''пользователь'' + username.Text
+ "создан успешно!";
// Рекурсивно о чища ем все текстовые поля ввода
EmptyTextBo х( fопnl. С о ntro Is);
IblResuhText += "< Ьг/> Поля ввода о чищены";
break;
}
}
// Откат
catch (МеmЬеrshipСгеаtеUsегЕхсерtюп ех)
(
IblResult.Text:= "< h2 style='co lor: Rеd '> Ошибка создания пош
S ystem DiagnostKs. Debug. WriteLine(''Exception: "
+ ex.Message);
}
}

private уою ЕmрtуТеxtВох(СопtгоlСоПесtiоп controls)


{
foreach (Сопиоl ctrl in controls)
{
if (сиl is TextВox)
((TextВox)ctrl).Text = Suing.Empty;

// Идем в глубину иерархической цепочки и ищем до ч ерни


if (ctrLControls != null)
EmptyTextBo х( ctrL С о пио Is );
}
}
</script>

<script Ianguage=''C#'' runat= "server''>


// Еще один блок С#, хотя можно было ВЮlючить В блок по умолч~
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

// Проверка допустим ости пароля на сервере


// Обработчик события ServerValidate элемента CustomValidator
protected void passwordValidator_ServerValidate(object sошсе, Serve
{
string data = args. Value;

// Установить начальное значение флага достоверности


args.lsValid = fulse;

// Проверить длину пароля


if (data.Length < 7)
геtшп;

// Проверить наличие неалфавитноцифрового символа


// Формируем массив неалфавитноцифровых символов по ю
// ч тобы не связываться с инт ерпретируемыми символами
int[] поnAlphапшneгiсСhагасtеrsСоdе =
{33,34,35,36,37,38,39,40,41,42,43,44,45,46,
58,59,60,61 ,62,63,64,91 ,92,93,94,95,123, 124, 125, 126};

// Перебираем символы пользовательского ввода


foreach (char ch in data)
{
for (in! i = О; i < nonAlphanumericCharactersCode.Length; i++ )
if (ch == Сопvеrt.ТоСhaг(поnAlp hа пшneгiсСhагасtеrsСоdе[i]J
{
// Пар оль допустим
args.lsValid = tлJе ;
геtшп;

}
}
}
</script>

<script Ianguage='Javascript" type=''text/javascript''>


// Проверка допусти мости пароля на ЮJИенте. Работает при вкл
// по умолча нию свойстве EnableClientScript элемента CustomVal

funсtioп VаlidаtеРа sswогd(sо шсе , args)


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

(
// Расщепить строку на масс ив символов с пустым разделите.
уаг data = args.Va!ue.split('''');

// Уста нови ть начальное з нач е ни е флага достоверности


args.lsValid == fulse;

// Пр ове рить длину пароля


if(data.length < 7)
геtшп;

// Пр ове рить наличие н еалфав и т ноцифрового символа


// Формируем строку неалфавитноцифровых символов по их
// ч тобы н е связываться с инт ер пр етируемыми символами
уаг поnAlp hапumе гiсСhaгас tегs Striпg=
5 tring. ~o те ШГС оdе(3З, 34,35,36,37,38,39,40,41 ,42,43,44,45,.
58,59,60,61,62,63,64,91,92,93,94,95,123,124,12:
for(var ch iп data)
(
if(поnAlphапшneгiсСhагасtеrsS triпg.iпdехО f( data[ ch]) ! = - 1)
{
// Пароль допустим
args.lsValid = tПJе ;
геtшп;

}
}
}
</script>

<html XmInS= 'http ://www.w3.or!j'1999/xhtml''>


<head id =' 'Неаdl '' гuпаt= "s еrveг''>
<tide >Добавление пользоват елей в БД </tide>
<lhead>
<body>
<form id ="form1 " nmat="selVer''>
<div stу!е=''tехt-аligп : сепtег">
< Ы ю =' 'Н 2 _1 '' nmat= "selVer''>
Введите учетную запись для добавления пользователя <,
< аsр:Рапе! ID ='МаiпРа пе !" runat="selVer" BorderCo!or="S ilver"

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

BorderWidth="2px" Height=''90px'' Width= 'З64рх' '>


чаЫе border=''O'' ceUpadding="5" cellspacing=''O'' style=''width
<tr>
<td>
&пЬsр;&пЬsр;&пЬsр;
</td >
<td align=''right'' hеight="4З" style= 'width: 224рх">
Имя&пЬ sр;пользователя :
</td >
<td>
&пЬsр; < аsр:ТехtВох ID =''usе rпаme '' nmat="server" />
</td >
<td>
<asp:RequiredFieldValidator ID="usегпаmеRеquirеdVа
ruпаt= "server" Сопtrоrrо Validate=''usemame''
ErrorMessage='He за полнено поле ' 'Имя пользOI
Disрlaу=''Dупаmiс''>* </аsр:RеquirеdFieldVаlidаtor >
</td >
</tr>
<tr>
<td>
&пЬsр;&пЬsр;&пЬsр;
</td >
<td align=''right'' hеight="4З" style= 'width: 224рх">
&пЬsр;Пароль:
</td >
<td>
&пЬsр; < аsр:ТехtВох ID="password" ruпаt="sеrvег " />
</td >
<td>
<asp:RequiredFieldValidator ID="passwordRequiredV~
ruпаt= "server" Сопtrоrrо Validate=''password''
ErrorMessage='He за полнено поле ' Пароль'·
Disрlaу=''Dупаmiс''>* </аsр:RеquirеdFieldVаlidаtor >
<asp:CustomValidator ID=''passwordValidator'' ruпаt= "
СО пtго rro Validate= "passwo rd"
Disрlaу=''Dупаmiс''
С lie пt Validatio пF uпсtioп= 'Validate Р assword"
ОпSеrvегVаlidаtе="раsswогdVаlidаtог_SеrvегVаlidа
ее,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

</td >
</tr>
<tr>
<td>
&nbsp;&nbsp;&nbsp;
</td >
<td align=''right'' hеight= "4З" style= 'width: 224рх">
Е- mail:</td>
<td>
&nbsp; <asp:TextBox ID= "email" runat= "server''></asp
</td >
<td>
<asp:RequiredFieldValidator ID="emailRequiredValidat
runat= "server" Controrro Validate="email"
ErrorMessage='He за полнено поле ''E-mail'"
Display="Dynamic''>* </asp:RequiredFieldValidator>
<asp:RegularExpressio nValidator ID="emailValidator" Il
СО ntro rro Validate= "ета П" Епor М essage= ''Н ев ерн 1
ValidationExpression='\ w+([ - +. ']\w +)* @\w+([-.]\w·
Display="Dynamic''> * </asp:RegularExpressionValid;;
</td >
</tr>
<tr>
<td>
&nbsp;&nbsp;&nbsp;
</td >
<td align=''right'' hеight="4З" style= 'width: 224рх">
КОНТРОЛЬНblЙ вопрос:</td >
<td>
&nbsp; <asp:TextBox ID="question" nmat="server"></.
</td >
<td>
<asp:RequiredFieldValidator ID="questionRequiredVali
runat= "server" СопиоГГо Validate="q uestion"
ErrorMessage='He за полнено поле ''Ко нтр ольнь
Display="Dynamic''>* </asp:RequiredFieldValidator>
</td >
</tr>
<tr>
ее,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<td>
&nbsp;&nbsp;&nbsp;
</td >
<td align=''right'' hеight="4З" style='width: 224рх">
КОНТРОЛЬНblЙ OTBeT:</td>
<td>
&nbsp;<asp:TextBox ID="answer" runat="server' '></a ~
</td >
<td>
<asp:RequiredFieldValidator ID="answerRequiredValid
runat= "server" Controrro Validate="answer"
ErrorMessage='He за полнено поле "Ко нтр ольнь
Display=''Dynamic''>*</asp:RequiredFieldValidator>
</td >
</tr>
<tr>
<td colspan="4" align="ce nter">
<asp:Button ID ='Ъ tnAddUsе г" runat="server"
Теxt="Добавить" OnClick="AddUserMemberstllp_
</td >
</tr>
</table>
</asp:Panel>
<asp:Label ID="lb lResult" runat="server" Font- Bold='True"
Fопt-Size=''Lагgе'' ForеСоloг=''Вluе'' />
</div>
<asp:ValidationSummary ID='ValidationS lll11I1liJryl " runat="server" /:
</fonn>
</body>
<lhtml>

Листинг Административная страница


AddUserMemЬership.aspx добавления пользователей в БД

• r;.:.=вbl п олните страниц у AddUserMemberstllp .aspx и у6едитесь в


р абото сп особности рассматриваемо го механизма добавления
по льзо вателей в БД SQL Server

Те п е рь рассмотрим вопрос удале ни я п ользователей . Он намного пр още ,


ч ем создан и е. Нужно только при менить метод

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

5 ystem Web . Sесшity.МеmЬеrship . Delete User(), который имеет две

перегрузки :

• publ i c static bool DeleteUser(st ri ng


username) - Удаляет п о имени п ользователя все связанн ы е с

ним данные из всех таблиц БД


• publ i c static bool DeleteUser(st ri ng
username , bool dele t eAl l Re l atedData) - Удаляет
п ользователя только из таблицы asp net Use rs, если фла г
р авен f а 1 s е . И наче удаляет все связанные с п ользователем
данные при флаге рав н ом t rue

Обе перегрузкu возвращают t r ue , если п ользователь усп ешно Удален,


и н аче f alse .

• ~ азработайте из ко п ии ст р ани ц ы MyLogin.aspx


адм и нист р ативную ст р аницу удаления п ользователей
DeleteUserMembership.aspx, которая БУдет пр и мер н о такой

<%@ Page Language="C#" EnableViewState=''fulse'' %>

<script runat= "server''>

protected void DeleteUsecClick(object sender, EventArgs е)


{
if (Membership. Delete User(usemame. Text))
{
IbIRеsult.Теxt= ' Пользователь " + username .Text
+ " успеUllЮ удален";
username.Text == "";
}
else
{
IbIResult.Text = ' Пользователь не удален";
IbIResult.ForeColor == System.Drawing.Color.Red;
}
}
</script>
ее,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<html XmInS= ' huр ://www.wЗ.or!j'1999/xhtml' '>


<head id=''Неаdl'' runat="server''>
<tide >Удале ние польз ователе й из БД </tidе>
<lhead>
<body>
<form id ="forml " nmat="server''>
<div style=''text-align: center">
<h2>
Введите имя удал яемого пользователя<lh2 >
<asp:Pane! ID ='МаiпРа пе!" runat="server" BorderCo!or="Silver"
Bord erS ty!e= ''Ridge''
BorderWidth="2px" Height=''9 0px'' Width= "4 1 2рх' '>
чаЫе border::::''O'' сеUpаddiпg="5" сеllsрасiпg=''О'' style::::''width
чг>

<td align=''right'' hеight="4З" style='width: lб 7рх">


Имя&пЬ sр;пользов ателя : < /td >
<td>
&nbsp;<asp:TextBox ID=''usemame'' runat="server" 1>
</td >
</tr>
</tabIe>
<asp:Button ID =''Вuttопl '' nmat="server" Техt=''Удалить''
OnClick= "DeleteUser_ С lick " 1></asp :Рапе!>
<asp:Labe! ID="lb lResult" nmat="server" Font- Bold='True"
Font- S ize=''Large'' F orеСоюг= ''В!uе''>
</asp:Labe!>
</div>
< /fопn>
<!body>
<lhtml>

Листинг Административная страница


De l eteUserMembership.aspx удаления пользователей из БД

• ~ с п ы тайте стр аниц у удале ни я пользов а теле й

И звлечени е из хранилища спи сков по ль зователей

Для получе ни я сп ис ка п ользо в ателей п ри ме н яют метод

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Membersh i p . GetAI I Users () , а для извлечения ко н кретного

п ользователя - метод МетЬе r s h i Р . Ge t Us е r ( ) .

Ра с смотрим пример , в котором бу,цем ис п ользовать элемент Gr i dVi ew


для п редставления п ользователей в виде таблицы.

• r;:;='Добавьте к nроекту страницу GetUsersMemberstllp.aspx и


назначьте ее стартовой
• ~3аnолните страниц у следующим кодом

<%@ Page Language=="C#" EnableViewState==''fulse'' % >

<script runat== "server''>

// Вынесли поле для видимости в обработчиках


MemberstllpUserCollecllon myUsers == new MemberstllpUserCollecllol

protected void Page_Load(object sender, EventArgs е)


{
// Скр ываем табл иц у деталей
tabIeDetails. VlSible = {аlsе;
lblUser.VlSib1e :::: {аlsе;

if (checkUser.Checked)
{
// Извл екаем одного пользователя
if (txtUser.Text.Length == О)
{
lblUsersList.Text :::: ''Введ и те имя польз ователя";
геtшп;

try // Попытка
(
string user = Server.HtmlEncode(txtUser.Text);
myUsers:::: new MemberstllpUserCollectionO;
myU sers .Add(M етЬ erstllp. GetU ser( user));
}
catch // Откат
,ее
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

{
IblUsersList.Text :::: ''пользователь не найден";
геtшп;

}
}
.Is.
{
// Извлекаем всех пользователей
myUsers :::: Membersrup.GetAllUsersO;
}

// Подключаем к сетке извлеченную информации и наполняеJ


UsеrsGгidViеw.Dаta Sошсе:::: myUsers;
UsersG гю View.Data В iпdО;
}

// Обработчик щелчков на ссылки столбца отображения деталеi


protected void UsегsGгidViеw_ Sеlесtеdl пdе хСhaпgеd(оЬjесt sепdег, ]
{
if (UsегsGгidViеw.Sеlесtеdlпdех >= О)
{
// Заполняем интерфейсные элементы отображаемой инфо
// адресуясь к конкретному пользователю по ключевому им
// заданному параметром DataKeyNames::::'UserName" элем е
MembersrupUser сurrепtUsег ::::
myU sers[ (striпg) U sersG гю View.S е lected Уа lue];
IblUserName.Text:::: сurrепtUsег.UsегNаmе;
IblEmail Text :::: currentUser.Email;
IbIPasswordQ uestion. Text :::: сurrепtUsег. PasswordQuestion;
IblLаstLоgiпDаtе. Text :::: сurrепtUsег.LаstLоginDаtе .ToLo ngDate~
txtСопuneпt.Техt:::: сшгепtUsег.Сопuneпt;
checklsApproved.Checked = сurrепtUsег.lsАрргоvеd;
checklsLockedOut.Checked == сurrепtUsег.lsLосkеdОut;

// Включаем видимость таблицы деталей


tabIeDetails. VlSible :::: true;
IblUser.VlSible = true;
}
}
ее ,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

</script>

<html xmIns= ' huр ://www.wЗ.or&,1 999/xhtml" >


<head runat= "server''>
<tide >Untitled Page</tide>
<lhead>
<body>
<form id= "forml " nmat="server''>
<div>
<h2 >
<asp:Label ID="lb IUsersList" runat= "server" Font- Bold= ''true''
Теxt="С пи сок зарегистрир оваННbl Х поль зователей"><1
<1h2>
< р > КонкреТНblЙ польз ователь:
<asp:C heckBox ID="checkUser" runat= "server" />
< asp:TextВox ID=''txtUser'' runat="server''></asp :TextBox>
<asp:Button ID ='ЪtпUsе г " nmat="server" Техt='Получить " />
<asp:GridView ID='UsersGridView" nmat="server"
DataKeyN ames='UserN ате"
АutоGе пегаtеСо lшnns ="Fаlsе"
О nS е 1ected IndexC hanged = 'UsersG гю View _ 5 е 1ected IndexC lli
<Columns >
< asp:BourкlFiekl DataField='UserName" Н е аdегТеxt=''ИМ5
< asp:BourкlFiekl DataField=''Email'' HeaderText= "email" />
< asp:BourкlFiekl DataField =''C reationDate'' HeaderText="C
<asp:C ommandField ShowSelectButton='True " HeaderText:
SеlесtТехt= ' 'Показать '' />
</Co lumns>
</asp:GridView>
<h2 >
<asp:Label ID="lb IUser" runat= "server"
Теxt=' 'Подробности для Вbl дел енного польз ователя"
Visible="False" Font- Bold= ''true''></asp :Label>
<1h2>
<tab1e id=''tableDetails'' bordeF "l " bordercolor=''#OOOOFF ''
width="100%" nmat="server">
Чг>

<td width= "50% ">


Пользователь:< /td >
ее,
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<td>
<asp:Label ID="lb IUserName" runat="server''></asp:Lab(
</tr>
Чг>

<td width= "50% ">


email:</td >
<td>
<asp:Label ID="lb lEmail" runat="server"></asp :Label></t
</tr>
Чг>

<td width= "50% ">


КОНТРОЛЬНblЙ вопрос:</td>
<td>
<asp:Label ID="lb lPasswordQ uestion" nmat="server"></.
</tr>
Чг>
<td width= "50% ">
Дата по след ней регистрации: </td >
<td>
<asp:Label ID="lb lLastLoginDate" runat="server''> </asp:I
</tr>
Чг>

<td valign=''top'' width="50%''>


Комментарии:< /td >
<td>
< as p :TextВox ID =''txtСопunепt '' runat="server" TextМodE
Width="100%"> </asp:TextВox> < /td >
</tr>
Чг>

<td width= "50% ">


Проверенный :</td >
<td>
<asp:CheckBox ID="checkIsApproved" runat="server" f;
</tr>
Чг>

<td width= "50% ">


Заблокирован :</td >
<td>
<asp:CheckBox ID="check IsLockedOut" runat="server" ,

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

</tr>
</tabIe>
</div>
</fопn>
</body>
<lhtml>

Листинг Код страницы GetUsersMemЬership.aspx для


извлечения пользователей

Интерфейсная часть стра ницы пр едставлена элементом Gr i dVi ew и


текстовыми метками, спозиционированными в серверной таблице .
Значения пар аметров DataFi eld элемента Gri dVi ew представляют
собой имена полей таблиц aspnet Users и aspne t _ Me mbe r ship
базы данных

'"
"'.'",",~"""."",,"" ASP. N ET

13 - [j] Оаи Corn:ctJons


6 -- (],. ASPNEТDB,rvDF
ltI- D Database О~гатз
~" L:.i Таbl€з
[] aspneCA~catiOns
[] aspneClYJembersh,:)
LiJ Appicabonld
Ш UserId
Li1 Password
lI] PasswordFormat
LIJ PasswordSalt
L!] МOblePIN
LiJ Emai
Ш LowffedEm al
ш PasswordQuesbon
ш PasswordAnswer
LIJ IsAwoved
LIJ IsLockedOut
I!J createDate
ш LastlOJпDаtе
Ш LastpasswcrdCh~cDate
ш L.зsti...осkoutDаtе
LiJ faledPasswordAttemptcount
LIJ Fail€dPasswordAttempt\NГкbwStart
LIJ Fail€dp asswr:xdдrnwer А tte mptcomt
I!J Fail€dPasswcrdAnswerAttemptwnd::JWStart
LiJ Comment
1m aspnet_Patlls
!::I аsрnet_Рerson ai zаtioпА J.Jsегs
[] aspneCPersonEizationPerUser
" [] aspneCProfie
" I:E] aspneCRoles
[] аsрneСSch€mаvегsa-rs
aspnet_Users
Li1 Ap~cabalId
L;j UserId
cm ф'@1§
lI] LoweredUserName
I!J МObleAlias

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

Установка в элеме нт е управления Gr i dVi ew свойств а


DataKeyNames= " Use r Name " по зволяет извлекать значения поля

Use r Name ч е рез Gri dVi ew . Se l ectedVa l ue , что очень удоб н о


при получении подроб нос тей о конкретном польз ователе из коллекции
пол ьзователей .

Метод Me mbe r sh i p . GetUser ( ) возвращает объект запрошенного


пол ьзова теля , свойства которого мы отображаем в текстовы х элеме н тах,
скомпонованных в табли ц е. Прив язка к свойствам объекта пользователя
выполня ется в об р аботч и ке собы тия Se l ec t edl n de x Changed
элемента управле ния Gr i dVi e w.

Р езул ьта т работы страницы GetUsersMembership.aspx БУдет при мерно


таким

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

~ Untltled Page - MICrosoft Internet Explorer


- -.....;...;
[Eie Cd' ,е. - е,"а"б "ОХ tjф -
.... Back ... ..... о (ш] G1 ~ Seif"ch [ij Favootes '9 Мeda @ :'8'" J &! ~ 7 О
AQj"ess 111 http://осзhJst: 11 24/WebSite2 1/Getlter~mber~,aspx
СШlСОК зареrистрироваииых пользователей

Конкретный пользователь: г rl- - - - - - - - , получ"ить- I

Имя email Создан Детали


adminDia10g-Sеrviсе@List.ru04.05.2008 12:41 :38 Показать
userl L@s.r 02.06.200812:10:47 Показать
user2 S@l.r 02.06.200813:05:31 Показать
user3 FGFGF@yty.com 02.06.2008 13:06:00 Показать
user4 S ist.ru 02.06.2008 13:38:27 Показать

Подробиости ДЛЯ вьщелеlПlоrо пользователя

ользователь: adтin

email: ia10 -Service ist.ru


у Вас продается славянсЮIЙ
онтроль:ны:й: вопрос:
аф?

ата последней еrис aцшr: 30 мая 2008 г.


о:мментарIШ:

ове е:нны::й:: '"


аблокирован: г
~~~~~~~~~~~~~~~~ ~

~1i:i"----------------ГГГ~ LОСЗ lltТinеt

Конфигурирование поставщика SqlMembershipProvider

И з влечение парол я напрямую через свойство не предусмотр е н о в


массе Me mbershipUser . Для это го существует метод
Me mbersh i pUser . Get Passwo r d () , который р аб отает только
то гда , когда постав щик SqlMembe rshi pProv i de r сконфигурирован
с пар а метр ом enablePasswordRetrieva l = " true " в

конфuгурацuонном файле Web.config.

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Наша задача - перенастроить п оставщик по умол чанию , создав для этого


поставщик того же типа , но с д р угими настройками. Н овый поставщик
в той же базе данных будет и меть доступ ТОЛЬЮ) к своим данным .
Включение параметра enab l e PasswordRetr ieva l = " true "
несовм естимо с настройЮ)й ра sswordForma t= " Hashed ", а долж н о
иметь з нач ения " Clear " или " Encrypted "

• ~ змените конфuгурацuонный файл , чтобы он прин ял


следУЮЩИЙ вид

<?xml version= "l.O" encoding=''utf-8'?>


< со пfigш аоо n xmlns= ''http ://schemas. mkroso ft.co m/. N etC о nfigшаtiо n/у2,
<system.web >
<compilation debug=''true'' 1>
<authentication пюdе=''Fогms' '>
<forms
name='MyCookieName"
10 ginU rl= ' 'М yLo gin.as рх "
d е faultU rl=' 'м yDe са ult.asp х"
protection="All"
timeout= ''2 0''
path= "I"
requireSSL= "fals e"
slid ingExpiration=" true"
cookieless="AutoDetect"
domain='"'
enableCrossAppRedirects=''fulse''>
</forms >
</authentication>
< !-- Временно заЮ)мме н т иров ал и , чтоб ы не требовал ре
<authorization>
<deny users='?"I>
</authorization>
-->
<membership defaultProvider= 'MyMembershipProvider''>
<providers>
<add name='MyMembershipProvider" co rmectionSt
enable PasswordReset=''true'' requiresQuestionAndJ
геqUn-е sU niquеЕmail="falsе" enablePasswordRetrie\

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

type= "System. Web.Security. Sq lМеmЬеrshipРгоvidе


/>
</providers>
</membership>
</system. web>
<connectionStrings>
<add name='MyMembershipConnString"
connectionString=''Data Sо шсе=)осаlhоst; Initia! Cata!og=
/>
</connectionS trings >
</соnfigшаtiоп>

Листинг Конфигурационный файл с новыми настройками

поставщика SqlMembershipProvider
• г;.:.='Добавьте новых пользователей с помощью нашей
административной страницы AddUserMembership.aspx
• ~ олучите из страницы GetUsersMembership.aspx копию с
именем GetUsersMyMembe r shipProv i der . asp x,
назначьте ее стартовой и добавьте в интерфейсную часть
те кс товую метку l blPasswo r d для отображения пар оля
• IJ$Добавьте в обработчик события Se l ectedlnde x Changed
строку заполнения метки

IbIPassword.Text == сшгепtUsег.GеtРаsswordО;

Обновление пользователей в хранилище

Если У нас есть экземпляр масса Me mbe r shipUse r, то мы можем


обновить е го свойства, имеющие аксессор set , а именно:

• Coтment
• Ema i l
• IsApp r oved
• Las t Activ i tyDate
• Las t LoginDate

Для этого используется статический метод


Membersh i p . UpdateUser() .

'"
В.М. С """,,,в Про,р а ммupoвtJNШ' 110 ASP. N ET

• ~ олучите из страницы GetUsersMembership.aspx ко пи ю с


Upda t eUse rM embe r sh i p . азр х
им е н ем

• ~С корр е ктируйте страницу UpdateUserMembership.aspx, чтобы


обновляемые параметры таблицы д еталей размещались в
те кстовых полях

• ~3акр еп ите за полем


t xt Email элементы пров е рки
достоверности RequiredFieldValidator и

Regu l arE x p r essionValidator

Окончательный код стра ни цы UpdateUserMembership.aspx будет таким

<%@ Page L апguagе= "С #" Епа ы lviеwst аtе= ''fаlsе' ' %>
<%@ lmport N аmеsрасе= "Systеm.WеЬ.Sес шitу" %>

<script nшa t= "sеrvег ''>

// Вы н есл и поле для в и ди мости в обработч и ках


MembershipUserCo llection myUsers = new MembershipUserCo llectionO;

protected void Page_Load(object sender, EventArgs е)


{
// С кр ываем та бл иц у детале й
tableDetails.Visib le := false;
lblUser.VlSible = false;

// И звлекаем всех пользователей


myUsers = Membership. GetAllUsersO;

// П ОДЮIюч аем к сетке извлече нн ую ин qюрмаци и и наполняем элеr-.


U sеrsG гidViеw. D а tаSошсе = myUsers;
UsersGridView. DataBindO;
}

// Обр а ботч и к щелчков на сс ы лки столб ц а отображе н ия д еталей


protected void UsersGridView_Se lectedIndexC hanged(object sender, EventA
{
if (UsersGridView.Selected Index >= О)
{
// 3а п ол н яем ин те р фейсн ы е элемен ты отображаемой инqю р ма Цl
,ОС
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP. N ET

11 а.цресуясь к конкретному поль зователю п о ЮIючевому имени ,


11 задан ном у па р аметром DataK eyN ames='UserName" элемента GI
MemberstllpUser curre ntUser =
myU sers[(string) UsersGridVIew. 5 е lected Value];
IblUserName.Text = currentUser.UserName;
txtEmaiL Text = сшгепtUsег.Еmail;
IblP asswordQuestion. Text = currentUser.P asswordQuesllon;
Ib lLastLoginDate. Text = сигге ntUser. LastLo ginDate. То Lo ngDate 5 tringO
txtComment.Text = currentUser. Comment;
check IsApproved .C hecked = currentUser.IsApproved;
check IsLockedOut.Checked = сшгепtUsег.lsLосkеdОut;

11 8ЮIючаем видимость табл ицы деталей


tableDetails.Visib le = true;
IblUser.VlSible = true;
}
}

protected void btnUpdate_ Click(object sender, EventArgs е)


(
if (UsersGridVIew.Selectedlndex >= О)
(
11 Адресуемся к выделенному пользователю
MemberstllpUser curre ntUser =
myU sers[(string) UsersGridVIew. 5 е lected Value];

11 Избавляемся от возможных управляющих символов


11 в пользовательском вводе
currentUser.Email = Setver. HtmlEncode(txtEmaiL Text);
currentUser.Comme nt = Sеrve г.НtmlEпсоd е(txtСОПШ1епt.Техt);

currentUser. IsApproved = check IsApproved.C hecked;

11 Сбрас ыв аем в базу данн ых


М emberstllp. U pda te U ser( currentU ser);

11 Обновить содерж им ое GridView из БД, пос кольку


11 этот обработчик выполнится посл е Page_Load
myUsers = Memberstllp .GetAUUsersO;11 И звлекаем пользователей

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

UsersGridView.DataBindO;
}
}
</script>

<html xmlns=''httр://www.wЗ.огgl1999/xhtml'' >


<head nmat= "server">
< title >Uпtitled Page</tide >
<lhead >
<body>
< fопn id="fопnl" ruпаt="sеrvег' '>
<div>
<h2 >
<asp:Label ID= ''lblUsersList'' nmat="server" Font·Bok:l=''true''
Техt=''Список зарегистрированных nользователей ''> </аsр:Lа

<1h2>
<asp:GridView ID='UsersGridView" гuпаt="sеrvег"
DаtаКеуNашеs='UsегNаme"

AutoGenerateColumns=''False''
О nS е lected lndexC hanged = 'U sersGridView_ S е lected 1ndexC hапgеd '~
< Соlшnns>
< аsр:ВоuпdField DataField="UserN аmе" НеаdегТеxt= ' 'Имя '' 1>
< аsр:ВоuпdField DataField="Email" HeaderText="email" 1>
<asp :ВоuпdField DataField= "СгеаtioпDаtе " НеаdегТехt="С оздан '
< аsр:СоmmaпdFiеk:l SlюwSеlесtВuttоп='Тruе" НеаdегТехt="Дет;:
SеlесtТехt='nоказать" 1>
</Соlшnns>
</asp:GridView>
<h2 >
<asp:Label ID= ''lblUser'' nmat="server"
Техt=''Подробности для выделенного пользователя "
VlSible=''False'' Font· Bold=''true''> </asp:Label>
<1h2>
<table id=''tabIeDetails'' border= "l " bordercolor=''#OOOOFF''
width="lOO%" nmat= "server''>
<tr>
<td width="50%''>
Пользователь: </td >
<td >

'"
В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

<asp :Label ID=''lblUserN ате" runat="server"></asp:Label></td


</tr>
< tr>
<td width="5 0%">
< fo nt со 10 г= "#00 00 F F "> email:</fo nt> </td>
<td >
<asp:TextBox ID="txtEmail" runat="server" Width= "100%">
</asp:TextВox >
< asp :Required F ie ld Validator
ID="Req uiredFieldValidatorl " runat= "server"
C ontrofГo Validate= ''txtEmail'' Display=''Dynamic''> *
</asp :Req uired F ie k:l Valida to г>
< asp :RegularЕхр ress io nValida to r ID= "Re gularExp ressio nУа lida t<
runat="server" СопиоfГо Validate= "txtEmail"
Display= ''Dynamic''
ValidationExpression= '\W+([ - + .']\W+ )* @\W+([-.]\W+)*\.\W+(
</asp:RegularExpressionValidator></td>
</tr>
< tr>
<td width="5 0%">
Контрольный вопрос:</td >
<td >
<asp :Label ID=''lb lPasswordQ uestion" runat="server"></asp :Lal
</tr>
< tr>
<td width="5 0%">
Дата последн е й регис трац ии :< /td >
<td >
<asp :Label ID=''lb lLastLoginDate'' runat="server"></asp :Label>·
</tr>
< tr>
<td valign="top" width= "50%''>
<fo nt color="#OOOOFF"> Комментарии :</font></td >
<td >
<asp:TextBox ID="txtComment" runat= "server"TextM ode='Mu
Width= "100%''></asp:TextBox></td>
</tr>
< tr>
<td width="5 0%''>

'"
в.м. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

< font со lor= ''#00 00 F F "> П ро вер е н н ы й :</fo nt> </td>


<td >
<asp:CheckBox ID="check lsApproved" runat= "server" 1></td>
</tr>
<tr>
<td width="50%''>
Заблоки р ован :</td>
<td >
<asp:CheckBox ID="check lsLockedOut" nmat= "server" 1></td :
</tr>
<tr>
<td colspan="2" align="center">
<aspButton ID=' ЪtпUрdаtе " nmat= "server" Теxt="Об новить "
ОпСliсk='ЪtпUрdаtе_Сliсk " 1></td>
</tr>
</table>
</div>
</form>
<lbody>
</html>

Листинг Код страницы UpdateUserMemЬership.aspx


В.М. С""",,,в Про,раммupoвtJNШ' 110 ASP.NET

Спиеок литераryры
1. Мэп,ю Mak-ДоналЬД, Марио lllnУШI а, Microsoft ASP.NET 2.0 с примерами на С#
2005 для профессuоналов, М.: 000 " И .Д . Вильяме" , 2006
2. Гле нн Джонеон, Тони Н ор1рОП, Разработка КIIиeHтcKиx веб-прuложенuй на
платформе Microsoft .Net Framework. УчеБНblЙ курс M icrosoft, М.: " Русс кая
редакция", СПб.: " Питер ", 207

з. БаЙДilчный с.с., Мал(>нIФ Д.А, ASP.NET 2.0: ceKpembl создания Web-приложенuй,


М . : CQrlOH- П РЕСС, 2007

""
В_М_ CHeтm. ПfЮ<'Р'НН'ЩЮlШмШ': ма ASPNET

Содержание

Титульная страница 2
Выходные данные 3
Лекция 1. ОСНОВЫ Visua1 Studio 2005 4
Лекция 2. Введение в Web-сайты 26
Лекция 3. Web-формы 62
Лекция 4. Се р верные элеме нты управления 124
Лекция 5. Применение сер верных элемен тов управления 183
Лекция 6. Поль зо вательские элеме нты управления 194
Лекция 7. Многокадровые элеме нты управления 260
Лекция 8. Программирование уровня приложения
308
ASP.NEТ

Лекция 9. С редства форматирования страниц 321


Лекция 10. Управление состоянием ASP.NET 427
Лекция 11. Основы ADO.NET 507
Лекция 12. Компоненты данных ADO.NET 568
Лекция 13. Привя зка данных ADO.NET 629
Лекция 14. Интерфейсные элементы ADO.NET 739
Лекция 15. Серверные элеме нты управления 753
Лекция 16. Работа с файлами и каталогами 786
Лекция 17. Карты сайта 790
Лекция 18. Безопасность 822
Список литературы 901

Вам также может понравиться