Работа вне браузера и с web-сервисами
Ниже приведены некоторые опции для утилиты.
При создании приложения Silverlight можно использовать так называемое "дуплексное" взаимодействие. Это когда сервер вызывает методы клиента, например, для системы мониторинга клиента. Либо, например, клиент вызывает веб-сервис, с помощью которого подписывается на какое-либо событие на сервере. Когда это событие происходит веб-сервис обращается к клиенту и вызывает там какой-нибудь метод. Для реализации этого необходимо на клиенте с помощью средств WCF запустить прослушивание порта TCP. Этого может не допустить файрвол клиента. Реализовать "псевдо-дуплекс" (эмуляция) можно периодически вызывая веб-сервис и опрашивая его на предмет наличия обновлений.
В Silverlight 3 дуплексное взаимодействие осуществляется с помощью фабрики factory, имеющейся в библиотеке System.ServiceModel.PollingDuplex, состоящей из клиентской *.dll для приложения Silverlight и серверной для веб-сервиса. Реализовать дуплекс в Silverlight 3 гораздо проще и не нужны знания WCF. Библиотеки расположены в каталогах C:\Program Files\Microsoft SDKs\Silverlight\v3.0\Libraries\Client\System.ServiceModel.PollingDuplex.dll и C:\Program Files\Microsoft SDKs\Silverlight\v3.0\Libraries\Server\System.ServiceModel.PollingDuplex.dll.
Чтобы организовать дуплекс, необходимо на веб-сервисе определить контракт с обратным вызовом:
[ServiceContract(CallbackContract = typeof(…))] [OperationContract(IsOneWay = true)]
Получить вызывающего "клиента"
OperationContext.Current.GetCallbackChannel<…>();
Для примера приведится приложение периодически генерирующее GUID, который после генерации передается клиенту и отображается в приложении Silverlight. Ниже приведен код веб-сервиса:
namespace DuplexCommunication.Web { [ServiceContract(Namespace = "", CallbackContract = typeof(ICallback))] public class DataPushService { private ICallback client; private Timer timer; [OperationContract(IsOneWay = true)] public void Subscribe() { client = OperationContext.Current.GetCallbackChannel<ICallback>(); timer = new Timer( new TimerCallback(PushUpdateToClient), null, 0, 3000); return; } private void PushUpdateToClient(object state) { try { client.Update(Guid.NewGuid().ToString()); } catch (TimeoutException) { timer.Dispose(); } catch (CommunicationException) { timer.Dispose(); } } } [ServiceContract] public interface ICallback { [OperationContract(IsOneWay = true)] void Update(string message); } }
Здесь в коде опеределен контракт и указан параметр CallbackContract = typeof(ICallback). Параметр ICallback представляет собой интерфейс, который передает одну переменную string message. Т.е. в этом примере GUID. В методе Subscribe() каждые 3 секунды генерируется новый GUID и в методе PushUpdateToClient он передается клиенту.
На клиенте добавляется ссылка на веб-сервис, как было показано ранее. Но адрес веб-сервиса нужно указать явно "http://localhost:6652/DataPushService.svc".
namespace DuplexCommunication { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); DataPushServiceClient proxy = new DataPushServiceClient(binding, address); proxy.UpdateReceived += new EventHandler<UpdateReceivedEventArgs>(proxy_UpdateReceived); proxy.SubscribeAsync(); } EndpointAddress address = new EndpointAddress(@"http://localhost:6652/DataPushService.svc"); CustomBinding binding = new CustomBinding( new PollingDuplexBindingElement(), new TextMessageEncodingBindingElement (MessageVersion.Soap12WSAddressing10, Encoding.UTF8), new HttpTransportBindingElement()); void proxy_UpdateReceived(object sender, UpdateReceivedEventArgs e) { serverResponse.Text = e.message; } } }
Здесь создается прокси-класс, который "подписывается" на событие proxy.UpdateReceived, proxy.SubscribeAsync(). При возникновении этого события вызывается метод proxy_UpdateReceived, который выводит на экран то, что передает веб-сервис через прокси-класс.
Подключение приложения Silverlight к веб-сервису REST
Для доступа к REST сервису приложение Silverlight использует классы HttpWebRequest и WebClient. REST сервис возвращает данные в определенном формате. Если это формат XML, то на стороне сервера используются средства XmlReader / XmlWriter, Linq to XML, XmlSerializer.
Чтобы вызвать веб-сервис REST надо:
- Сослаться на веб-сервис Uri serviceUri = new Uri("http://fabrikam.com/service/getUser")
- В случае, если приложение Silverlight находится в другом домене, чем веб-сервис, надо настроить кроссдоменность (см. ранее).
- Создать экземпляр класса WebClient downloader = new WebClient()
- Вызвать асинхронно и подписаться на событие получения ответа downloader.OpenReadCompleted += new OpenReadCompletedEventHandler(downloader_OpenReadCompleted); downloader.OpenReadAsync(serviceUri)
- Начать обрабатывать результат System.IO.Stream responseStream = e.Result ;
Пример с классом WebClient:
public void HowToMakeRequestsToHttpBasedServices() { Uri serviceUri = new Uri("http://fabrikam.com/service/getUser"); WebClient downloader = new WebClient(); downloader.OpenReadCompleted += new OpenReadCompletedEventHandler(downloader_OpenReadCompleted); downloader.OpenReadAsync(serviceUri); } void downloader_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e) { if (e.Error == null) { System.IO.Stream responseStream = e.Result; } }
Таким образом, приложение Silverlight 3 может использовать как SOAP, так и REST веб-сервисы. И делается это довольно просто.