Chamada do Servidor para Silverlight 3 com WCF Duplex

Recentemente me deparei com a situação onde o servidor precisava enviar dados a
um cliente Silverligh, primeiramente pensei em fazer utilizando um timer no
cliente onde de tempos em tempos ele fazia uma chamada no servidor e o servidor
retornava os dados caso houvessem, mas devido ao alto tráfego de dados que
teríamos na rede e pela quantidade de acessos de clientes no sistema essa
solução foi descartada e então ficou o desafio, essa chamada deveria ser feita
pelo servidor assim não teríamos chamadas desnecessárias e só haveria a troca de
mensagens entre servidor e cliente nos momentos em que realmente houvessem dados
para serem trafegados.

A Solução veio com o uso de WCF Duplex que nos permite fazer chamadas
assíncronas do servidor para o cliente Silverlight.

Benefícios

Você reduz a carga no servidor, em vez dos clientes fazerem chamadas múltiplas
periodicamente, enviamos os dados do servidor para os clientes como e quando
quisermos.

Podemos eliminar ou reduzir a defasagem de dados em aplicações sensí­veis ao
tempo. Isto pode ser muito importante para aplicações que necessitam de
alterações de dados para mostrar como eles acontecem.

Todos os clientes recebem atualizações ao mesmo tempo.

Existe um aplicativo de exemplo agradável do Mix09 disponível
http://code.msdn.microsoft.com/silverlightws/Release/ProjectReleases.aspx?ReleaseId=2401
que cria um bate-papo, bem como um exemplo de chamadas do servidor. Sendo assim
um exemplo mais simples seria melhor para nos familiarizarmos com isso,
juntamente com um pouco mais explicação. Entretanto iremos utilizar a classe
genérica DuplexService que foi criada neste projeto.

O que nossa aplicação vai fazer

Queremos um exemplo simples, e é isso que vamos obter. O servidor irá
periodicamente enviar uma mensagem “LiveDataMessage” para qualquer cliente
Silverlight que esteja conectado, e o cliente irá exibi-la. Não estou preocupado
com os dados no servidor, apenas como enviá-lo para o cliente uma vez que o
temos.

Veja como será a estrutura do projeto

Criando o projeto

Primeiro crie um novo projeto do Silverlight, vamos chamá-lo DuplexExample e não
esqueça de incluir um Asp.Net Web Application com o nome padrão
(DuplexExample.Web). No site Web Adicione uma referência para o
System.ServiceModel.PollingDuplex.

Agora no projeto Silverlight também adicione uma referência para System.ServiceModel.PollingDuplex.

Baixe o exemplo Duplex
http://code.msdn.microsoft.com/silverlightws/Release/ProjectReleases.aspx?ReleaseId=2401,
extraia e copie o arquivo DuplexService.cs para seu web site.

Criando o serviço

Agora poderí­amos dicionar um serviço WCF usando os modelos do Visual Studio, mas
isso iria cria um monte de coisas que não precisamos que apenas temos que apagar
depois, sendo assim, basta adicionar um arquivo de texto e chamá-lo de
LiveDataService.svc. Isso nos dará um arquivo em branco no qual você pode
adicionar o seguinte:




<%
@ ServiceHost

Language=”C#”

Debug=”true”

Factory=”DuplexExample.Web.LiveDataServiceFactory”

Service=”DuplexExample.Web.LiveDataService”

%>

A única diferença aqui para o conteúdo de um arquivo normal svc é o fato de
que não há CodeBehind especificado e sim de forma explícita uma classe Factory.
(Veja aqui mais detalhes sobre estas opções: http://msdn.microsoft.com/en-us/library/aa967286.aspx) Desde que tenha especificado uma LiveDataService
para nosso serviço e classe LiveDataServiceFactory que será usado para
instanciar o serviço de fábrica, vamos ter que ir e criar esses.

Mas antes de fazer isso precisamos de uma classe DataContract chamada
LiveDataMessage, esta é a classe simples que o nosso serviço vai enviar para o
Silverlight.



[DataContract]

public class LiveDataMessage: DuplexMessage

{

[DataMember]

public
int
Value { get; set;
}

[DataMember]

public
string
Description { get; set;
}

}

Ok, então agora podemos criar nosso “LiveDataService”, adicione uma classe no
seu web site chamada LiveDataService.cs e adicione o seguinte código. Esta é bem
simples, estamos usando um timer para enviar uma mensagem a todos os clientes a
cada 5 segundos.


using System;

usingMicrosoft.Silverlight.Cdf.Samples.Duplex;

usingSystem.Threading;

namespace DuplexExample.Web

{

public
class
LiveDataService :DuplexService

{

Timer liveDataTimer;

public LiveDataService()

{

//Setup uma atualização a cada 5 segundos

this.liveDataTimer = newTimer(newTimerCallback(LiveDataUpdate),null, 0, 5000);

}

void LiveDataUpdate(objecto)

{

LiveDataMessage liveDataMessage = newLiveDataMessage()

{

Description =”Live Data at “+ DateTime.Now.ToLongTimeString(),

Value = newRandom().Next(0,
100)

};

PushToAllClients(liveDataMessage);

}

}

}

A Classe DuplexService

Você vai notar que a classe LiveDataService herda da DuplexService que nós adicionamos ao nosso projeto.

Esta classe também deve ser marcada com o atributo InstaceContextMode igual a
Single, desta forma o serviço pode acompanhar os clientes que estão conectados,
porque ela permanece na memória e não é descartada.

Ok, então o DuplexService fornece a abundância de graça, porém existe
uma coisa que precisamos alterar neste arquivo (você já deve ter notado que ele não está compilando), lá no fundo você ver uma lista de KnownTypes, estes relacionados para o projeto de exemplo que você baixou e não é o que nós queremos.

Nós temos somente uma KnownType específica (para além de conectar e desconectar) chamar o LiveDataMessage.

Agora, você precisa fazer a seguinte alteração no arquivo DuplexService.cs (na parte inferior):

A classe LiveDataServiceFactory

Finalmente adicionamos a classe LiveDataServiceFactory, que herda da classe DataServiceFactory no arquivo DuplexService.cs (isso é tudo o que faremos nesta classe)


namespace DuplexExample.Web
{
    public class LiveDataServiceFactory : DuplexServiceFactory<LiveDataService> {}
}

Veja que a classe DuplexServiceFactory também herda do arquivo DuplexService.cs, você verá que ele fornece a configuração para o serviço com um custom binding (esta é uma da alternativa de configuração para conserguirmos fazer o Serviço Duplex)

O Projeto Silverlight

Conpile sua solução, em seguida, adicione o serviço de referência do
LiveDataService no projeto Silverlight:

Eu criei uma interface bem simples, apenas um Botão e um Listbox:


<Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
        <RowDefinition Height="75"/>
        <RowDefinition Height="225"/>
    </Grid.RowDefinitions>
    <Button Content="Connect" 
            Click="ButtonConnect_Click"
            x:Name="ButtonConnect" Margin="10">
    </Button>
    <ListBox Grid.Row="1"
             ScrollViewer.VerticalScrollBarVisibility="Visible"              
             x:Name="ListBox1">
    </ListBox>
</Grid>




Aqui está todo o código da MainPage.Xaml.cs. Dê uma olhada e então vamos discutir o assunto:


public partial class MainPage : UserControl
{
    DuplexServiceClient receiver;
    ObservableCollection<string> liveDataMessages =
                                 new ObservableCollection<string>();
    CustomBinding binding = new CustomBinding(
                                new PollingDuplexBindingElement(),
                                new BinaryMessageEncodingBindingElement(),
                                new HttpTransportBindingElement()
                                );

    public MainPage()
    {
        InitializeComponent();

        ListBox1.ItemsSource = liveDataMessages;

        //make sure the endpoint address is correct
        receiver = new DuplexServiceClient(binding,
                  new EndpointAddress("http://localhost:6719/LiveDataService.svc"));
        receiver.SendToClientReceived += (sender, e) =>
            {
                if (e.msg is LiveDataMessage)
                {
                    LiveDataMessage msg = (LiveDataMessage)e.msg;
                    liveDataMessages.Add(string.Format("{0}.
                      Value = {1}", msg.Description, msg.Value));
                }
            };
    }

    bool connected = false;
    private void ButtonConnect_Click(object sender, RoutedEventArgs e)
    {
        if (connected)
        {
            Disconnect();
        }
        else
        {
            Connect();
        }
    }

    private void Connect()
    {
        ButtonConnect.Content = "Connecting...";
        receiver.SendToServiceCompleted += (sender, e) =>
        {
            ButtonConnect.Content = "Connected (click to disconnect)";
            connected = true;
        };
        receiver.SendToServiceAsync(new ConnectMessage());
    }

    private void Disconnect()
    {
        ButtonConnect.Content = "Disconnecting...";
        receiver.SendToServiceCompleted += (sender, e) =>
            {
                ButtonConnect.Content = "Disconnected (click to connect)";
                connected = false;
            };
        receiver.SendToServiceAsync(new DisconnectMessage());
    }
}

No topo deste código, foi declarado 3 variáveis: o DuplexServiceClient, um CustomBinding (que corresponde ao binding do serviço que criamos no servidor) e um ObservableCollection para armazenar as mensagens que recebemos do servidor.
Vamos instanciar o DuplexServiceClient no construtor da classe usando o custom binding e o endpoint (certifique se é este mesmo o endereço correto do seu serviço) e conectar o evento SendToClientReceived que é onde podemos adicionar as mensagens que recebemos do servidor para o ObservableCollection (que por sua vez, nos mostra no ListBox)

No entanto, também é preciso fornecer um método Connect (que envia um ConnectMessage para o servidor), essa chamada é essencial para o serviçõ Duplex no servidor identificar o cliente acompanhando através da sessão ID. Você pode ver isso no arquivo DuplexService.cs como abaixo (linha 133):

O método de desconexão faz o inverso, envia um DisconnectMessage para o
servidor que remove o cliente monitorado pela sessão ID.

Testando o aplicativo

Pressione F5 para executar o aplicativo, clique no botão Connect, veja que as mensagens enviadas para o Silverlight a partir do servidor a cada 5 segundos. Para torná-lo mais interessante, inicie uma segunda instância do navegador e execute a mesma aplicação. Você verá que ambos os clientes estão sendo atualizados exatamente ao mesmo tempo.

Baixe o código fonte aqui:
http://cid-fb8b852ef1ab0b35.skydrive.live.com/self.aspx/SampleCode/DuplexExample.zip

Artigo original:

http://silverlightforbusiness.net/2009/06/23/pushing-data-from-the-server-to-silverlight-3-using-a-duplex-wcf-service/

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Preencha esse campo
Preencha esse campo
Digite um endereço de e-mail válido.
Você precisa concordar com os termos para prosseguir

Menu