Аннотация: Данная статья написана когда автор столкнулся с необходимостью использования Web сервисов
в поставляемом в фирму ПО. До этого как то обходились без Web сервисов. Литературы в инете по данному вопросу много и много прочитано,
но очень многое еще и остается темными пятнами. Поэтому, по мере накопления знаний, статья будет модифицироваться и уточняться.
Автор будет благодарен за любые замечания и уточнения. Адрес почты - найдете на главной странице сайта по ссылке "Об авторе".
Параграф 1. Вместо предисловия
Параграф 2. Создаем WCF web сервис
Параграф 3. Публикация Web сервиса
Параграф 4. Создание клиентских Windows и Web приложений, использующих Web службу
Параграф 6. Совмещение проектов для удобства отладки Web сервисов
Параграф 7. О параметрах вызова методов Web Service
Веб-служба, веб-сервис (web service) — программная система, идентифицируемая строкой URI,
чьи общедоступные интерфейсы определены на языке XML (eXtensible Markup Language).
Благодаря веб-сервисам функции любой программы могут стать доступными через Интернет - программы могут
обращаться к какой-нибудь программе, работающей на другом сервере (т.е. к веб-сервису), и использовать ответ, полученный от нее
на своем веб-сайте, или в приложении.
Веб-службы обеспечивают взаимодействие программных систем независимо от платформы. Они
основаны на базе открытых стандартов и протоколов. Благодаря использованию XML достигается простота разработки и отладки веб-служб.
Используемые стандарты
XML: Расширяемый язык разметки, предназначенный для хранения и передачи структурированных данных;
SOAP (Simple Object Access Protocol): Протокол обмена сообщениями на базе XML;
WSDL (Web Services Description Language): Язык описания внешних интерфейсов веб-службы на базе XML;
UDDI: Универсальный интерфейс распознавания, описания и интеграции (Universal Discovery, Description and Integration).
Каталог веб-служб и сведений о компаниях, предоставляющих веб-службы во всеобщее пользование или конкретным компаниям.
Для создания Web сервиса в Visual Studio Net воспользуемся темплатой "WCF Server Application" (меню "File/New Project") и дадим ему имя
"MyFirstWebService" (Рис.1). Сразу отметим, что мы создаем непривычный для предыдущих Net Framework web сервис -
WCF (Windows Communication Foundation). WCF — программный фреймворк, используемый для обмена данными между приложениями входящими в
состав .NET Framework. До Net Framework 4 использовался немного другой сервис (его мы можем найти, если сменим в окне ".Net Framework 4",
на ".Net Framework 3.5" и найдем темплату ASP.NET Web Service Application). Создав проект на базе этой темплаты, мы найдем привычные .asmx файлы,
которых, как видно из Рис.2. нет в проекте WCF сервиса. Это не просто смена имен файлов, а смена технологии -
WCF делает возможным построение безопасных и надёжных транзакционных систем через упрощённую унифицированную программную модель
межплатформенного взаимодействия. Комбинируя функциональность существующих технологий .NET по разработке распределённых приложений
(ASP.NET XML Web Services — ASMX, WSE 3.0, .NET Remoting, .NET Enterprise Services и System.Messaging).
WCF предоставляет единую инфраструктуру разработки, повышающую производительность и снижающую затраты на создание безопасных,
надёжных и транзакционных Web-служб нового поколения.
Собственно говоря мы уже приступили к его созданию (см.выше). На Рис.1. показан выбор темплаты и задание имени службы - "MyFirstWebService" и
таким же оставим и имя проекта. Если мы планируем тестировать службу перед применением и будем создавать Host и клиентское приложение для работы,
то имена службы и проекта следует разделить. После нажатия кнопки "OK" служба практически создана.
Рис.1. Создание Web сервиса WCF
Рис.2. Создание Web сервиса WCF
Сервис WCF представлен основным файлом Service1.svc.cs (Рис.2.), где размещены методы сервиса, IService1.cs - методы интерфейса и два файла
Web.config для двух режимов. Кроме того обратим внимание на закладке References и в используемых пространствах имен на ссылки System.ServiceModel:
Стартовый пример показывает и то, как вводить данные собственных типов ([DataContract]):
Так как сервис создан, нажав F5, мы можем посмотреть его презентационное представление и указание на то, что делать дальше. А нажав
ссылку svcutil.exe http://localhost:3818/Service1.svc?wsdl - можем посмотреть с помощью "svcutil.exe" его XML содержание (.wsdl файл, в котором описывается, что сервис может делать
и с какими данными он может работать) - (Рис.3).
Рис.3. Web сервис WCF
В XML коде мы можем найти:
контракт сервиса (2 метода: GetData, GetDataUsingDataContract);
контракт данных (2 встроенных типа: int, string, + 1 собственный тип: CompositeType состоящий из bool и string);
сигнатуры методов (из wsdl:input message= и wsdl:output message=).
Для отладки сервиса можно использовать "WCF Test Client". Выберем узел "Service1.svc" и в его контекстном меню выберем пункт
"Set As Start Page" и нажмем F5. Теперь появится окно "WCF Test Client" (Рис.4.). В нем мы можем просмотреть и протестировать наши методы
и посмотреть их XML реализацию.
Рис.4. Использование WCF Test Client
Наполним сервис своим содержанием, например, поставим ему задачу проверять валидность почтовых адресов, для чего в файле
IService1.cs оставим один контакт(OperationContract).
В принципе, если мы уверены в работоспособности службы, то мы можем ее опубликовать.
Опубликуем наш сервис. Режим компиляции выберем "Release", на всякий случай перекомпилируем службу (меню "Build/RebuildMyFirstService") и далее
выбираем меню "Build/Publish MyFirstService" (Рис.5.):
Рис.5. Публикация службы
На Рис.6. показано, что мы публикуем службу туда, куда IIS нам определил сайт по умолчанию (Default Web Site). Это сделано для удобства.
В принципе, когда мы работаем "на дядю", то есть, сайт у нас на другой машине, то можно опубликовать в любое место, а затем скопировать
файлы сборки в нужное место, а далее с помощью тамошнего IIS сделать директорию сборки приложением. Еще один момент - не рекомендуется менять имя
сервиса.
Рис.6. Публикация службы
Теперь превратим нашу папку сборки в приложение IIS.
Рис.7. Создание приложения
Рис.8. Создание приложения
Осталось проверить работоспособность службы, как показано на Рис.9., и доступность кода XML, как это делали выше, нажав ссылку
http://localhost/MyFirstWebService/Service1.svc?wsdl:
Отметим, что для выборки службы мы использовали вызов
Рис.9. Проверка службы
Далее создадим новый проект - либо консольное, либо WindowsApplication или Asp.Net приложение, которое будет обращаться к службе.
У нас будет возможность проверить, являются ли действительными указанные адреса электронной почты, или, по крайней мере удовлетворяющими
нашему регулярному выражению. Я создал обычное ASP.Net Web приложение (Рис.10.):
Рис.10. Создание ASP.NET приложения
Поместим на форму два контрола: Button и Label и добавим ссылку на наш сервис как показано на Рис.11-17.
Рис.11. Создание ASP.NET приложения
Рис.12. Добавление ссылки на сервис
Рис.13. Добавление ссылки на сервис
Рис.14. Добавление ссылки на сервис
Если сервис не отображается - введите его адрес и нажмите зеленую кнопочку справа:
Рис.15. Добавление ссылки на сервис
Задайте имя сервису для приложения и нажмите кнопочку "Add Reference":
Рис.16. Добавление ссылки на сервис
Рис.17. Ссылка на сервис добавлена
Добавим код в приложение, как показано на Рис.18.
Рис.18. Код приложения
Испытаем приложение - результат показан на Рис.19.
Рис.19. Выполнение ASP.NET приложения
Проделав все то же cамое для Windows приложения, получим тот же результат (Рис.20):
Рис.20. Выполнение Windows приложения
Возьмем наш проект в том виде, в котором он изображен на Рис.5. - иначе на момент когда мы создали наш сервис.
Переименуем решение из MyFirstService в FirstService, воспользовавшись контекстным меню, пункт "Rename".
К решению добавим, например Console Application (контекстное меню решения, пункты "Add/New Project" - темплата "Console Application" (закладка "Windows")).
Не меняя имени приложения нажмем кнопку "OK". Получим результат, показанный на Рис.21.
Рис.21. Сервис и консольное приложение
Кликаем в Solution Exploreре на узле CondoleApplication1 и в контекстном иеню выбираем "Add Service Reference" (Рис.22.).
Рис.21. Сервис и консольное приложение
Далее повторяем шаги, показанные на Рис.12-14. На шаге Рис.14. выбираем "Web Services in This Solution" (Рис.23.).
Рис.23. Добавление сервиса из текущего проекта
Выбираем Service1 и даем ему имя, например "myservice", нажимаем кнопку "Add Reference" (Рис.24.).
Рис.24. Добавление сервиса из текущего проекта
В проет ConsoleApplication добавляем пространство имен:
и код
Кликаем в Solution Exploreре на узле CondoleApplication1 и в контекстном иеню выбираем пункт "Set as Startup Project".
Запускаем приложение и получаем резельтат, как показано на Рис.25.
Рис.25. Исрользование Web сервиса в целях отладки приложения
После отладки приложения мы точно также можем публиковать наш сервис, как это описано выше.
Пока мы работали с методом, в котором все параметры строки, проблем не было с вызовом метода, ровно, как и с тем как, и сколько параметров
определено в файле интерфейса, и с тем, как и столько параметров используется.
Однако. Если мы зададим в IService1.cs контакт с параметрами типа int или другими, отличными от строковых, например:
При этом в файле Service1.svc.cs определим его, как метод возведения числа в квадрат:
Вновь добавим web ссылку на service в консольном приложении, как это сделано в параграфе 6. И теперь попытаемся
использовать наш метод:
То получим ошибку:
Кликнув правой кнопкой мышки на методе "square" и выбрав в контекстном меню "Go To Defination",
попадем в файл "Reference.cs", где увидим, что наш метод получил серьезное преобразование:
По крайней мере, параметров в методе стало 4. Прием первого параметра методом выглядит как обычно, а возврат результата осуществляется
через параметр типа "out".
Два параметра "xxxSpecified" определяют действительность параметров в сериализованном XML документе. Эти преобразования как раз и связаны
с передачей XML документа в сериализованном виде.
В MSDN написано: "Сериализация XML– это процесс преобразования открытых свойств и полей объекта в серийный формат (в данном случае в
формат XML) для хранения и транспортировки. Десериализация пересоздает объект в его исходном состоянии из вывода XML.
Сериализацию можно представить в качестве способа сохранения состояния объекта в поток или буфер.
Например, ASP.NET использует класс XmlSerializer для кодирования сообщений веб-службы XML.... схема включает
использование двух параметров - один параметр для использования (System.ComponentModel.DefaultValueAttribute) значения по умолчанию,
другой параметр для использования специального шаблона с целью создания логического поля, определяемого XmlSerializer, и с целью применения
XmlIgnoreAttribute к полю. Шаблон создается в форме propertyNameSpecified. Например, при наличии поля с именем "MyFirstName" (Мое имя) также
будет создано поле с именем "MyFirstNameSpecified" (Мое имя указано), инструктирующее XmlSerializer о необходимости генерирования элемента
XML с именем "MyFirstName"
Таким образом, мы вынуждены мириться с изменением определенных в интерфейсе методов, например, в нашем примере выход из положения прост:
Молчанов Владислав 15.12.2011г.
Параграф 1. Вместо предисловия
Параграф 2. Создаем WCF web сервис
using System.ServiceModel;
using System.ServiceModel.Web;
namespace MyFirstService
{
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
}
[DataContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace MyFirstWebService
{
[ServiceContract]
public interface IService1
{
[OperationContract]
string ValidateAddress(string address);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace MyFirstWebService
{
public class Service1 : IService1
{
public string ValidateAddress(string address)
{
string pattern = @"^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@(([0-9a-zA-Z])+([-\w]*[0-9a-zA-Z])*\.)+[a-zA-Z]{2,9})$";
if (Regex.IsMatch(address, pattern))
{
return address + " is valid";
}
else
{
return address + " is no valid";
}
}
}
}
Параграф 3. Публикация Web сервиса
http://localhost/MyFirstWebService/service1.svc
Параграф 4. Создание клиентских Windows и Web приложений, использующих Web службу
Параграф 6. Совмещение проектов для удобства отладки Web сервисов
using ConsoleApplication1.myservice;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ConsoleApplication1.myservice;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Service1 webservice = new Service1();
Console.WriteLine("Insert email adress!");
string str = Console.ReadLine();
str= webservice.ValidateAddress(str);
Console.WriteLine(str);
str = Console.ReadLine();
}
}
}
Параграф 7. О параметрах вызова методов Web Service
[OperationContract]
int square(int value);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace MyFirstService
{
public class Service1 : IService1
{
public int square(int p)
{
return (p*p);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ConsoleApplication1.myService;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Service1 webservice = new Service1();
Console.WriteLine("Insert number!");
string str = Console.ReadLine();
int a=webservice.square(Convert.ToInt32(str));
Console.ReadLine();
}
Error 1 No overload for method 'square' takes 1 arguments
E:\Service\FirstService\ConsoleApplication1\Program.cs 18 21 ConsoleApplication1
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/IService1/square",
RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/",
Use=System.Web.Services.Description.SoapBindingUse.Literal,
ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public void square(int value, [System.Xml.Serialization.XmlIgnoreAttribute()] bool valueSpecified,
out int squareResult, [System.Xml.Serialization.XmlIgnoreAttribute()] out bool squareResultSpecified)
{
object[] results = this.Invoke("square", new object[]{value,valueSpecified});
squareResult = ((int)(results[0]));
squareResultSpecified = ((bool)(results[1]));
}
static void Main(string[] args)
{
Service1 webservice = new Service1();
Console.WriteLine("Insert number!");
string str = Console.ReadLine();
//Так работать не будет
//int a = webservice.square(Convert.ToInt32(str));
int rez=0;
bool f = false;
//Так работает
webservice.square(Convert.ToInt32(str),true,out rez,out f);
Console.WriteLine(rez.ToString());
Console.ReadLine();
}