Опубликован: 01.03.2010 | Доступ: свободный | Студентов: 958 / 46 | Оценка: 4.38 / 4.31 | Длительность: 09:26:00
Лекция 3:

Работа вне браузера и с web-сервисами

< Лекция 2 || Лекция 3: 123456 || Лекция 4 >

Ниже приведены некоторые опции для утилиты.

-= COMMON OPTIONS =- C:\Program Files\Microsoft SDKs\Silverlight\v3.0\Tools>slsvcutil.exe
/directory:<directory> Directory to create files in (default: current directory) (Short Form: /d)
/slsvcutilConfig:<configFile> Custom configuration file to use in place of the app config file. This can be used to register system.serviceModel extensions without altering the tool's config file
/noLogo Suppress the copyright and banner message.
/help Display command syntax and options for the tool. (Short Form: /?)
-= CODE GENERATION =- Syntax: slsvcutil.exe <metadataDocumentPath>* | <url>* | <epr>
<metadataDocumentPath> The path to a metadata document (wsdl or xsd). Standard command-line wildcards can be used in the file path.
<url> The URL to a service endpoint that provides metadata or to a metadata document hosted online.
<epr> The path to an XML file that contains a WS-Addressing EndpointReference for a service endpoint that supports WS-Metadata Exchange.
Options:
/out:<file> The filename for the generated code. Default: derived from the WSDL definition name, WSDL service name or targetNamespace of one of the schemas. (Short Form: /o)
/config:<configFile> The filename for the generated config file. Default: ServiceReferences.ClientConfig
/mergeConfig Merge the generated config into an existing file instead of overwriting the existing file.
/noConfig Do not generate config
/language:<language> The programming language to use for generating code. Provide either a language name registered in the machine.config file or provide the fully-qualified name of a class that inherits from System.CodeDom.Compiler.CodeDomProvider. Examples of language names to use are CS and VB. Default: C#. (Short Form: /l)
/namespace:<string,string> A mapping from a WSDL or XML Schema targetNamespace to a CLR namespace. Using the '*' for the targetNamespace maps all targetNamespaces without an explicit mapping to that CLR namespace. Default: derived from the target namespace of the schema document for Data Contracts. The default namespace is used for all other generated types. (Short Form: /n)
/messageContract Generate Message Contract types. (Short Form: /mc)
/enableDataBinding Implement the System.ComponentModel.INotif yPropertyChanged interface on all Data Contract types to enable data binding. (Short Form: /edb)
/internal - Generate classes that are marked as internal. Default: generate public classes. (Short Form: /i)
/reference:<file path> Reference types in the specified assembly. When generating clients, use this option to specify assemblies that might contain types representing the metadata being imported. The assembly must be a Silverlight assembly. (Short Form: /r)
/collectionType:<type> A fully-qualified or assembly-qualified name of the type to use as a collection data type when code is generated from schemas. (Short Form: /ct)
/excludeType:<type> A fully-qualified or assembly-qualified type name to exclude from referenced contract types. (Short Form: /et)
/noStdLib Do not reference standard libraries. By default mscorlib.dll and System.ServiceModel.dll are referenced.
/serializer:Auto Automatically select the serializer. This tries to use the Data Contract serializer and uses the XmlSerializer if that fails. (Short Form: /ser)
/serializer:DataContractSerializer Generate data types that use the Data Contract Serializer for serialization and deserialization
/serializer:XmlSerializer Generate data types that use the XmlSerializer for serialization and Deserialization
/wrapped Generated code will not unwrap "parameters" member of document-wrapped-literal messages.

При создании приложения 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 надо:

  1. Сослаться на веб-сервис Uri serviceUri = new Uri("http://fabrikam.com/service/getUser")
  2. В случае, если приложение Silverlight находится в другом домене, чем веб-сервис, надо настроить кроссдоменность (см. ранее).
  3. Создать экземпляр класса WebClient downloader = new WebClient()
  4. Вызвать асинхронно и подписаться на событие получения ответа downloader.OpenReadCompleted += new OpenReadCompletedEventHandler(downloader_OpenReadCompleted); downloader.OpenReadAsync(serviceUri)
  5. Начать обрабатывать результат 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 веб-сервисы. И делается это довольно просто.

< Лекция 2 || Лекция 3: 123456 || Лекция 4 >