Немного истории


Технология ASP появилась в 1997 году и предназначалась для построения web-страниц в Internet Information Server (US). В сценариях ASP HTML-код объединялся со сценарным кодом, интерпретируемым IIS в ответ на запросы со стороны клиента. В


результате строилась страница HTML, которая возвращалась клиенту. Технология ASP обладала рядом недостатков:

  • быстродействие сценариев оставляло желать лучшего, поскольку в основу ASP была заложена интерпретация кода на стороне сервера;
  • разработка и сопровождение сценариев затруднялись тем, что представление страницы не отделялось от управляющего кода;
  • сложности с масштабированием, поскольку страницы ASP не сохраняли текущее состояние сеанса при переходе на другие серверы web-комплекса или после перезапуска;
  • отсутствие нормальной модели безопасности.

Эти и другие проблемы решаются в новой технологии ASP .NET.

 

Простое web-приложение для ASP .NET

Выберите в диалоговом окне New Project значок приложения ASP .NET.

После небольшой задержки VS IDE создает страницу, которой по умолчанию присваивается имя WebFormsl.aspx. Сгенерированная страница содержит код вывода для приложения ASP .NET. Примерный вид VS .NET IDE показан на рис. 12.1. Обратите внимание, сколько файлов было создано для такой простой страницы (имена файлов перечислены в окне решения). Посмотрите на каскадный список стилей, определяющий общие параметры внешнего вида страницы. Дизайнер очень похож на дизайнер форм Windows, описанный в главе 8. Слева расположена панель, с которой элементы перетаскиваются на web-страницу (конечно, web-страницы на стадии конструирования обладают меньшими возможностями по сравнению с формами Windows, поскольку они должны работать в броузере).

Создайте на форме надпись и кнопку. Растяните надпись по ширине страницы, расположите кнопку под надписью и выровняйте по центру, при этом генерируются экземпляры классов из пространства System. Web. UI. WebControl. Ссылка на это пространство имен автоматически включается в решение при создании «скелета» нового приложения ASP .NET. В свойстве Text надписи следует ввести пустую строку, а в свойстве Text кнопки вводится текст «Click me!». Изменения свойств сохраняются в HTML-коде, содержащемся в странице .aspx. Чтобы просмотреть базовый HTML-код, можно выполнить команду View > HTML Source (клавиши Ctrl+PageDown) или выбрать вкладку HTML в IDE. В следующем фрагменте ключевые строки выделяются жирным шрифтом1.

<%@Page Language="vb"AutoEventWireup="false"

Codebehind="WebForml.aspx.vb"

Inherits="WebApplicationl.WebForml'l>

<!DOCTYPE HTML PUBLIC "-//W3C//

DTD HTML 4.0 Transitional//EN">

<HTML>

<HEAD>

<title></title>

<meta name="GENERATOR"

content="Microsoft Visual Studio.NET 7.0">

<meta name="CODE_LANGUAGE"content="Visua1 Basic 7.0">

<meta name="vs_defaultClientScript"content="JavaScript">

<meta name="vs_ta rgetSchema"

content= "http://schemes.microsoft.com/intel1i sense/ie5">

</HEAD>

<body MS_POSITIONING="GridLayout">

<form id="Forml"niethod="post''runat="server">

<asp:Button id="Buttonl"style="Z-INDEX:101;LEFT:311px: POSITION:absolute;TOP:212px"r'bnat-"server"Text-"Click me!" Width="123px"Height="67px">

</asp:Button>

<asp:Label id="Labe11"

style="Z-INDEX:102;LEFT:

15px;POSITION:absolute: TOP:40px"runat="server

"Width="631px"Height="132px">

</asp:Label>

</form>

</body>

</HTML>

Рис. 12.1. Простое приложение ASP .NET в IDE

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

Обратите внимание: все теги элементов страницы снабжаются префиксом <asp:. Дело в том, что элементы ASP .NET не являются элементами HTML. Они находятся на сервере, и обычные элементы HTML используются только в страницах, передаваемых клиенту (там, где это возможно). Так, в HTML не существует аналогов для таких элементов ASP .NET, как календарь или элемент интервальной проверки. В этом случае в ASP .NET для достижения желаемого эффекта используется комбинация обычных элементов HTML, сценарного кода и кода, работающего на стороне сервера.

Если дважды щелкнуть на кнопке, в окне программы открывается процедура события Cl i ck. Открывшаяся страница имеет много общего с приложениями, созданными на базе форм Windows; она тоже содержит автоматически сгенерированный код, который будет описан ниже. В приложениях ASP .NET код обычно отделяется от средств визуального представления и хранится в отдельном файле с двойным расширением .aspx.vb.

Включите в процедуру события Cl ick следующий фрагмент:

Private Sub Buttonl_Click(ByVal sender As System.Object,_

ByVal e As System.EventArgs)

Handles Buttonl.Click

Me.Label 1.Font.Size = FontUnit.XLarge

Me.Label 1.Text = "Welcome to ASP .NET @" & Now

End Sub

Обратите внимание на сходство этого кода с обработчиками событий в приложениях форм Windows, включая наличие параметров sender и EventArgs. Свойство Font в web-элементах несколько отличается от одноименного свойства форм Windows, и это вполне естественно, поскольку количество шрифтов, отображаемых в страницах HTML, заметно ограничено по сравнению с формами Windows. Также обратите внимание на возможность использования встроенных функций .NET (таких, как Now) в коде ASP .NET. Приложения ASP .NET обладают полноценным доступом к .NET Framework. В частности, это означает, что для обращения к данным в ASP .NET могут использоваться все элементы и вся программная поддержка баз данных .NET (см. главу И).

При нажатии клавиши F5 VS .NET IDE генерирует web-страницу и автоматически отображает ее в Internet Explorer. После нажатия кнопки окно приобретает вид, показанный на рис. 12.2.


Ниже приведен полный код страницы с разверткой регионов:

Public Class WebForml

Inherits System.Web.UI.Page

Protected WithEvents Labell As System.Web.UI.WebControls.Label

Protected WithEvents Buttonl As System.Web.UI.WebControls.Button #Region "Web Form Designer Generated Code "

'This call is required by the Web Form Designer. <System.Diagnostics.DebuggerStepThrough()>

Private Sub _

InitializeComponent()

End Sub

Private Sub

Page_Init(ByVal sender As System.Object.

ByVal e As System.EventArgs)

Handles MyBase.Init

'CODEGEN: следующий вызов необходим для дизайнера форм Web.

' Не изменяйте его в редакторе!

InitializeComponent()

End Sub

#End Region

Private Sub Page_Load(ByVal sender As System.Object._

ByVal e As System.EventArgs) Handles MyBase.Load

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

End Sub

Private Sub Bultonl_Click(ByVal sender As System.Object._

ByVal e As System.EventArgs) Handles Buttonl.Click Me.Label1.Font.Size_

FontUnit.XLarge Me.Label1.Text = "Welcome to ASP .NET @" & Now

End Sub

End Class

Рис. 12.2. Результат выполнения простейшего кода ASP .NET

В ASP .NET используется файл globalasax — аналог файла global.asa из ASP. Главное различие между этими файлами заключается в том, что обращения к файлу global.asax происходят:

  • в начале каждого запроса;
  • при возникновении ошибки;
  • при попытке аутентификации пользователя (процесс аутентификации рассматривается ниже).


Простая web-служба


Как упоминалось в главе 9, непосредственное извлечение информации из web-страниц — процесс медленный (из-за необходимости анализировать всю страницу) и ненадежный, поскольку структура страницы может измениться. Удобным средством получения таких данных с web-сайта является web-служба (Web service).

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


В .NET создание web-служб, используемых в клиентских программах, становится делом почти элементарным. В сущности, для этого достаточно определить класс .NET и пометить его члены, доступные через web-службу, атрибутом <WebMethod( )>. Рассмотрим простой пример — допустим, мы создаем web-службу для возвращения информации о погоде.


Создайте новый проект web-службы, для чего следует выбрать значок ASP .NET Web Service в диалоговом окне New Project. Результат показан на рис. 12.3.

Рис. 12.3. Проект web-службы в IDE

Дважды щелкните на дизайнере и обратите внимание на автоматически сгенерированный код:

Public Class Servicel

Inherits System.Web.Services.WebService

Класс System. Web. Services. WebServi се является базовым для всех web-служб .NET. Благодаря наследованию в вашем распоряжении оказываются все возможности этого класса, в том числе и свойство Context для получения запроса HTTP, использованного для обращения к странице через Web.

Включите следующий фрагмент перед командой End Class:

<WebMethod()>Public Function GetWeather(ByVal City As String)

As String Select Case City

' Получить информацию о погоде в Сиэттле

Case "Seattle"

Return "The current temperature is 64 degrees. " & _

"and raining of course."

Case Else

Return "Can't find data for " & City & "."

End Select

End Function

При нажатии клавиши F5 VS .NET IDE автоматически генерирует web-страницу наподобие показанной на рис. 12.4. На этой странице приводится общая информация о web-службе.

Рис. 12.4. Автоматически сгенерированная страница с описанием web-службы


 

Использование web-службы на стороне клиента

Если щелкнуть на ссылке GetWeather на рис. 12.4, в броузере загружается страница, показанная на рис. 12.5. На странице приведен код, который может использоваться для обращения к web-службе. В разделе «SOAP» описывается доступ к службе через протокол SOAP, основанный на XML. Этот протокол отличается наибольшей гибкостью, но простым его не назовешь. В простейшем варианте обращения к web-службе используется запрос HTTP GET. Прототип выглядит следующим образом:

/WebServicel/Servicel.asmx/

GetWeather?city=string НTTР/1.1

Host:Local Host

Рис. 12.5. Простейший вариант использования web-службы

Введите в текстовом поле строку Seattle и нажмите кнопку Invoke. Примерный вид страницы показан на рис. 12.6.

Рис. 12.6. Результаты обращения к web-службе

Результат представлен в формате XML, что позволяет легко проанализировать данные в программе. Также обратите внимание на то, что в автоматически сгенерированном коде показано, как обращаться к web-службе за пределами IDE. Для этого необходимо лишь сгенерировать правильный запрос HTTP GET или SOAP. Ниже приведен пример построения запроса GET в консольном приложении, использующем для отправки запроса GET классы WebRequest и WebResponse пространства имен System.Net:

1 Imports System.Net

2 Imports System.I0

3 Module Module1

4 Sub Main()

5 Dim myResponse As WebResponse

6 Try

7 Dim myWebServiceRequest As WebRequest

8 myWebServiceRequest - WebRequest.Create _

9 ("http://localhost/WebServicel/Servicel.

asmx/GetWeather?dty=SeattIe")

10 myResponse = _

11 myWebServiceRequest.GetResponse()

12 Dim theAnswer As String

13 Dim aStream As New StreamReader

(myResponse.GetResponseStream)

14 theAnswer = aStream.ReadToEnd

15 MsgBox(theAnswer)

16 Catch e As Exception

17 Console.WriteLine(e.Message)

18 Finally

19 myResponse. Close()

20 End Try

21 End Sub

22 End Module

Ключевая роль в этом листинге принадлежит строке 8 (продолжающейся в строке 9), в которой серверу передается запрос GET. Как было показано в главе 9, результат представляет собой поток данных, используемый для построения StreamReader (строка 13). Строка 14 читает в строковую переменную весь текст потока. Строка 19 закрывает объект запроса HTTP и освобождает все связанные с ним ресурсы. Кстати, переменная myResponse была объявлена в строке 5 именно потому, что при объявлении ее в блоке Try (строки 6-15) переменная оказалась бы недоступной для секции Fi nal ly. Результат выполнения программы показан на рис. 12.7.

Рис. 12.7. Результат обращения к web-службе с использованием запроса GET

С запросами SOAP дело обстоит несколько сложнее. Вряд ли кому-нибудь захочется генерировать их вручную. Вместо этого можно воспользоваться командой Project > Add Web Reference или утилитой командной строки wsdl.exe, входящей в поставку .NET Framework. Оба варианта приводят к одному результату — генерируется вспомогательный класс-посредник, который используется в программе.

Пожалуй, решение с утилитой командной строки отличается большей гибкостью. Ниже показано, как выглядела командная строка в нашем случае. Хотя приведенный пример разбит на две строки, его следует ввести в одной строке:

"С:\Program Fi1es\Microsoft.NET\FrameworkSDK\Bin\wsdl"/language:VB"

http://localhost/WebServicel/Servicel.asmx?wsdl

При запуске с ключом /language: VB утилита создает файл с кодом вспомогательного класса Servicel.vb, по умолчанию находящийся в одном каталоге с wsdl.exe (выходной каталог задается ключом out). Основной код сгенерированного класса выглядит так (ключевые строки выделены жирным шрифтом):

Option Strict Off

Option Explicit On

Imports System

Imports System.Diagnostics

Imports System.Web.Services

Imports System.Web.Servi ces.Protocols

Imports System.Xml.Serialization

'This source code was auto-generated by wsdl,Version=l.0.2914.16.

<System.Web.Servi ces.WebServi ceBi ndi ngAttri bute(Name:="ServicelSoap". [Namespace ]:="http://tempuri,org/")> _

Public Class Servicel

Inherits System.Web.Services.Protocols.SoapHttpClientProtocol

<System.Diagnostics.DebuggerStepThroughAttri bute()> _

Public Sub New() MyBase.New Me.Url ="http://localhost/WebServicel/Servicel.asmx"

End Sub

<System.Diagnostics.DebuggerStepThroughAttri bute().

System.Web.Services.Protocols.

SoapDocumentMethodAttri bute _

("http://tempuri.org/GetWeather".

Use:=System.Web.Services.Description.

SoapBindingUse.Literal.

ParameterStyle:=System.Web.Services.

Protocols.SoapParameterStyle.Wrapped)> _

Public Function GetWeather(ByVal city

As String)As String

Dimresults() As Object=Me.Invoke

("GetWeather". New Object 0 {city})

Return CType(results(0). String)

End Function

<System.Diagnostics.

DebuggerStepThroughAttribute()> _

Public Function BeginGetWeather(ByVal city As String._

ByVal callback As System.AsyncCallback.

ByVal asyncState As Object) As System.IAsyncResult

Return

Me.Beginlnvoke("GetWeather", New Object()

{city}.call back.asyncState)

End Function

<System.Diagnostics.DebuggerStepThroughAttributet)> _

Public Function EndGetWeather(ByVal asyncResult

As System.IAsyncResult) As String

Dim results()As Object = Me.EndInvoke(asyncResult)

Return

CType(results(0), String)

End Function

End Class

Затем в проект включается код класса (или ссылка на него) и ссылки на сборки System. Web, System. XML и System. Web.Services. Остается лишь создать экземпляр вспомогательного класса и вызвать функцию GetWeather!

Теперь, когда вы знаете, как получить результаты обращения к web-службе, нетрудно представить себе следующие возможные шаги:

  • объединение результатов нескольких обращений к web-службам в одном файле;
  • применение к результату запроса преобразований XSL и построение новых страниц с HTML-кодом при помощи web-служб, работающих на разных сайтах.

Перед нами одно из проявлений той концепции, которую сейчас активно внедряет Microsoft, — Web как глобальная сеть, через которую пользователь легко получает доступ к любым необходимым данным.