Skip to content

3. Вступ до веб-розробки ASP.NET

3.1. Introduction

У попередньому розділі було представлено принципи веб-розробки, які не залежать від використовуваної мови програмування. Наразі на ринку веб-розробки домінують три технології:

  • J2EE — це платформа розробки на Java. У поєднанні з технологією Struts, встановленою на різних серверах додатків, платформа J2EE використовується переважно у великих проєктах. Завдяки використаній мові — Java — додаток J2EE може працювати на основних операційних системах (Windows, Unix, Linux, Mac OS тощо)
  • PHP — це інтерпретована мова, яка також не залежить від операційної системи. На відміну від Java, це не об’єктно-орієнтована мова. Однак у версії PHP5 планується впровадження об’єктної моделі в мову. Завдяки простоті використання PHP широко застосовується в малих та середніх проектах.
  • ASP.NET — це технологія, що працює лише на комп’ютерах під управлінням Windows із платформою .NET (XP, 2000, 2003, ...). Як мова розробки може використовуватися будь-яка мова, сумісна з .NET, c.a.d. Їх понад десяток, починаючи з мов Microsoft (C#, VB.NET, J#), Delphi від Borland, Perl, Python тощо.

У попередньому розділі наведено короткі приклади для кожної з цих трьох технологій. Цей документ присвячений веб-розробці ASP.NET з використанням мови VB.NET. Ми припускаємо, що ця мова вам відома. Це важливий момент. Тут ми розглядаємо виключно її використання в контексті веб-розробки. Роз’яснимо це детальніше, розглянувши методологію веб-розробки MVC.

Веб-додаток, що відповідає моделі MVC, матиме таку архітектуру:

Image

Така архітектура, яка називається трирівневою або трикомпонентною, спрямована на дотримання моделі MVC (Model View Controller):

  • користувацький інтерфейс — це V (представлення)
  • логіка додатка — це C (контролер)
  • джерела даних — це M (модель)

Інтерфейс користувача часто є веб-браузером, але це може бути також автономний додаток, який через мережу надсилає запити HTTP до веб-сервісу та оформлює результати, які той йому надсилає. Логіка додатка складається зі скриптів, що обробляють запити користувача. Джерелом даних часто є база даних, але це можуть бути також прості текстові файли, каталог LDAP, віддалений веб-сервіс тощо. Розробнику вигідно зберігати значну незалежність між цими трьома компонентами, щоб у разі зміни одного з них інші два не потребували змін або потребували їх у мінімальному обсязі.

  • Бізнес-логіку додатка слід розміщувати в класах, відокремлених від класу, що керує діалогом «запит-відповідь». Таким чином, наведений вище блок [Logique applicative] може складатися з таких елементів:

Image

У блоці [Logique Applicative] можна виділити

  • клас-контролер, який є вхідними воротами додатка,
  • блок [Classes métier], що об’єднує класи, необхідні для логіки додатка. Вони є незалежними від клієнта.
  • блок [Classes d'accès aux données], який об’єднує класи, необхідні для отримання даних, потрібних сервлету, часто це постійні дані (BD, файли, сервіс WEB тощо)
  • блок сторінок ASP, що утворюють представлення додатка.

У простих випадках логіка додатка часто зводиться до двох класів:

  • клас контролера, що забезпечує взаємодію «клієнт-сервер»: обробка запиту, формування різних відповідей
  • бізнес-клас, який отримує від контролера дані для обробки та надає йому у відповідь результати. Цей бізнес-клас самостійно керує доступом до постійних даних.

Особливість веб-розробки полягає у написанні класу контролера та сторінок інтерфейсу. Бізнес-класи та класи доступу до даних є класичними класами .NET, які можна використовувати як у веб-додатку, так і в додатку для Windows або навіть у консольному додатку. Написання цих класів вимагає глибоких знань об’єктно-орієнтованого програмування. У цьому документі вони будуть написані на VB.NET, тому ми припускаємо, що ця мова вам відома. З огляду на це немає сенсу надмірно зупинятися на коді доступу до даних. Майже у всіх підручниках з ASP.NET один із розділів присвячений ADO.NET. Наведена вище схема показує, що доступ до даних здійснюється за допомогою цілком класичних класів .NET, які не враховують, що використовуються у веб-контексті. Контролер, який є керівником команди веб-додатку, не повинен турбуватися про ADO.NET. Він повинен просто знати, до якого класу звертатися за необхідними даними та як це робити. Ось і все. Включення коду ADO.NET у контролер суперечить концепції MVC, описаній вище, і ми цього не робитимемо.

3.2. Інструменти

Цей документ призначений для студентів, тому ми будемо працювати з безкоштовними інструментами, які можна завантажити з Інтернету:

  • платформа .NET (компілятори, документація)
  • середовище розробки WebMatrix, яке включає веб-сервер Cassini
  • різні SGBD (MSDE, MySQL)

Читачеві пропонується ознайомитися з додатком «Веб-інструменти», де вказано, де знайти та як встановити ці різні інструменти. У більшості випадків нам знадобляться лише три інструменти:

  • текстовий редактор для написання веб-додатків;
  • інструмент для розробки VB.NET для написання коду VB, коли його обсяг є значним. Такий тип інструменту зазвичай пропонує допомогу під час введення коду (автозавершення коду), а також виявлення синтаксичних помилок — або під час введення коду, або під час його компіляції.
  • веб-сервер для тестування написаних веб-додатків. У цьому документі ми розглянемо Cassini. Читач, який має сервер IIS, може замінити Cassini на IIS. Обидва вони сумісні з .NET. Однак Cassini обмежений лише відповідями на локальні запити (localhost), тоді як IIS може відповідати на запити з зовнішніх машин.

Відмінним комерційним середовищем для розробки на VB.NET є Visual Studio.NET від Microsoft. Цей дуже багатофункціональний IDE дозволяє керувати всіма видами документів (код VB.NET, документи HTML, XML, таблиці стилів тощо). Під час написання коду він надає цінну допомогу у вигляді автоматичного «доповнення» коду. Однак цей інструмент, який суттєво підвищує продуктивність розробника, має й зворотний бік: він обмежує розробника стандартним режимом розробки, який, хоч і є ефективним, але не завжди є доречним.

Сервер Cassini можна використовувати поза межами [WebMatrix], і ми часто це робитимемо. Виконуваний файл сервера знаходиться в <WebMatrix>\<версія>\WebServer.exe, де <WebMatrix> — це каталог інсталяції [WebMatrix], а <version> — його номер версії:

Image

Відкриємо вікно командного рядка та перейдемо до папки сервера Cassini:

E:\Program Files\Microsoft ASP.NET Web Matrix\v0.6.812>dir
...
29/05/2003  11:00               53 248 WebServer.exe
...

Запустимо [WebServer.exe] без параметрів:

E:\Program Files\Microsoft ASP.NET Web Matrix\v0.6.812>webserver

Image

Наведена вище панель показує, що програма [WebServer/Cassini] підтримує три параметри:

  • /port: номер порту веб-сервісу. Може бути будь-яким. За замовчуванням — 80
  • /path: фізичний шлях до папки на диску
  • /vpath: віртуальна папка, пов’язана з попередньою фізичною папкою.

Ми розмістимо наші приклади в дереві файлів з кореневим каталогом P, що містить папки chap1, chap2, ... для різних розділів цього документа. Цьому фізичному каталогу P ми прив’яжемо віртуальний шлях V. Отже, запустимо Cassini за допомогою такої команди DOS:

dos> WebServer /port:80 /path:P vpath:V

Наприклад, якщо ми хочемо, щоб фізичним коренем сервера була папка [D:\data\devel\aspnet\poly], а її віртуальним коренем — [aspnet], то команда DOS для запуску веб-сервера буде такою:

dos> WebServer /port:80 /path:D:\data\devel\aspnet\poly vpath:/aspnet

Цю команду можна додати до ярлика. Після запуску Cassini встановлює піктограму на панелі завдань. Двічі клацнувши на ній, можна отримати доступ до панелі «Вимкнути/Увімкнути» сервера:

Image

Панель відображає три параметри, з якими вона була запущена. Вона має дві кнопки ввімкнення/вимкнення, а також посилання для тестування на кореневий каталог її веб-дерева. Ми переходимо за ним. Відкривається браузер і запитується сторінка URL [http://localhost/aspnet]. Ми отримуємо вміст папки, вказаної у полі [Physical Path] вище:

Image

У цьому прикладі запит URL відповідає папці, а не веб-документу, тому сервер відобразив вміст цієї папки, а не конкретний веб-документ. Якщо в цій папці є файл із назвою [default.aspx], він буде відображений. Створімо, наприклад, такий файл і розмістимо його в кореневій папці веб-дерева Cassini (тут — d:\data\devel\aspnet\poly):

<html>
    <head>
        <title>Page d'entrée</title>
    </head>
    <body>
    Page d'index...
    </body>
</html>
dos>dir d:\data\devel\aspnet\poly\default.aspx
23/03/2004  18:21                  107 default.aspx

Тепер завантажимо URL [http://localhost/aspnet] у браузері:

Image

Бачимо, що насправді відобразилися URL та [http://localhost/aspnet/default.aspx]. Далі в цьому документі ми вкажемо, як слід налаштувати Cassini, використовуючи нотацію Cassini(path,vpath), де [path] — це ім’я кореневої папки веб-дерева сервера, а [vpath] — відповідний віртуальний шлях. Нагадаємо, що для сервера Cassini(path,vpath) URL-адреса [http://localhost/vpath/XX] відповідає фізичному шляху [path\XX]. Ми розмістимо всі наші документи у фізичному кореневому каталозі, який назвемо <webroot>. Таким чином, ми зможемо говорити про файл <webroot>\chap2\here1.aspx. Для кожного користувача цей корінь <webroot> буде папкою на його особистому комп’ютері. Наведених нижче знімках екрана видно, що ця папка часто має назву [d:\data\devel\aspnet\poly]. Однак це не завжди так, оскільки тестування проводилося на різних комп’ютерах.

3.3. Перші приклади

Ми наведемо прості приклади динамічної веб-сторінки, створеної за допомогою VB.NET. Читачеві пропонується протестувати їх, щоб переконатися, що його середовище розробки налагоджено належним чином. Ми побачимо, що існує кілька способів побудови сторінки ASP.NET. Ми оберемо один із них для подальшої розробки.

3.3.1. Базовий приклад — варіант 1

Необхідні інструменти: текстовий редактор, веб-сервер Cassini

Повернемося до прикладу з попереднього розділу. Створимо такий файл [heure1.aspx]:

<html>
  <head>
      <title>Demo asp.net </title>
  </head>
  <body>
      Il est <% =Date.Now.ToString("T") %>
  </body>
</html>

Цей код — це код HTML зі спеціальним тегом <% ... %>. Усередині цього тегу можна розмістити код VB.NET. Ось цей код

Date.Now.ToString("T")

генерує рядок символів C, що відображає поточний час. Тег <% ... %> замінюється цим рядком символів C. Отже, якщо C — це рядок 18:11:01, рядок HTML, що містить код VB.NET, перетворюється на:

      Il est 18:11:01

Помістимо попередній код у файл [<webroot>\chap2\heure1.aspx]. Запустимо Cassini (<webroot>,/aspnet) і відкриємо у браузері сторінку URL [http://localhost/aspnet/chap2/heure1.aspx]:

Image

Отримавши цей результат, ми переконуємося, що середовище розробки встановлено правильно. Сторінка [heure1.aspx] була скомпільована, оскільки містить код VB.NET. В результаті її компіляції було створено файл DLL, який було збережено в системній папці, а потім виконано сервером Cassini.

3.3.2. Базовий приклад — варіант 2

Необхідні інструменти: текстовий редактор, веб-сервер Cassini

Документ [heure1.aspx] поєднує код HTML та код VB.NET. У такому простому прикладі це не становить проблеми. Якщо доведеться включити більше коду VB.NET, бажано ще більше відокремити код HTML від коду VB. Це можна зробити, об’єднавши код VB у тег <script>:

<script runat="server">
     ' розрахунок даних для відображення за допомогою коду HTML
...
</script>
<html>
....
' відображення обчислених значень у скрипті
</html>

Приклад [heure2.aspx] ілюструє цей метод:

<script runat="server">
    Dim maintenant as String=Date.Now.ToString("T")
</script>
<html>
    <head>
        <title>Demo asp.net </title>
    </head>
    <body>
        Il est
        <% =maintenant %>
    </body>
</html>

Ми розміщуємо документ [heure2.aspx] у дереві [<webroot>\chap2\heure2.aspx] на веб-сервері Cassini (<webroot>,/aspnet) і запитуємо документ за допомогою браузера:

Image

3.3.3. Базовий приклад — варіант 3

Необхідні інструменти: текстовий редактор, веб-сервер Cassini

Ми продовжуємо процес розділення коду VB та коду HTML, розміщуючи їх у двох окремих файлах. Код HTML буде міститися у файлі [heure3.aspx], а код VB — у файлі [heure3.aspx.vb]. Вміст файлу [heure3.aspx] буде таким:


<%@ Page Language="vb" src="heure3.aspx.vb" Inherits="heure3" %>
<html>
    <head>
        <title>Demo asp.net</title>
    </head>
    <body>
        Il est
        <% =maintenant %>
    </body>
</html>

Є дві принципові відмінності:

  • директива [Page] з поки що невідомими атрибутами
  • використання змінної [maintenant] у коді HTML, хоча вона ніде не ініціалізована

Директива [Page] тут слугує для вказівки, що код VB, який ініціалізує сторінку, знаходиться в іншому файлі. Саме атрибут [src] вказує на цей файл. Ми побачимо, що код VB належить класу з назвою [heure3]. Непомітно для розробника файл .aspx перетворюється на клас, що походить від базового класу з назвою [Page]. У даному випадку наш документ HTML повинен походити від класу, який визначає та обчислює дані, що мають відображатися. У даному випадку це клас [heure3], визначений у файлі [heure3.aspx.vb]. Також необхідно вказати цей зв’язок «батько-дочір» між документами VB, [heure3.aspx.vb] та документами HTML, [heure3.aspx]. Цей зв’язок визначається атрибутом [inherits]. Він повинен вказувати ім’я класу, визначеного у файлі, на який вказує атрибут [src].

Тепер розглянемо код VB на сторінці:

Public Class heure3
    Inherits System.Web.UI.Page

     ' дані веб-сторінки, що мають відображатися
    Protected maintenant As String

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
         'обчислення даних веб-сторінки
        maintenant = Date.Now.ToString("T")
    End Sub
End Class

Слід звернути увагу на наступні моменти:

  • код VB визначає клас [heure3], похідний від класу [System.Web.UI.Page]. Це завжди так, оскільки веб-сторінка завжди має походити від [System.Web.UI.Page].
  • клас оголошує захищений (protected) атрибут [maintenant]. Відомо, що захищений атрибут доступний безпосередньо у похідних класах. Саме це дозволяє документу HTML [heure3.aspx] отримати доступ до значення даних [maintenant] у своєму коді.
  • Ініціалізація атрибута [maintenant] відбувається в процедурі [Page_Load]. Пізніше ми побачимо, що об’єкт типу [Page] отримує від веб-сервера повідомлення про певну кількість подій. Подія [Load] відбувається, коли об’єкт [Page] та його компоненти були створені. Обробник цієї події визначається директивою [Handles MyBase.Load]
    Private Sub XX(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  • назва обробника події [XX] може бути будь-якою. Однак його сигнатура повинна відповідати наведеній вище. Наразі ми не будемо її пояснювати.
  • Часто використовують обробник події [Page.Load] для обчислення значень динамічних даних, які має відображати веб-сторінка.

Документи [heure3.spx] та [heure3.aspx.vb] розміщуються в [<webroot>\chap2]. Потім за допомогою браузера надсилається запит на URL та [http://localhost/aspnet/chap2/heure3.aspx] до веб-сервера (<webroot>,/aspnet):

Image

3.3.4. Базовий приклад — варіант 4

Необхідні інструменти: текстовий редактор, веб-сервер Cassini

Ми використовуємо той самий приклад, що й раніше, але знову об’єднуємо весь код в один файл [heure4.aspx]:

<script runat="server">
     ' дані веб-сторінки, які потрібно відобразити
    Private maintenant As String

     ' evt page_load
    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
         '— обчислюються дані веб-сторінки
        maintenant = Date.Now.ToString("T")
    End Sub
</script>

<html>
    <head>
        <title>Demo asp.net</title>
    </head>
    <body>
        Il est
        <% =maintenant %>
    </body>
</html>

Ми бачимо ту саму послідовність, що й у прикладі 2:

<script runat="server">
.... code VB
</script>

<html>
... code HTML
</html>

Цього разу код VB було структуровано у вигляді процедур. Тут знову зустрічається процедура [Page_Load] з попереднього прикладу. Тут ми хочемо показати, що сама по собі сторінка .aspx (не пов’язана з кодом VB в окремому файлі) неявним чином перетворюється на клас, похідний від [Page]. Отже, можна використовувати атрибути, методи та події цього класу. Саме це робиться тут, де використовується подія [Load] цього класу.

Метод тестування ідентичний попереднім:

Image

3.3.5. Базовий приклад — варіант 5

Необхідні інструменти: текстовий редактор, веб-сервер Cassini

Як і в прикладі 3, код VB та код HTML розміщуються у двох окремих файлах. Код VB розміщується у файлі [heure5.aspx.vb]:

Public Class heure5
    Inherits System.Web.UI.Page

     ' дані веб-сторінки, які потрібно відобразити
    Protected maintenant As String

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
         'обчислюються дані веб-сторінки
        maintenant = Date.Now.ToString("T")
    End Sub
End Class

Код HTML розміщений у [heure5.aspx]:


<%@ Page Inherits="heure5" %>
<html>
    <head>
        <title>Demo asp.net</title>
    </head>
    <body>
        Il est
        <% =maintenant %>
    </body>
</html>

Цього разу директива [Page] більше не вказує на зв’язок між кодом HTML та кодом VB. Веб-сервер більше не має можливості знайти код VB для його компіляції (відсутність атрибута src). Цю компіляцію ми маємо виконати самостійно. Отже, у вікні командного рядка ми компілюємо класи VB та [heure5.aspx.vb]:

dos>dir
23/03/2004  18:34                  133 heure1.aspx
24/03/2004  09:47                  232 heure2.aspx
24/03/2004  10:16                  183 heure3.aspx
24/03/2004  10:16                  332 heure3.aspx.vb
24/03/2004  14:31                  440 heure4.aspx
24/03/2004  14:45                  332 heure5.aspx.vb
24/03/2004  14:56                  148 heure5.aspx
dos>vbc /r:system.dll /r:system.web.dll /t:library /out:heure5.dll heure5.aspx.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4
dos>dir heure5.dll
24/03/2004  14:51                3 072 heure5.dll

Вищезазначений виконуваний файл компілятора [vbc.exe] містився у файлі PATH на комп’ютері з ОС DOS. Якби це не було так, довелося б вказати повний шлях до файлу [vbc.exe], який знаходиться в дереві папок, де було встановлено SDK.NET. Класи, похідні від [Page], потребують ресурсів, що містяться у файлах DLL та [system.dll, system.web.dll], тому на них посилаються за допомогою опції /r компілятора. Опція /t:library вказує, що потрібно створити файл DLL. Опція /out вказує ім’я файлу, що створюється, у даному випадку — [heure5.dll]. Цей файл містить клас [heure5], який потрібен веб-документу [heure5.aspx]. Однак веб-сервер шукає необхідні йому файли DLL у чітко визначених місцях. Одним із таких місць є папка [bin], розташована в корені його дерева каталогів. Цей корінь ми назвали <webroot>. Для сервера IIS це зазвичай <диск>:\inetpub\wwwroot, де <диск> — це диск (C, D, ...) диск, на якому встановлено IIS. Для сервера Cassini цей корінь відповідає параметру /path, з яким ви його запустили. Нагадаємо, що це значення можна отримати, двічі клацнувши на піктограмі сервера на панелі завдань:

Image

<webroot> відповідає атрибуту [Physical Path], зазначеному вище. Отже, ми створюємо папку <webroot>\bin і розміщуємо в ній файл [heure5.dll]:

Image

Ми готові. Надсилаємо запит на URL [http://localhost/aspnet/chap2/heure5.aspx] до сервера Cassini (<webroot>,/aspnet):

Image

3.3.6. Базовий приклад — варіант 6

Необхідні інструменти: текстовий редактор, веб-сервер Cassini

До цього моменту ми показали, що динамічний веб-додаток складається з двох компонентів:

  1. код VB для обчислення динамічних частин сторінки
  2. код HTML, який іноді містить код VB для відображення цих значень на сторінці. Ця частина представляє відповідь, яка надсилається веб-клієнту.

Компонент 1 називається контролером сторінки, а частина 2 — компонентом представлення. Компонент представлення повинен містити якомога менше коду VB, а краще взагалі не містити коду VB. Ми побачимо, що це можливо. Тут ми наводимо приклад, у якому є лише контролер, а компонента представлення відсутня. Саме контролер самостійно генерує відповідь для клієнта без допомоги компоненти представлення.

Код представлення виглядає так:

 <%@ Page src="heure6.aspx.vb" Language="vb" AutoEventWireup="false" Inherits="heure6" %>

Бачимо, що в ньому більше немає жодного коду HTML. Відповідь формується безпосередньо в контролері:

Public Class heure6
    Inherits System.Web.UI.Page

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
         ' формується відповідь
        Dim HTML As String
        HTML = "<html><head><title>heure6</title></head><body>Il est "
        HTML += Date.Now.ToString("T")
        HTML += "</body></html>"
         ' відправляється
        Response.Write(HTML)
    End Sub
End Class

Контролер формує тут всю відповідь, а не лише її динамічні частини. Крім того, він її надсилає. Це здійснюється за допомогою властивості [Response] типу [HttpResponse] класу [Page]. Це об’єкт, який представляє відповідь, надану сервером клієнту. Клас [HttpResponse] має метод [Write] для запису в потік HTML, який буде надіслано клієнту. Тут ми поміщаємо весь потік HTML, який потрібно надіслати, у змінну [HTML] і надсилаємо її клієнту через [Response.Write(HTML)].

Ми запитуємо URL-адресу [http://localhost/aspnet/chap2/heure6.aspx] у сервера Cassini (<webroot>,/aspnet):

Image

3.3.7. Висновок

Надалі ми будемо використовувати метод 3, який розміщує код VB та код HTML динамічного веб-документа у двох окремих файлах. Перевага цього методу полягає в тому, що він розділяє веб-сторінку на дві складові:

  1. компонент-контролер, що складається виключно з коду VB для обчислення динамічних частин сторінки
  2. компонент представлення, який є відповіддю, що надсилається клієнту. Він складається з коду HTML, який іноді включає код VB для відображення динамічних значень. Ми завжди прагнемо мати мінімум коду VB у частині презентації, а ідеально — взагалі його не мати.

Як показано в методі 5, контролер можна компілювати незалежно від веб-додатка. Це дає змогу зосередитися виключно на коді та отримувати список усіх помилок під час кожної компіляції. Після компіляції контролера веб-додаток можна тестувати. Без попередньої компіляції її виконає веб-сервер, і тоді помилки будуть повідомлятися по черзі. Це може здатися обтяжливим.

Для наведених нижче прикладів достатньо таких інструментів:

  • текстовий редактор для створення документів HTML та VB додатка, якщо вони прості
  • інструмент розробки .NET для створення класів VB.NET, щоб скористатися допомогою, яку надає такий інструмент під час написання коду. Прикладом такого інструменту є, наприклад, CSharpDevelop (http://www.icsharpcode.net). Приклад використання наведено в додатку [Les outils du développement web].
  • інструмент WebMatrix для створення сторінок інтерфейсу додатка (див. додаток [Les outils du développement web]).
  • сервер Cassini

Усі ці інструменти є безкоштовними.