|
||||
|
Глава 17Службы Web Службы Web — это новый способ выполнения удаленного вызова методов посредством HTTP с помощью SOAP (Simple Object Access Protocol — простой протокол доступа к объектам). Раньше это было связано с трудностями, что может засвидетельствовать каждый, кто имеет опыт работы с DCOM (Distributed COM — распределенный COM). Создание экземпляра объекта на удаленном сервере, вызов метода и получение результата были далеко не простыми, а необходимая конфигурация была еще более сложной. SOAP существенно упрощает ситуацию. Эта технология является стандартом на основе XML который определяет, как можно делать вызовы методов через HTTP воспроизводимым образом. Удалённый сервер SOAP способен понимать эти вызовы и выполнять всю трудную работу, такую как создание экземпляра требуемого объекта, выполнение вызова и возврат клиенту ответа, форматированного SOAP. Как и в случае ASP.NET мы обладаем всеми возможностями технологий C# и .NET на сервере, но более важно, что простое использование служб Web можно получить на любой платформе, имеющей к серверу доступ HTTP. Другими словами, вполне возможно что код Linux мог бы, например, использовать службы .NET. Кроме того, службы Web можно полностью описать с помощью WSDL (Web Service Description Language — язык описания служб Web), допуская динамический поиск cлужб Web во время выполнения приложения. WSDL предоставляет с помощью XML со схемами XML описания всех методов (вместе с типами данных, требуемыми для их вызова). Существует широкое множество типов данных, доступных для служб Web, которые простираются от простых примитивных до полноценных объектов DataSet, так что базы данных, расположенные полностью в памяти, могут маршализоваться клиенту, что может в результате привести и существенному сокращению нагрузки на сервер базы данных. Эту главу мы начнем с синтаксиса SOAP и WSDL, а затем перейдем к их использованию службами Web. Мы обсудим, как предоставлять и использовать службы Web, и разберем полный пример, построенный на основе приложения заказа помещения для проведения мероприятий из предыдущей главы. SOAPКак упоминалось выше, одним из способов обмена данными со службами Web является SOAP. Эта технология широко обсуждалась в прессе, особенно с тех пор, как компания Microsoft решила принять ее для использования на платформе .NET. Теперь волнение, кажется, слегка успокоилось, так как спецификация SOAP была завершена. Если подумать, то знание того, как точно работает SOAP, похоже на знание того, как работает HTTP, в принципе это интересно, но не существенно. Большую часть времени нам нет необходимости беспокоиться о формате сделанного со службами Web обмена, он просто происходит, а мы получаем требуемый результат, и все довольны. По этой причине здесь не будет представлено подробное рассмотрение, но будет показано несколько простых запросов и ответов SOAP, чтобы можно было получить некоторое представление о том, что происходит за сценой. Давайте предположим, что необходимо вызвать метод службы Web, имеющий следующую сигнатуру. int DoSomething(String stringParam, int intParam) Далее представлены требуемые для этого заголовки SOAP и body. Вверху указан адрес службы Web (об этом больше будет сказано далее): POST /SomeLocation/myWebService.asmx HTTP/1.1 Host: karlivaio Content-Type: text/xml; charset=utf-8 Content-Length: length SOAPAction: "http://tempuri.org/DoSomething" <?xml version="1.0"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2000/10/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope"> <soap:Body> <DoSomething xmlns="http://tempuri.org/"> <stringParam>string</stringParam> <intParam>int</intParam> </DoSomething> </soap:Body> </soap:Envelope> Параметр Используемое пространство имен soap определяет различные элементы, которые применяются для создания сообщения. При отправке этого кода через HTTP реальные посылаемые данные будут несколько другими. Например, можно было бы вызвать приведенный выше метод с помощью простого метода GET: GET /PCSWebSrv1/Service1.asmx/AddEvent?stringParam=string&intParam= int HTTP/1.1 Host.: hostname Ответ SOAP этого метода будет следующим: HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: length <?xml version="1.0" ?> <soap:Envelope xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2000/10/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope"> <soap:Body> <DoSomethingResponse xmlns="http://tempuri.org/"> <DoSomethingResult>int</DoSomethingResult> </DoSomethingResponse> </soap:Body> </soap:Envelope> где И снова реальный ответ через HTTP может быть значительно проще, например: HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: length <?xml version="1.0"?> <int xmlns="http://tempuri.org/">int</int> Это совсем простой формат XML. Как упоминалось в начале раздела, все это можно полностью игнорировать. Только при необходимости сделать что-то действительно необычное точный синтаксис становится важным, но такие случаи выходят за рамки этой книги. WSDLWSDL полностью описывает службы Web, доступные методы и различные способы вызова этих методов. Все детали этого опять же не так уж важны, но общее понимание будет полезно. WSDL имеет синтаксис, полностью соответствующий XML, и определяет службы Web по доступным методам, типам данных, используемых этими методами, форматам сообщений запросов и ответов, посылаемых методам и из методов с помощью различных протоколов (чистый SOAP, HTTP GET и т.д.), и различным связываниям между упомянутыми выше элементами. Возможно, что наиболее важной частью файла WSDL является раздел определения типов данных. Он использует схемы XML для описания формата обмена данными и их отношениями с помощью элементов XML. Например, метод службы Web, использованной в качестве примера в последнем разделе: int DoSomething(string stringParam, int intParam) будет иметь типы, объявленные для запроса следующим образом: <?xml version="1.0" ?> <definitions xmlns:s="http://www.w3.org/2000/10/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" ... другие пространства имен ... > <types> <s:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://tempuri.org/"> <s:import namespace="http://www.w3.org/2000/10/XMLSchema" /> <s:element name="DoSomething" > <s:complexType> <s:sequence> <s:element name="stringParam" nullable="true" type="s:string" /> <s:element name="intParam" nullable="true" type="s:int" /> </s:sequence> </s:complexType> </s:element> <s:element name="DoSomethingResponse"> <s:complexType> <s:sequence> <s:element name="DoSomethingResult" type="s:int" /> </s:sequence> </s:complexType> </s:element> <s:element name="int" type="s:int" /> </s:schema> </types> ... другие определения ... </definitions> Все, что требуется для запросов и ответов SOAP и HTTP, которые мы видели ранее, определяется этими типами, которые далее в этом файле связываются с такими операциями. Все типы определяются с помощью стандартного синтаксиса схемы XML, например: <s:element name="DoSomethingResponse"> <s:complexType> <s:sequence> <s:element name="DoSomethingResult" type="s:int" /> </s:sequence> </s:complexType> </s:element> Этот код определяет, что элемент с именем <DoSomethingResponse>имеет элемент-потомок с именем <DoSomethingResult>, который содержит целое число. Если мы имеем доступ к коду WSDL для службы Web, то мы можем его использовать. Как мы скоро увидим, это не так уж трудно сделать. Теперь, когда мы кратко ознакомились с SOAP и WSDL, пришло время посмотреть, как создаются и используются службы Web. Службы WebОбсуждение служб Web включает два вопроса: □ Создание служб Web, которое связано с написанием служб Web и размещением их на серверах Web. □ Использование служб Web, которое связано с применением на стороне клиента созданных служб. Создание служб WebСлужбы Web создают, либо помещая код прямо в файлы .asmx, либо, ссылаясь на классы службы Web из этих файлов. Как и со страницами ASP.NET, создание службы Web в VS.NET применяет последний подход, и он также будет использоваться для целей демонстрации. Создание проекта службы Web, называемой PCSWebSrv1, как показано выше, приводит, как и для проекта приложения Web, к аналогичному множеству созданных файлов. Фактически, единственное различие состоит в том, что вместо создания файла с именем WebForm1.aspxсоздается файл с именем Service1.asmx. Созданный файл .vsdiscoотвечает за идентификацию службы Web, чтобы система Visual Studio .NET, как мы вскоре увидим, могла добавить на него ссылку Web. Код в Service1.asmxне доступен непосредственно через VS.NET, но просмотр с помощью Notepad показывает следующую строку кода: <%@ WebService Language="c#" Codebehind="Service1.asmx.cs" Class="PCSWebSrv1.Service1" %> Этот код ссылается на файл кода, который можно увидеть в VS.NET, — Service1.asmx.cs, доступный при щелчке правой кнопкой мыши на Service1.asmxв Solution Explorer и выборе View Code. Созданный код с удаленными для краткости комментариями показан ниже: namespace PCSWebSrv1 { using system; using System.Collections; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Web; using System.Web.Services; public class Service1 : System.Web.Services.WebService { public Service1() { InitializeComponent(); } private void InitializeComponent() { } public override void Dispose() { } } } Этот код определяет пространство имен PCSWebSrv1с несколькими ссылками на стандартные пространства имен и класс службы Web с именем Service1(ссылку на который мы видели выше в файле Service1.asmx), производный от System.Web.Services.WebService. Мы должны предоставить методы для этого класса службы Web. Добавление метода, доступного через службу Web, требует простого определения метода как publicи задание для него атрибута WebMethod. Этот атрибут помечает методы, которые мы хотим сделать доступными. Вскоре мы рассмотрим типы данных, которые можно использовать для возвращаемого типа и для параметров, но пока добавим следующий метод: [WebMethod] public String CanWeFixIt() { return "Yes we can!"; } и откомпилируем метод. Можно проверить, как это будет работать, направляя браузер Web на файл Service1.asmx: Щелчок на имени метода предоставляет нам информацию о запросе и ответе SOAP, а также примеры того, как запрос и ответ будут выглядеть с помощью методов HTTP GET и HTTP POST. Можно также протестировать метод, нажимая на предоставленную кнопку Invoke (если метод требует простых параметров, их также можно ввести в этой форме). Если сделать это, мы увидим код XML, возвращаемый вызовом метода: <?xml version="1.0" ?> <string xmlns="http://tempuri.org/">Yes we can!</string> Это показывает, что метод работает прекрасно. Следование по ссылке Service Description, показанной на экране браузера выше, позволяет увидеть описание WSDL службы Web. Наиболее важной частью, имеющей к нам отношение, является описание типов элементов для запросов и ответов: <types> <s:schema attributeFormDefault="qualified" elementFormPefault="qualified" targetNamespace="http://tempuri.org/"> <s:element name="CanWeFixIt"> <s:complexType /> </s:element> <s:element name="CanWeFixItResponse"> <s:complexType> <s:sequence> <s:element name="CanWeFixItResult" nullable="true" type="s:string" /> </s:sequence> </s:complexType> </s:element> <s:element name="string" nullable="true" type="s:string" /> </s:schema> </types> Это описание содержит также описание типов данных, требуемых для запросов и ответов, а также различных соединений для службы, делая его достаточно длинным файлом. Типы данных, доступные для служб WebСлужбы Web могут использоваться для обмена любыми из следующих типов данных: String Char Byte Boolean Int16 Int32 Int64 UInt16 UInt32 UInt64 Single Double Guid Decimal DateTime XmlQualifiedName class struct XmlNode DataSet Массивы всех приведенных выше типов данных также допустимы. Отметим, также, что маршализуются только открытые свойства и поля типов classи struct. Использование служб WebТеперь, когда мы знаем, как создавать службы Web, пришло время разобраться, как они используются. Чтобы сделать это, необходимо создать в коде класс прокси, который знает, как общаться с заданной службой Web. Любые обращения из кода к службе Web будут проходить через этот прокси, который выглядит идентично службе Web, создавая в коде иллюзию, что имеется локальная копия службы Web. В реальности существует большой объект коммуникации HTTP, но мы защищены от деталей. Для этого существуют два способа. Можно пользоваться либо утилитой командной строки WSDL.exe, либо пунктом меню Add Web Reference в VS.NET. При использовании утилиты WSDL.exeсоздается файл .cs, содержащий класс прокси на основе описания WSDL службы Web. Мы определяем это с помощью URL, например: WSDL http://localhost/PCSWebSrv1/Service1.asmx?WSDL Для примера из последнего раздела эта утилита создаст файл с именем Service1.csкласса прокси. Класс называется по имени cлужбы Web, в данном случае Service1, и будет содержать методы, которые вызывают идентично названные методы службы. Чтобы использовать этот класс, мы просто добавляем файл .cs, созданный для проекта, и используем следующий код: Service1 myService = new Service1(); String result = myService.CanWeFixIt(); По умолчанию созданный класс будет помещен в корневое пространство имен, поэтому не нужен никакой оператор using, но можно определить для использования другое пространство имен с помощью параметра командной строки /n<namespace> утилиты WSDL.exe. Эта техника хорошо работает, но может оказаться неудобным непрерывно переделывать код, если служба разрабатывается и постоянно изменяется. Конечно, можно было бы делать это в режиме сборки проекта, чтобы автоматически обновлять созданный прокси перед каждой компиляцией, но существует способ лучше. Мы проиллюстрируем его в новом приложении Web с именем PCSWebClient1, создавая клиента для примера из последнего раздела. В теле формы на созданной странице .aspxнеобходимо заменить существующее объявление form на следующий код: <form method="post" runat="server"> <asp:Label Runat="server" ID="resultLabel" /> <br> <asp:Button Runat="server" ID="triggerButton" Text="Invoke CanWeFixIt()" /> </form> Соединим обработчик события нажатия кнопки со службой Web. Для начала добавим в проект ссылку на службу Web. Чтобы сделать это, щелкнем правой кнопкой мыши на приложении в Solution Explorer и выберем пункт Add Web Reference… В появившемся окне введем URL файла .vsdiscoслужбы Web: Здесь можно следовать по ссылкам справа, чтобы получить те же самые описания с границы Web службы, которые мы видели в предыдущем разделе, и добавить ссылку с помощью кнопки Add Reference Нажатие на эту кнопку приведет к следующим изменениям в Solution Explorer: Папка, содержащая нашу ссылку Web, называется по имени сервера, где расположена служба, в данном случае — localhost. Это также пространство имен, на которое необходимо ссылаться, чтобы использовать класс прокси, поэтому имеет смысл переименовать папку, что можно сделать с помощью щелчка правой кнопкой мыши на папке. Если переименовать эту папку в myWebServiceи добавить инструкцию usingв код… using PCSWebClient1.myWebService; …то тогда можно будет использовать службу в нашем классе. Добавим обработчик событий к кнопке на форме с помощью следующего кода: protected void triggerButton_Сlick(object sender, System.EventArgs e) { Service1 myService = new Service1(); resultLabel.Text = myService.CanWeFixIt(); } Нажатие кнопки во время выполнения приложения приведет к выводу CanWeFixIt()в окне браузера. Служба Web может впоследствии измениться, но с помощью такого метода можно просто сделать щелчок правой кнопкой мыши на ссылке Web в проводнике сервера и выбрать Update Web Reference. Это создаст для нас новый класс прокси. Расширение примера заказа помещения для проведения мероприятийТеперь, когда мы знакомы с основами создания и использования служб Web, давайте применим наши знания, расширив приложение заказа помещения для проведения мероприятий из предыдущей главы. В частности, извлечем детали доступа к базе данных из приложения и поместим их в службу Web. Эта служба Web имеет два метода: □ GetData(), который будет возвращать объект DataSet, содержащий все три таблицы базы данных PCSWebApp3. □ AddEvent(), добавляющий событие и возвращающий обновленную версию DataSet, которая включает изменение Кроме того, мы создадим службу Web, помня о некоторых приемах сокращения нагрузки из предыдущей главы. В частности, мы будем хранить DataSetна уровне приложения в приложении службы Web. Это означает, что несколько запросов данных не потребуют работы дополнительных запросов к базе данных. Данные в этом DataSetуровня приложения обновятся, когда в базу данных добавятся новые данные. Это означает, что изменения, сделанные в базе данных другими средствами, такими как редактирование вручную, не будут отражаться в этом DataSet. Тем не менее, до тех пор, пока мы знаем, что наша служба Web является единственным местом с прямым доступом к данным, нам не о чем беспокоиться. Служба Web заказа помещения для проведения мероприятийСоздайте новый проект службы Web в VS.NET с именем PCSWebSrv2. Для начала добавим код в обработчик Application_Start()в global.asax. Мы хотим загрузить все данные из PCSWebApp3.mdbв множество данных и сохранить его. Это будет по большей части включать код, с которым мы знакомы, так как перенос базы данных в DataSetуже делали. Фактически, можно скопировать весь нужный код из WebForm1.aspx.csв PCSWebApp3из предыдущей главы, включая строку соединения с базой данных (которая здесь не показана, так как у читателя она должна быть, скорее всего, другой): protected void Application_Start (Object sender, EventArgs e) { System.Data.DataSet ds; System.Data.OleDb.OleDbConnection оleDbConnection1; System.Data.OleDb.OleDbDataAdapter daAttendees; System.Data.OleDb.OleDbDataAdapter daRooms; System.Data.OleDb.OleDbDacaAdapter daEvents; oleDbConnection1 = new System.Data.OleDb.OleDbConnection(); oleDbConnection1.ConnectionStnng = @" ... "; oleDbConnection1.Open(); ds = new DataSet(); daAttendees = new System.Data.OleDb.OleDbDataAdapter( "SELECT * FROM Attendees", oleDbConnection1); daRooms = new System.Data.OleDb.OleDbDataAdapter( "SELECT * FROM Rooms", oleDbConnection1); daEvents = new System.Data.OleDb.OleDbDataAdapter( "SELECT * FROM Events", oleDbConnection1); daAttendees.Fill(ds, "Attendees"); daRooms.Fill(ds, "Rooms"); daEvents.Fill(ds, "Events"); oleDbConnection1.Close(); Application["ds"] = ds; } Необходимо отметить важный код в последней строке. Объекты Application(и Session) имеют коллекцию пар имя/значение, которую можно использовать для хранения данных. Здесь создается имя dsв хранилище объекта Application, которое получает сериализованное значение DataSetиз ds, содержащее таблицы Attendees, Roomsи Eventsиз базы данных. Это значение будет доступно всем экземплярам службы Web в любое время. Чтобы приведенный выше код работал, нам нужно также добавить ссылку на пространство имен System.Dataв пространстве имен PCSWebSrv2в global.asax: namespace PCSWebSrv2 { ... using System.Data; Эта техника очень полезна для данных, предназначенных только для чтения, так как несколько потоков выполнения смогут к нему обращаться, сокращая нагрузку на базу данных. Отметим, однако, что таблица Eventsскорее всего должна измениться и будет обновлять DataSetна уровне приложения, когда это произойдет. Мы скоро это увидим. Затем необходимо добавить к службе в Service1.asmx.csметод GetData(): [WebMethod] public DataSet GetData() { return (DataSet)Application["ds"]; } Здесь для доступа к множеству данных используется тот же синтаксис, что и в Application_Load(), где просто выполняется преобразование типа данных в правильный тип, а также возврат. Метод AddEvent()немного сложнее. Концептуально нам необходимо сделать следующее: □ Получить данные события от клиента. □ Создать инструкцию SQL INSERTс помощью этих данных. □ Соединиться с базой данных и выполнить инструкцию SQL. □ Если добавление выполнится успешно, то обновить данные в Application["ds"]. □ Вернуть уведомление об успехе или отказе клиенту (мы оставляем клиенту возможность обновить его DataSet, если потребуется). Начиная сверху, принимаем все поля как строки: [WebMethod] public int AddEvent(String eventName, String eventRoom, String eventAttendees, String eventDate) { } Затем мы объявляем объекты, которые нужны для доступа к базе данных, соединяемся с базой данных и выполняем запрос, используя код аналогичный коду в PCSWebApp3(здесь также требуется строка соединения, которая здесь не показана): [WebMethod] public int AddEvent(String eventName, String eventRoom, String eventAttendees, String eventDate) { System.Data.OleDb.OleDbConnection oleDbConnection1; System.Data.OleDb.OleDbDataAdapter dbEvents; DataSet ds; oleDbConnection1 = new System.Data.OleDb.OleDbConnection(); OleDbConnection1.ConnectionString = @" ... "; String oleDbCommand = "INSERT INTO Events (Name, Room, AttendeeList, " + " EventDate) VALUES ('" + eventName + "', + eventRoom + "', '" + eventAttendees + "', '" + eventDate + "')"; System.Data.OleDb.OleDbCommand insertCommand = new System.Data.OleDb.OleDbCommand(oleDbCommand, oleDbConnection1); oleDbConnection1.Open(); queryResult = insertCommand.ExecuteNonQuery(); } Используем, как и прежде, queryResultдля хранения числа строк, затронутых запросом. Мы можем проверить его, чтобы оценить наш успех. Если все происходит хорошо, выполняется новый запрос на базе данных для обновления таблицы Eventsв нашем DataSet. Жизненно важно блокировать данные приложения во время выполнения обновлений, чтобы гарантировать, что никакие другие потоки выполнения не могут получить доступ к Application["ds"]во время его обновления. Это можно сделать с помощью методов Lock()и UnLock()объекта Application: [WebMethod] public int AddEvent(String eventName, String eventRoom, String eventAttendees, String eventDate) { ... int queryResult = insertCommand.ExecuteNonQuery(); if (queryResult == 1) { daEvents = new System.Data.OleDb.OleDbDataAdapter( "SELECT * FROM Events", oleDbConnection1); Application.Lock(); ds = (DataSet) Application["ds"]; ds.Tables["Events"].Clear(); daEvents.Fill(ds, "Events"); Application["ds"] = ds; Application.UnLock(); oleDbConnection1.Close(); } } Наконец, мы возвращаем queryResult, позволяя клиенту узнать, что запрос был успешным: [WebMethod] public int AddEvent(String eventName, String eventRoom, String eventAttendees, String eventDate) { ... return queryResult; } Это завершает создание службы Web. Как и прежде, есть возможность протестировать эту службу, направляя браузер Web на файл .asmx, поэтому мы можем добавить записи и взглянуть на представление XML для DataSet, возвращаемое GetData(), не создавая никакого клиентского кода. Клиент приложения предварительного заказа помещения для проведения мероприятияИспользуемый клиент является разработкой приложения Web PCSWebApp3из предыдущей главы. Назовем это приложение PCSWebApp4и воспользуемся кодом из PCSWebApp3в качестве начальной точки. Сделаем два существенных изменения в проекте. Первое: удалим все непосредственные обращения к базе данных из этого приложения и воспользуемся вместо этого службой Web. Второе: введем хранилище уровня приложения из DataSet, возвращаемого из службы Web, которое обновляется только в случае необходимости, это значит, что на базу данных падает меньшая нагрузка. Прежде всего в нашем новом приложении Web необходимо добавить ссылку Web на службу PCSWebSrv2/Service1.asmx. Это можно сделать точно таким же образом, как мы видели ранее в этой главе, определяя местонахождение файла .vsdiscoи вызывая его eventDataService. После этого добавляем код в Global.asax, по большей части, таким же образом, как это было сделано для службы Web. Этот код, однако, будет существенно проще. Сначала мы ссылаемся на службу Web и пространство имен System.Data: namespace PCSWebApp4 { ... using System.Data; using eventDataService; Затем заполняем множество данных ( dataset) и помещаем его в хранилище данных уровня приложения с именем ds: protected void Application_Start(Object sender, EventArgs e) { Service1 dataService = new Service1(); DataSet ds = dataService.GetData(); Application["ds"] = ds; } Теперь DataSetдоступно для всехэкземпляров PCSWebApp4, т.е. несколько пользователей могут читать данные без какого-либо обращения к службе Web, то есть к базе данных. Теперь, когда имеется это DataSet, необходимо изменить WebForm1.aspx.csдля его использования. Прежде всего можно удалить объявления oleDbConnection1, daAttendees, daRoomsи daEvents, так как не будет осуществляться никакого обращения к базе данных. Затем необходимо изменить Page_Load()следующим образом: private void Page_Load(object sender, System.EventArgs e) { validationSummary.Enabled = false; foreach (System.Web.UI.WebControls.WebControl validator in this.Validators) { validator.Enabled = false; } ds = (DataSet)Application["ds"]; attendeeList.DataSource = ds.Tables["Attendees"]; roomList.DataSource = ds.Tables["Rooms"]; eventTable = ds.Tables["Events"]; eventDetails1.DataSource = eventTable; eventDetails2.DataSource = eventTable; if (!this.IsPostBack) { System.DateTime trialDate = System.DateTime.Now; calendar.SelectedDate = getFreeDate(trialDate); this.DataBind(); } else { eventDetails1.DataBind(); eventDetails2.DataBind(); } } Большая часть кода остается без изменений, необходимо только использовать Application["ds"]вместо получения DataSet. Необходимо также изменить submitButton_Click()для использования метода AddData()службы Web. В этом случае также большая часть кода остается без изменений: protected void submitButton_Click(object sender, System.EventArgs e) { foreach (System.Web.UI.WebControls.WebControl validator in this.Validators) { validator.Enabled = true; } this.Validate(); if (this.IsValid) { String attendees = ""; foreach (ListItem attendee in attendeeList.Items) { if (attendee.Selected) { attendees += attendee.Text + " (" + attendee.Value + "), "; } } attendees += " and " + nameBox.Text; String dateString = calendar.SelectedDate.Date.Date.ToShortDateString(); Service1 dataService = new Service1(); int queryResult = dataService.AddEvent(eventBox.Text, roomList.SelectedItem.Value, attendees, dateString); if (queryResult == 1) { resultLabel.Text = "Event Added"; ds = dataService.GetData(); Application.Lock(); Application["ds"] = da; eventTable = ds.Tables["Events"]; calendar.SelectedDate = getFreeDate(calendar.SelectedDate.AddDays(1)); eventDetails1.DataSource = eventTable; eventDetails1.DataBind(); eventDetails2.DataSource = eventTable; eventDetails2.DataBind(); } else { resultLabel.Text = "Event not added due to DB access problem."; } } else { validationSummary.Enabled = true; } } Фактически, мы существенно упростили систему. Это часто бывает при правильном проектировании служб Web — можно забыть о большей части работы приложения и вместо этого сосредоточиться на работе пользователя. К этому коду почти не требуется комментариев. Продолжающееся использование queryResultявляется дополнительной премией, а блокирование приложения существенно, как уже было отмечено. Приложение Web PCSWebApp4выглядит и функционирует точно также, как PCSWebApp3, но выполняется существенно лучше. Можно также очень легко использовать эту же службу Web для других приложений, просто выводя на странице мероприятия, например, или редактируя мероприятия, имена почетных гостей и помещения, если добавить несколько других методов. Все это не разрушит PCSWebApp4, так как мы будем просто игнорировать все вновь созданные методы. ЗаключениеВ этой главе мы увидели, как создавать и использовать службы Web с помощью C# и платформы разработки VS.NET. Сделать это достаточно просто, но какая это невероятно полезная возможность. Уже сейчас мы видим множество объявлений о новых службах Web и можно ожидать, что скоро они будут повсюду. Также было отмечено, что службы Web могут быть доступны с любой платформы. Это связано с простотой протокола SOAP, который не ограничивается платформой .NET. Пример, разработанный в этой главе, иллюстрирует, как можно легко создавать распределенные приложения .NET. Здесь предполагается, что для тестирования используется один сервер, но почему бы службу Web полностью не отделить от клиента. Она может даже находиться на отдельном от базы данных сервере, если требуется дополнительная связь данных. Использование кэширования данных является другой важной техникой, которую необходимо освоить для использования в крупномасштабных приложениях, когда имеются тысячи одновременно присоединяющихся пользователей. Конечно, в такой ситуации использование Microsoft Access в качестве источника данных может оказаться не лучшей идеей. Наконец, стоит помнить, что потребителями службы Web не обязательно должны быть приложения Web. Нет причин, по которым нельзя использовать службы Web из приложений платформы Windows, что может оказаться привлекательным для корпоративных сетей интранет. |
|
||
Главная | В избранное | Наш E-MAIL | Добавить материал | Нашёл ошибку | Наверх | ||||
|