Главная
страница 1
Лабораторная работа № 5

Использование Web сервисов XML

в консольных приложениях и приложениях Windows Forms

1. ЦЕЛЬ И ЗАДАЧИ РАБОТЫ

Ознакомление с Web сервисами (Web-службами) XML и получение практических навыков создания и использования Web-сервисов на базе ASP.NET 2.0 и интегрированной среды разработки Visual Studio .NET 2.0.



2. ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

Прокси-классы для Web-сервисов XML


Прежде чем клиент сможет использовать Web-службу, он должен быть способен создавать, отправлять, получать и понимать XML-сообщения. Платформа .NET предоставляет решение в виде специального компонента, который называется прокси-классом (proxy class) и который выполняет наиболее трудную часть работы для клиентского приложения. Прокси-класс скрывает вызовы методов Web-службы. Он отвечает за генерацию SOAP-сообщений в корректном формате и управление сообщениями в сети (с помощью протокола HTTP). Когда прокси получает ответное сообщение, он еще и преобразует результаты обратно в соответствующие типы данных .NET.

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



Рис. 1. Запуск Web-службы из приложения ASP.NET

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

Чтобы к Web-службе можно было получить доступ с другого компьютера, эта Web-служба должна быть доступной. Это означает, что мы не можем полагаться на встроенный Web-сервер Visual Studio (который динамически выбирает новый порт каждый раз, когда его запускают). Вместо этого мы должны создать виртуальный каталог для своей Web-службы. Выполнив этот шаг, мы должны попытаться, используя имя виртуального каталога (например, Service6), запросить Web-службу в окне браузера:

http://localhost/Service6/Service6.asmx

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

Существуют два способа создания прокси-класса в .NET:

Воспользоваться утилитой командной строки wsdl.ехе.

Воспользоваться предлагаемой в Visual Studio возможностью для добавления Web-ссылок.

Оба эти подхода, по сути, дают один и тот же результат, поскольку они предполагают использование одних и тех же классов в .NET Framework для выполнения фактической работы. Отличием подхода, предполагающего использование утилиты wsdl.exe, от подхода, предполагающего использование функции для добавления Web-ссылок в приложение ASP.NET, является то. что в случае применения функции для добавления Web-ссылок увидеть фактический код прокси-класса будет невозможно (потому что он генерируется позже, во время компиляции). Это ограничение не распространяется на клиентов других типов, например, приложений Windows Form или консольного типа. Они не используют модель компиляции ASP.NET, поэтому код прокси-класса добавляется прямо в проект.


Генерирование прокси-класса с помощью wsdl. exe


Утилита wsdl.exe берет Web-службу и генерирует исходный код прокси-класса либо в VB.NET, либо в С#. Название утилиты "WSDL" происходит от названия стандарта Web-служб (Web Service Description Language — язык описания Web-служб), который используется для описания предоставляемых Web-службой функциональных возможностей.

Файл wsdl.exe можно найти в каталоге .NET Framework, путь к которому обычно выглядит примерно так: C:\Program Files\Microsoft Visual Studio 8/Sdk\v2.0\Bin (зависит от установленной версии Visual Studio). Этот файл представляет собой утилиту командной строки, поэтому с ним легче всего работать в окне командной строки. В некоторых случаях целесообразно работать с копией этого файла в текущем каталоге.

Минимальный синтаксис для генерации прокси-класса Web-службы Service6 выглядит так:

wsdl http://localhost/Service6/Service6.asmx

По умолчанию генерируемому файлу также присваивается такое же, как и у Web-службы, имя (которое указано в свойстве Name атрибута WebService). Вы можете изменить его, добавив в команду wsdl.exe параметр /out, а также можете воспользоваться параметром /namespace и изменить для генерируемого класса пространство имен, например, следующим образом (показанный ниже код был разбит на две строки, поскольку он не умещался в одну строку):

wsdl /namespace:MyNS /out:Service6Proxy.cs http://localhost/Service6/Service6.asmx

Как только этот файл будет создан, его потребуется скопировать в каталог АррCode — это сделает его доступным для страниц в Web-приложении. В случае, когда создается многофункциональное клиентское приложение (такое как приложение Windows Forms), этот файл не следует копировать в каталог App_Code, а необходимо добавить прямо в проект, что гарантирует его компиляцию в окончательный ЕХЕ-файл.

В листинге 1 приведен код прокси-класса Web-службы Service6, который наследует свойства, события и методы базового класса SoapHttpClientProtocol. Например, прокси-класс Service6 наследует свойство Url и в конструкторе инициализирует это свойство адресом Web-службы. В данном примере Web-сервер IIS (сервер localhost) взаимодействует с клиентами через порт 8080.

Для вызова Web-метода HelloWorld прокси-класс вызывает наследуемый метод Invoke. Отметим, что в прокси имеются также и другие методы, которые обеспечивают асинхронный вызов метода HelloWorld Web-службы.

Листинг 1. Код прокси-класса Web-службы Service6

namespace MyNS {

using System.Diagnostics;

using System.Web.Services;

using System.ComponentModel;

using System.Web.Services.Protocols;

using System;

using System.Xml.Serialization;

[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]

[System.Diagnostics.DebuggerStepThroughAttribute()]

[System.ComponentModel.DesignerCategoryAttribute("code")]

[System.Web.Services.WebServiceBindingAttribute(Name="Service6Soap",

Namespace="http://tempuri.org/")]

public partial class Service6 :

System.Web.Services.Protocols.SoapHttpClientProtocol {

private System.Threading.SendOrPostCallback

HelloWorldOperationCompleted;

public Service6() {

this.Url = "http://localhost:8080/Service6/Service6.asmx";

}

public event HelloWorldCompletedEventHandler HelloWorldCompleted;



[System.Web.Services.Protocols.SoapDocumentMethodAttribute(

"http://tempuri.org/HelloWorld", RequestNamespace="http://tempuri.org/",

ResponseNamespace="http://tempuri.org/",

Use=System.Web.Services.Description.SoapBindingUse.Literal,

ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]

public string HelloWorld(string name) {

object[] results = this.Invoke("HelloWorld", new object[] {name});

return ((string)(results[0]));

}

public System.IAsyncResult BeginHelloWorld(string name,



System.AsyncCallback callback, object asyncState) {

return this.BeginInvoke("HelloWorld", new object[] {

name}, callback, asyncState);

}

public string EndHelloWorld(System.IAsyncResult asyncResult) {



object[] results = this.EndInvoke(asyncResult);

return ((string)(results[0]));

}

public void HelloWorldAsync(string name) {



this.HelloWorldAsync(name, null);

}

public void HelloWorldAsync(string name, object userState) {



if ((this.HelloWorldOperationCompleted == null)) {

this.HelloWorldOperationCompleted = new System.Threading.SendOrPostCallback(this.OnHelloWorldOperationCompleted);

}

this.InvokeAsync("HelloWorld", new object[] {



name}, this.HelloWorldOperationCompleted, userState);

}

private void OnHelloWorldOperationCompleted(object arg) {



if ((this.HelloWorldCompleted != null)) {

System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));

this.HelloWorldCompleted(this, new HelloWorldCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));

}

}



public new void CancelAsync(object userState) {

base.CancelAsync(userState);

}

}

[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]



public delegate void HelloWorldCompletedEventHandler(object sender,

HelloWorldCompletedEventArgs e);

[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]

[System.Diagnostics.DebuggerStepThroughAttribute()]

[System.ComponentModel.DesignerCategoryAttribute("code")]

public partial class HelloWorldCompletedEventArgs :

System.ComponentModel.AsyncCompletedEventArgs {

private object[] results;

internal HelloWorldCompletedEventArgs(object[] results,

System.Exception exception, bool cancelled, object userState) :

base(exception, cancelled, userState) {

this.results = results;

}

public string Result {



get {

this.RaiseExceptionIfNecessary();

return ((string)(this.results[0]));

}

}



}

}

Генерирование прокси-класса с помощью Visual Studio


В Visual Studio прокси-класс создается путем добавления в проект клиента соответствующей Web-ссылки. Web-ссылки похожи на обычные ссылки, но вместо того, чтобы указывать на блоки с помощью обычных типов данных .NET, они указывают на URL-адрес Web-службы с помощью WSDL-контракта.

Чтобы создать Web-ссылку, выполните следующие действия:



  1. Щелкните правой кнопкой мыши на имени нужного проекта клиента в окне проводника Solution Explorer и в появившемся контекстном меню выберите команду Add Web Reference (Добавить Web-ссылку).

  2. Появится диалоговое окно Add Web Reference (Добавить Web-ссылку), как показано на рис. 2. Это диалоговое окно предлагает опции для поиска Web-служб и ввода URL-адреса, а также содержит ссылку, которая позволяет просмотреть Web-службы, имеющиеся на локальном компьютере, или выполнить поиск в UDDI-каталоге.

  3. Чтобы сразу перейти к Web-службе, в поле URL (URL-адрес) введите URL-адрес, указывающий на соответствующий .asmx-файл. В окне появится тестовая страница (как показано на рис. 3), а кнопка Add Reference (Добавить ссылку) станет доступной. Если же мы не укажем URL-адрес, а выберем опцию Web services on the local machine, то появится окно с перечнем существующих Web-служб на данной машине, из которых и необходимо осуществить выбор.

  4. Чтобы добавить ссылку на эту Web-службу, щелкните на кнопке Add Reference (Добавить ссылку) в нижней части окна.

  5. После этого Web-ссылка появится в окне проводника Solution Explorer в разделе Web References (Web-ссылки) соответствующего проекта (рис. 4). По умолчанию файл ссылки Reference.cs является скрытым. Чтобы увидеть его, необходимо выбрать в меню Project команду Show All Files.

3

Рис. 2. Диалоговое окно Add Web Reference

При создании Web-ссылки используют WSDL-контракт и ту информацию, которая существует на момент, когда они добавляются. В случае изменения Web-службы, прокси-класс придется обновить, щелкнув правой кнопкой мыши на Web-ссылке и в появившемся контекстном меню выбрав команду Update Web Reference (Обновить Web-ссылку). В отличие от локальных компонентов, Web-ссылки не обновляются автоматически при перекомпиляции приложения.

4

Рис. 3. Добавление Web-ссылки

Отметим, что при разработке и тестировании Web-службы в Visual Studio зачастую легче всего добавить Web-службу и клиентское приложение в одно и то же решение (рис. 4.).

Это позволит тестировать и изменять оба этих компонента в одно и то же время. Мы можем воспользоваться интегрированной программой отладки, чтобы установить контрольные точки и просматривать код как клиента, так и сервера, как будто бы они действительно являются одним приложением. Чтобы выбрать приложение, которое Visual Studio должен запускать при щелчке на кнопке Start (Пуск) или по клавише F5, щелкните правой кнопкой мыши на имени нужного проекта в окне проводника Solution Explorer и в появившемся контекстном меню выберите команду Set As Startup Project (Установить в качестве стартового проекта).

При при размещении клиентского и сервисного приложений в одном решении Web-сервер IIS не будет использоваться для отладки. Вместо него будет использоваться встроенный в Visual Studio Web-сервер, а обращение к сервису (к Web-службе) будет происходить через динамически создаваемые порты. Так, листинг 2 файла Reference.map для решения на рис. 4 показывает, что при отладке Web-служба Service5 будет работать через порт 1115.

Листинг 2. Файл C:\Service5Client\Web Referencies\localhost\Reference.map



xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance

xmlns:xsd="http://www.w3.org/2001/XMLSchema">



"System.Web.Services.Discovery.DiscoveryDocumentReference"

url=http://localhost:1115/Service5/Service5.asmx?disco

filename="Service5.disco" />



referenceType="System.Web.Services.Discovery.ContractReference"

url=http://localhost:1115/Service5/Service5.asmx?wsdl

filename="Service5.wsdl" />







1

Рис. 4. Размещение двух проектов в одном решении

Отметим, что при создании Web-ссылки на Web-сервис, расположенный на сервере localhost, в проекте консольного приложения Service5Client средой Visual Studio будет создан подкаталог Web Referencies/localhost с файлами Reference.cs (код прокси-класса), Service5.wsdl (описание Web-сервиса), Service5.disco (ссылки на адреса и механизмы, используемые для доступа к Web-сервису) и Reference.map (см. листинг 2).

Использование Web-сервиса XML консольным приложением


Рассмотрим пример создания и использования простейшей Web-службы Service5, Web-метод HelloWorld которой принимает в качестве аргумента имя клиента, а возвращает текст приветствия. Воспользуемся редактором Notepad для подготовки кода Web-сервиса Service5 (листинги 3 и 4) и тестового (консольного) клиента (листинг 5).

Листинг 3. Файл Service5.asmx

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

Листинг 4. Файл Service5.cs

using System;

using System.Web.Services;

namespace MyNS

{

public class Service5



{

[WebMethod]

public string HelloWorld(string name)

{

return "Why, hello "+name+"!";



}

}

}



Листинг 5. Файл Service5Client.cs

using System;

using System.Web.Services;

using Service5Client.localhost;

class testServiceClass {

static void Main() {

Service5 myTest = new Service5();

string response = myTest.HelloWorld("William");

Console.WriteLine(response);

}

}



Для предварительного тестирования Web-сервиса (т.е. для тестирования без использования консольного клиентского приложения) разместим Web-сервис в каталоге C:\Service5, откроем этот каталог как Web-сайт и запустим его построение и выполнение. Если данное тестирование прошло успешно, выполним публикацию этого сервиса на сервере IIS. Для этого скопируем каталог Service5 в каталог C:\Inetpub\wwwroot\Service5 и создадим виртуальный каталог Service5 для данного физического каталога (если виртуальный каталог Service5 уже существовал, то он предварительно удаляется). Далее открываем проект сервиса Service5 уже в каталоге C:\Inetpub\wwwroot\Service5 и вновь выполняем тестирование сервиса Service5 без клиентского приложения.

Если тестирование Web-сервиса Service5 посредством браузера и встроенного в Visual Studio Web-сервера прошло успешно, переходим к этапу создания клиентского приложения. Для этого сохраним в каталоге C:\Service5Client файл с именем Service5Client.cs (см. листинг 5). Прежде чем компилировать клиентское приложение, необходимо в этом приложении создать ссылку на класс System.Web.Services и Web-ссылку на Web-сервис Service5.

Ссылка на класс System.Web.Services необходима, поскольку мы в тексте консольного приложения используем директиву

using System.Web.Services;

Для создания ссылки необходимо в окне проекта клиентского приложения выделить строку References, щелкнуть правой клавишей и выбрать в контекстном меню пункт Add Reference. Далее на странице .NET окна Add Reference выбрать имя необходимой ссылки (рис. 5).

6

Рис. 5. Окно для добавления ссылки

Для создания Web-ссылки на Web-сервис Service5 необходимо в окне проекта клиентского приложения выделить строку Web References (или строку с именем проекта), щелкнуть правой клавишей и выбрать в контекстном меню пункт Add Web Reference. Появится окно Add Web Reference, показанное на рис. 2. После указания необходимой Web-службы появляется ее тестовая страница (см. рис. 3).

Отметим, что клиентское приложение должно импортировать пространство имен прокси-класса. В Visual Studio таким пространством имен автоматически становится пространство имен текущего проекта плюс пространство имен, указанное в диалоговом окне Add Web Reference (Добавить Web-ссылку) (в котором по умолчанию указывается пространство имен localhost). При условии, что проект называется Service5Client, Web-сервис находится на локальном компьютере и никакие изменения в окне Add Web Reference не вносились, это пространство имен будет выглядеть так (см. листинг 5):

using Service5Client.localhost;

После запуска построения и выполнения (по команде Ctrl+F5) клиентского приложения на экране появится консольное окно со строкой, полученной от Web-сервис Service5 (рис. 6).



2

Рис. 6. Окно с результатами выполнения консольного приложения


Использование Web-сервиса приложением Windows Forms


Создадим клиентское приложение Windows Forms (рис. 7) в каталоге C:\Service5WinFormClient для тестирования Web-сервиса Service5, используя шаблон Windows Application.

7

Рис. 7. Приложение Service5WinFormClient

Класс формы – класс Form1 имеет атрибут partial (распределенный по файлам класс) и будет размещаться в двух файлах: в файле Form1.Designer.cs, описывающем компоненты графического интерфейса, и файле Form1.cs, содержащем обработчики событий (листинги 6 и 7).

Листинг 6. Файл Form1.Designer.cs

namespace Service5WinFormClient

{

partial class Form1



{

private System.ComponentModel.IContainer components = null;

protected override void Dispose(bool disposing)

{

if (disposing && (components != null))



{

components.Dispose();

}

base.Dispose(disposing);



}

#region Windows Form Designer generated code

private void InitializeComponent()

{

this.label1 = new System.Windows.Forms.Label();



this.textBox1 = new System.Windows.Forms.TextBox();

this.button1 = new System.Windows.Forms.Button();

this.richTextBox1 = new

System.Windows.Forms.RichTextBox();

this.SuspendLayout();

//


// label1

//


this.label1.AutoSize = true;

this.label1.Location = new System.Drawing.Point(32, 36);

this.label1.Name = "label1";

this.label1.Size = new System.Drawing.Size(33, 13);

this.label1.TabIndex = 0;

this.label1.Text = "Login";

//

// textBox1



//

this.textBox1.Location = new System.Drawing.Point(82, 36);

this.textBox1.Name = "textBox1";

this.textBox1.Size = new System.Drawing.Size(100, 20);

this.textBox1.TabIndex = 1;

//


// button1

//


this.button1.Location = new System.Drawing.Point(260, 36);

this.button1.Name = "button1";

this.button1.Size = new System.Drawing.Size(111, 23);

this.button1.TabIndex = 2;

this.button1.Text = "Service5";

this.button1.UseVisualStyleBackColor = true;

this.button1.Click += new

System.EventHandler(this.button1_Click);

//

// richTextBox1



//

this.richTextBox1.Location =

new System.Drawing.Point(82, 96);

this.richTextBox1.Name = "richTextBox1";

this.richTextBox1.Size = new System.Drawing.Size(225, 36);

this.richTextBox1.TabIndex = 3;

this.richTextBox1.Text = "";

//


// Form1

//


this.AutoScaleDimensions =

new System.Drawing.SizeF(6F, 13F);

this.AutoScaleMode =

System.Windows.Forms.AutoScaleMode.Font;

this.ClientSize = new System.Drawing.Size(419, 151);

this.Controls.Add(this.richTextBox1);

this.Controls.Add(this.button1);

this.Controls.Add(this.textBox1);

this.Controls.Add(this.label1);

this.Name = "Form1";

this.Text = "Form1";

this.ResumeLayout(false);

this.PerformLayout();

}

#endregion



private System.Windows.Forms.Label label1;

private System.Windows.Forms.TextBox textBox1;

private System.Windows.Forms.Button button1;

private System.Windows.Forms.RichTextBox richTextBox1;

}

}

Листинг 7. Файл Form1.cs



using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using Service5WinFormClient.localhost;

namespace Service5WinFormClient

{

public partial class Form1 : Form



{

public Form1()

{

InitializeComponent();



}

private void button1_Click(object sender, EventArgs e)

{

Service5 myTest = new Service5();



string response = myTest.HelloWorld(textBox1.Text);

richTextBox1.AppendText(response + "\n");

}

}

}



После создания формы с помощью инструментальной панели Toolbox необходимо с помощью окна свойств изменить названия компонентов label1 и button1 и добавить обработчик события Click для кнопки button1 (добавление обработчика событий начинается с нажатия на символ молнии в окне свойств).

Следующий этап – это подключение Web-сервиса Service5 к приложению Service5WinFormClient. Для создания Web-ссылки на Web-сервис Service5 необходимо в окне проекта клиентского приложения выделить строку Web References (или строку с именем проекта), щелкнуть правой клавишей и выбрать в контекстном меню пункт Add Web Reference. Появится окно Add Web Reference, показанное на рис. 2. После указания необходимой Web-службы появляется ее тестовая страница (см. рис. 3), где и необходимо нажать кнопку Add Reference.

Кроме этого, необходимо импортировать пространство имен прокси-класса в клиентское приложение посредством включения в файл Form1.cs следующей строки:

using Service5WinFormClient.localhost;

Отметим, что объект myTest (объект прокси-класса или по другому объект заместителя Web-сервиса Service5) создается и используется как локальный объект обработчика button1_Click. В более общем случае этот объект можно объявить как поле класса Form1 и создавать этот объект в конструкторе класса Form1.

При генерировании каркаса клиентского приложения посредством шаблона Windows Application создается и третий исходный файл приложения – файл Program.cs, представленный в листинге 8. Файл содержит метод Main в классе Program, входящем в пространство имен Service5WinFormClient. Отметим, что в этом же пространстве находится и класс Form1 клиентского приложения.

Метод Main объявлен как статический, т.е. его можно использовать без порождения объекта класса Program. Метод Main имеет атрибут STAThread, который указывает исполняющей среде .NET запускать программу в отделенном потоке, чтобы обеспечить ее корректное взаимодействие с объектами COM.

Метод EnableVisualStyles класса Application позволяет задать более "современный" вид некоторых элементов управления. Метод Run запускает механизм обработки сообщений и завершается только тогда, когда пользователь закроет форму Form1 и уничтожит, таким образом, созданный методом Run объект класса Form1. Метод Run завершается и в случае возникновения ошибок в программе.



Листинг 8. Файл Program.cs

using System;

using System.Collections.Generic;

using System.Windows.Forms;

namespace Service5WinFormClient

{

static class Program



{

///

/// The main entry point for the application.

///

[STAThread]

static void Main()

{

Application.EnableVisualStyles();



Application.SetCompatibleTextRenderingDefault(false);

Application.Run(new Form1());

}

}

}



На рис. 7 представлены результаты выполнения приложения Service5WinFormClient.

8

Рис. 7. Результаты выполнения приложения Service5WinFormClient


Асинхронный вызов Web-сервиса XML


Рассмотренные Web-сервисы вызывались в синхронном режиме, т.е клиентское приложение при обращении к сервису блокировалось до момента получения результата. Более эффективным решением будет асинхронный вызов Web-сервиса, когда клиентское приложение не ожидает ответа, а продолжает параллельно выполнять какую-либо работу. Даже если Web-сервис выполняется быстро, мы можем секономить несколько миллисекунд, затрачиваемых на упаковку/распаковку SOAP-сообщений и передачу через сеть (если сервер находится на большом расстоянии).

Прокси-класс содержит все необходимое для выполнения как синхронных, так и асинхронных вызовов Web-сервисов. Для каждого Web-метода код прокси-класса включает два метода – синхронный и асинхронный (с суффиксом Async в имени). Ниже представлен код для синхронной версии Web-метода HelloWorld Web-сервиса (Web-службы) Service6:

public string HelloWorld(string name) {

object[] results = this.Invoke("HelloWorld", new object[] {

name});

return ((string)(results[0]));



}

Прокси-класс содержит две версии асинхронного метода HelloWorldAsync(). Единственное отличие между ними состоит в том, что одна из них принимает дополнительный параметр userState, которым может быть любой объект, используемый для идентификации вызова (например, объект типа Guid). Когда выполнение данного вызова завершится, этот объект будет возвращен в обратном вызове. Параметр userState особенно полезен в случаях, когда параллельно реализуются сразу несколько асинхронных Web-методов.

public void HelloWorldAsync(string name) {

this.HelloWorldAsync(name, null);

}

public void HelloWorldAsync(string name, object userState) {



if ((this.HelloWorldOperationCompleted == null)) {

this.HelloWorldOperationCompleted = new

System.Threading.SendOrPostCallback(

this.OnHelloWorldOperationCompleted);

}

this.InvokeAsync("HelloWorld", new object[] {name},



this.HelloWorldOperationCompleted, userState);

}

Алгоритм работы будет следующим. Чтобы запустить асинхронный вызов, клиентское приложение вызывает метод HelloWorldAsync(). Из этого метода сразу происходит возврат, еще даже до того, как запрос будет отправлен через сеть, в результате чего прокси-класс помещается в свободный поток и находится там в режиме ожидания до тех пор, пока не получит ответ. Как только ответ будет получен и пройдет десериализацию, .NET инициирует соответствующее событие, чтобы уведомить об этом клиентское приложение. После этого можно извлечь результаты.



Чтобы эта система работала, прокси-класс добавляет событие для каждого Web-метода. Это событие инициируется сразу же после того, как выполнение асинхронного метода завершится. Так, в прокси-классе Service6 объявлено следующее событие для метода HelloWorld():

public event HelloWorldCompletedEventHandler HelloWorldCompleted;

Кроме этого, для каждого Web-метода прокси-класс создает специальный специальный объект EventArgs. Этот объект содержит результат выполнения Web-метода в виде свойства Result:

// Определяет сигнатуру события завершения

public delegate void HelloWorldCompletedEventHandler(

object sender, HelloWorldCompletedEventArgs e);

public partial class HelloWorldCompletedEventArgs :

System.ComponentModel.AsyncCompletedEventArgs {

private object[] results;

internal HelloWorldCompletedEventArgs(object[] results,

System.Exception exception, bool cancelled, object userState) :

base(exception, cancelled, userState) {

this.results = results;

}

public string Result {



get {

this.RaiseExceptionIfNecessary();

return ((string)(this.results[0]));

}

}



}

}

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



Помимо свойства Result доступны еще несколько свойств, которые объявляются в базовом классе AsyncCompletedEventArgs, а именно: Cancelled (возвращает значение true, если операция была отменена до того, как она завершилась), Error (возвращает объект исключения, если во время обработки запроса произошла необработанная ошибка) и UserState (возвращает объект состояния, который формировался при вызове метода).

Для экспериментальной проверки работы асинхронных вызовов добавим следующий Web-метод в класс Web-сервиса Service5:

[WebMethod]

public string HelloWorldSlow(string name)

{

// Задержка на 5 секунд



System.Threading.Thread.Sleep(5000);

return "Why, hello " + name + "!";

}

Соответственно в киентское приложение Service5WinFormClient добавим кнопку button2 для асинхронного вызова Web-метода HelloWorldSlow, в обработчике которой создаем делегата обратного вызова для обработчика HelloWorldSlowCompleted:



private void button2_Click(object sender, EventArgs e)

{

button2.Enabled = false;



Service5 proxy = new Service5();

proxy.HelloWorldSlowCompleted +=

new HelloWorldSlowCompletedEventHandler(this.HelloWorldSlowCompleted);

proxy.HelloWorldSlowAsync(textBox1.Text);

}

В момент завершения выполнения Web-метода HelloWorldSlow возникает событие HelloWorldSlowCompletedEventHandler, при обработке которого полученный результат добавляется в поле richTextBox1:



private void HelloWorldSlowCompleted(object sender,

HelloWorldSlowCompletedEventArgs e)

{

button2.Enabled = true;



string response = (string)e.Result;

richTextBox1.AppendText(response + "\n");

}

3. ОБОРУДОВАНИЕ

Персональный компьютер с процессором не ниже Pentium 600 и имеющий не менее 192 МБ оперативной памяти, операционная система MS Windows 2000 SP4 или XP SP2, интегрированная среда разработки приложений MS Visual Studio.Net 2005 с комплектом документации MSDN 2005, каталог Lab4, содержащий файл Labtp4.doc (методические указания к данной лабораторной работе), не менее 200 Mб свободной памяти на логическом диске, содержащем каталог Lab4.



4. ЗАДАНИЕ НА РАБОТУ

4.1. Ознакомиться с технологией создания и использования в клиентских приложениях Web-сервисов XML.

4.2. Создать Web-сервис Service5 и выполнить его тестирование сначала в браузере IE, а затем посредством использования его в клиентских приложениях (в консольном приложении и приложении Windows Forms).

4.3. В соответствии с вариантом задания, полученным от преподавателя, создать Web-сервис и выполнить его тестирование.

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


  1. Каждый Web-метод сервиса выполняет одну из арифметических операций.

  2. Сервис получает массив целых чисел и возвращает их сумму и наибольшее из чисел.

  3. Сервис получает массив целых чисел и тип сортировки – по возрастанию или по убыванию, возвращает массив отсортированных чисел.

  4. Сервис получает массив целых чисел и возвращает среднее значение (число действительного типа).

5. ПОРЯДОК ВЫПОЛНЕНИЯ РАБОТЫ

5.1. Проверить наличие 200 Мб свободной памяти на логическом диске, содержащем каталог Lab4, наличие файла Labtp4.doc в каталоге Lab4.

5.2. Ознакомиться с информацией о Web-сервисах (Web-службах) в документации MSDN (раздел Development Tools and Languages->Visual Studio->Visual C#->Getting Started with Visual C#->How Do I in C#->Web Pages and Web Services). Удалить виртуальный каталог Service5, если он имеется.

5.3. В каталоге, заданным преподавателем, создать Web-сервис XML Service5, используя файлы, приведенные в листингах 3 и 4. Выполнить тестирование Web-сервиса без использования клиентского приложения.

5.4. Опубликовать Web-сервис Service5 на сервере IIS. Для этого необходимо очистить каталог C:\Inetpub\wwwroot\Service5 и перекопировать в него файлы предварительно оттестированного Web-сервиса Service5. Создать виртуальный каталог Service5 для данного физического каталога (если виртуальный каталог Service5 уже существовал, то он предварительно удаляется).

5.5. Открыть проект Web-сервиса Service5 в каталоге C:\Inetpub\wwwroot\Service5 и выполнить тестирование сервиса Service5 без использования клиентского приложения.

5.6. Использовать утилиту wsdl.exe для генерирации исходного кода прокси-класса для Web-сервиса Service5. Ознакомиться с текстом полученного таким образом прокси-класса.

5.7. Создать консольное клиентское приложение в каталоге C:\Service5Client и создать в нем ссылку на класс System.Web.Services и Web-ссылку на Web-сервис Service5. Запустить построение и выполнение (по команде Ctrl+F5) созданного клиентского приложения.

5.8. Создать клиентское приложение Windows Forms в каталоге C:\Service5WinFormClient и создать в нем Web-ссылку на Web-сервис Service5. Запустить построение и выполнение созданного клиентского приложения.

5.9. В соответствии с вариантом задания, полученным от преподавателя, создать Web-сервис и выполнить его тестирование с использованием как синхронных, так и асинхронных вызовов Web-методов.



6. ОФОРМЛЕНИЕ ОТЧЕТА

Отчет должен содержать:



  • цель работы, вариант задания на работу;

  • структуру проекта и содержимое файлов созданного в соответствии с вариантом задания Web-сервиса XML и клиентского приложения;

  • результаты выполнения Web-сервисов XML, запущенных в процессе выполнения работы.

7. КОНТРОЛЬНЫЕ ВОПРОСЫ

7.1. Какие типы клиентских приложений Web-сервисов XML существуют? Какие из них относятся к тонким клиентам?

7.2. Что называется WSDL-контрактом? Что в нем описывается?

7.3. Как создается и как используется класс-прокси? Чем отличаются методы прокси от методов Web-сервиса?

7.4. Какое назначение каталога C:\Inetpub\wwwroot? Как создать новый виртуальный каталог?

7.5. Какие файлы входят в проект Web-сервиса XML? Как можно выполнить тестирование Web-сервиса без использования клиентского приложения?

7.6. Какие файлы входят в проект клиентского приложения Web-сервиса XML? Что содержится в файлах, обеспечивающих связь с Web-сервисом XML?

7.7. Как называется Web-сервер, встроенный в среду разработки Visual Studio .NET 2.0? Какие имеются ограничения на Web-сервисы XML, тестируемые без сервера IIS?

7.8. Как клиентское приложение импортирует пространство имен прокси-класса?

7.9. Какие файлы и классы создает шаблон Windows Application?

7.10. Какой код в приложениях Win32 API заменяет вызов метод Run класса Application в приложении .NET API?

БИБЛИОГРАФИЧЕСКИЙ СПИСОК

1. Мак-Дональд М., Шпушта М. Microsoft ASP.NET 2.0 с примерами на C# 2005 для профессионалов. – М.: ООО "И.Д. Вильямс", 2006. – 1408 с.

2. Смит С. ASP.NET. – М..: ДМК Пресс, 2005. – 496 с.

3. Троелсен Э. C# и платформа .Net. Библиотека программиста. – СПб.: Питер, 2002. – 800 с.

4. Петцольд Ч. Программирование с использованием Microsoft Windows Forms. Мастер-класс. – М. : Русская Редакция; СПб. : Питер, 2006. – 432 с.

5. Microsoft Corporation. Разработка Web-сервисов XML и серверных компонентов на Microsoft Visual Basic .NET и Microsoft Visual C# .NET. Учебный курс MCAD/MCSD. – М.: Издательско-торговый дом "Русская Редакция", 2004.- 576 с.



6. Ньюкомер Э. Веб-сервисы. Для профессионалов. – СПб.: Питер, 2003. – 256 с.

7. Хабибуллин И.Ш. Самоучитель XML. – СПб.: БХВ-Петербург, 2003. – 336 с.


Смотрите также:
Лабораторная работа №5 Использование Web сервисов xml в консольных приложениях и приложениях Windows Forms цель и задачи работы
284.97kb.
1 стр.
Лабораторная работа 9-01 Лабораторная Шонин В. А. работа 9-01 Использование табличной верстки для создания Web-страниц
446.97kb.
1 стр.
Лабораторная работа. Системный реестр Windows
74.22kb.
1 стр.
Лабораторная работа №2 «Система безопасности Windows xp» Цель работы: Изучить систему безопасности Windows xp описание работы
58.41kb.
1 стр.
Лабораторная работа. «Основы виртуальных машин. Инсталляция и настройка ос windows xp»
104.15kb.
1 стр.
Лабораторная работа Использование стандартных компонентов в C++ Builder
87.05kb.
1 стр.
Курс "Проектирование и разработка приложений на основе платформы Windows Azure"
22.68kb.
1 стр.
Отчет по работе должен содержать: Цель работы Вариант задания на выполнение работы
33.1kb.
1 стр.
Технологии проектирования программного обеспечения для ос windows (Windows Form, asp. Net, Web-сервисы xml) пояснительная записка к курсовой работе по дисциплине: «Операционные среды»
247.57kb.
1 стр.
Лабораторная работа по химии, физике, биологии, т е. по естественно-научным предметам. На уроках русского языка и литературы термин «лабораторная работа»
261.84kb.
1 стр.
Лабораторная работа №1-03 Работа в Windows в режиме командной строки
261.68kb.
1 стр.
Лабораторная работа №6 Межпроцессное взаимодействие
279.25kb.
1 стр.