Você está na página 1de 68

Ano 10 - 110 Edio 2013 - ISSN 1980-3931 - Impresso no Brasil

Fale com o Editor!

Corpo Editorial

Atendimento ao Leitor
A DevMedia conta com um departamento exclusivo para
o atendimento ao leitor. Se voc tiver algum problema
no recebimento do seu exemplar ou precisar de algum

contato com:

Se voc estiver interessado em publicar um artigo na


revista ou no site .NET Magazine, entre em contato com os
editores, informando o ttulo e mini-resumo do tema que
voc gostaria de publicar:

www.devmedia.com.br/central
(21) 3382-5038

Joel Rodrigues - Editor da Revista


joelrlneto@gmail.com

esclarecimento sobre assinaturas, exemplares anteriores,

Editor Geral
Joel Rodrigues (joelrlneto@gmail.com)

Jornalista Responsvel
Kaline Dolabella - JP24185

Capa e Diagramao
Romulo Araujo

Na Web
ww.devmedia.com.br/dotnet

muito importante para a equipe saber o que voc est


achando da revista: que tipo de artigo voc gostaria de
ler, que artigo voc mais gostou e qual artigo voc menos
gostou. Fique a vontade para entrar em contato com os
editores e dar a sua sugesto!

endereo de bancas de jornal, entre outros, entre em

Publicidade

Joel Rodrigues

Para informaes sobre veiculao de anncio na


revista ou no site e para fechar parcerias ou aes

Editor Chefe da .net


Magazine e Easy .net
Magazine

especficas de marketing com a DevMedia, entre em


contato com:

Distribuio
FC Comercial e Distribuidora S.A
Rua Teodoro da Silva, 907 | Graja - RJ - 206563-900

Cristiany Queiroz
publicidade@devmedia.com.br

Assine agora e tenha acesso a


todo o contedo da DevMedia:
www.devmedia.com.br/mvp

04 Notificaes Push no Windows Phone 8


[ Felipe Farias Ferrari ]

Contedo sobre Boas Prticas

Sumrio
D
s

Contedo sobre Novidades

Feedback
eu

[ Henrique Machado Gasparotto ]

36 Integration Services2012: implementando solues de ETL - Parte 1


[ Renato Jos Groffe ]

Artigo no estilo Soluo Completa

58 Criando uma aplicao para conexes remotas


[ Mauro Pichiliani ]

edio
ta

Artigo no estilo Curso

sobre e
s

24 Data Binding em WPF: Interagindo com o BD

D seu feedback sobre esta edio!


A .NET Magazine tem que ser feita ao seu gosto.
Para isso, precisamos saber o que voc, leitor, acha
da revista!
D seu voto sobre esta edio, artigo por artigo,
atravs do link:
www.devmedia.com.br/netmagazine/feedback

Notificaes Push no Windows Phone 8

Notificaes Push no
Windows Phone 8
Enviando e recebendo notificaes a partir de um
servio externo

o Windows Phone, com o nmero crescente


de Apps, temos que sempre estar dispostos
a nos diferenciar dos concorrentes, com isso,
um dos diferenciais pode ser notificar o usurio sobre
algum evento importante em tempo real, ou mesmo de
tempos em tempos dependendo do propsito da App.
Alm disso, podemos utilizar as notificaes Push no
apenas como diferencial, mas tambm como core da
App, por exemplo, em jogos por turno.
Desse modo, esse artigo se prope a abordar como
podemos trabalhar com notificaes Push no Windows
Phone 8.

Resumo DevMan
Porque esse artigo til::
Este artigo ser til para os desenvolvedores que desejam utilizar
novas formas de comunicao e interao com suas Apps por parte
dos usurios, por exemplo, notificar sobre novas notcias, exibir
novas imagens nos Tiles, a partir de um mecanismo que funciona
mesmo com a App fechada, e que consome pouco recurso do telefone, como bateria.

Push Notifications
Podemos descrever as notificaes Push como mensagens que contm informaes e podem ser recebidas
pelas Apps, mesmo quando esta no se encontra em
execuo, dependendo do tipo de notificao enviada.
O servio Microsft Push Notification para o Windows
Phone oferece aos desenvolvedores um canal para envio
de dados a uma App do Windows Phone, de forma assncrona, a partir de um servio web ou na nuvem que
resulte em baixo consumo de energia pelo telefone.
Conforme a Figura 1, podemos entender como funciona o servio.
1. A App solicita ao cliente Push do telefone uma URI
para notificao.
2. O cliente Push negocia com o Microsoft Push Notification Service (MPNS), e o MPNS retorna uma URI nica
de notificao ao cliente Push do telefone.
3. O cliente Push retorna a URI de notificao para a
App.
4. A App pode enviar a URI recebida a um servio web
ou na nuvem para que esse servio web possa enviar
mensagens App quando necessrio.
5. Quando o servio web tem alguma mensagem para
ser enviada App, este ir enviar uma requisio

4 .Net Magazine Edio 110

Figura 1. Diagrama sobre como funciona o envio das notificaes. Fonte: MSDN
utilizando a URI de notificao recebida anteriormente para
o MPNS.
6. O MPNS encaminha a notificao Push para o telefone.
Nesse processo de envio, o MPNS responder com um cdigo
de resposta ao solicitante do Push, indicando se o mesmo foi
encaminhado ou ser encaminhado na prxima possibilidade
ao telefone. Tambm, o MPNS pode retornar indicando que o
Push no ser entregue e com isso, dependendo da situao,
o Push pode ser reenviado ou no. Apesar disso, o MPNS no
oferece uma confirmao de ponta a ponta de que o Push foi
realmente entregue.

Para o uso desse servio a Microsoft exige e/ou recomenda que


algumas aes sejam tratadas, ou implementadas para garantir
melhor o funcionamento do sistema, tais como:
Para o uso do Push o desenvolvedor deve incluir no seu arquivo
WMAppManifest.xml a indicao do uso do Push atravs da capability ID_CAP_PUSH_NOTIFICATION, conforme Figura 2.

de outro publicador tenha esse mesmo trecho de cdigo para recuperar o identificador do telefone, o identificador retornado ser
diferente entre uma App e outra. Contudo, para que seja possvel
obter esse identificador necessrio adicionar ao arquivo de Manifesto a identificao ID_CAP_IDENTITY_DEVICE;
A quantidade de aplicativos com notificaes Push por aparelho
limitada em 15 no Windows Phone 7 pr Mango (7.5), 30 para Windows Phone 7.5 e ilimitada para Windows Phone 8. Caso o limite
seja atingido, ao abrir o canal com cliente MPNS ser lanada uma
exceo e no ser possvel habilitar a notificao para o aparelho
at que o usurio remova as notificaes de outra App.

Figura 2. Demonstrao da funcionalidade que deve ser adicionada no arquivo de Manifesto


Como parte da poltica de certificao da App, a mesma deve
descrever ao usurio qual ser a finalidade para a qual o Push
ser usado, e que o mesmo deve confirmar o uso. Tambm, a
App deve oferecer um meio para que o usurio possa cancelar o
recebimento das notificaes push;
A App sempre deve verificar se um canal de push j existe antes
de tentar abri-lo, para evitar que o mesmo gere uma exceo durante a execuo. O canal, por sua vez, persiste mesmo que a App
seja atualizada, contudo, isso exige que o mesmo esteja atrelado
a uma notificao do tipo Tile ou Toast;
A App deve registrar-se no evento ChannelUriUpdated no caso
de uma mudana da Uri de notificao, mesmo que o canal j
esteja aberto. A URI expira de tempos em tempos, necessitando
que a App solicite uma nova URI;
A App deve registrar-se no evento ErrorOccurred para tratar
qualquer erro. Alguns dos possveis erros esto na Tabela 1;
Sempre que a App for aberta, ela deve enviar a URI ao servidor
web para que este tenha a URI sempre atualizada. Tambm recomendado que a App envie um identificador nico do telefone
para que seja possvel rastrear uma mudana de URI por parte
do servidor web. Como exemplo para obter um identificador de
cada telefone, na Listagem 1 temos o exemplo de uma soluo para
Windows Phone 7.1, j na Listagem 2, para uma soluo Windows
Phone 8. Em uma soluo Windows Phone 8, o identificador ser
nico por telefone e publicador, sendo assim, caso em outra App

Listagem 1. Propriedade para recuperar o identificador nico em uma soluo


Windows Phone 7.1
01 private string m_DeviceUniqueId;
02 public string DeviceId
03 {
04 get
05 {
06
if (m_DeviceUniqueId == null)
07
{
08
object val;
09
if (Microsoft.Phone.Info.DeviceExtendedProperties.TryGetValue
(DeviceUniqueId, out val))
10
m_DeviceUniqueId = Convert.ToBase64String((val as byte[]));
11
}
12
return m_DeviceUniqueId;
13 }
14 }
Listagem 2. Propriedade para recuperar o identificador nico em uma soluo
Windows Phone 8
01 private string m_DeviceUniqueId;
02 public string DeviceId
03 {
04 get
05 {
06
if (m_DeviceUniqueId == null)
07
{
08
m_DeviceUniqueId =
Windows.Phone.System.Analytics.HostInformation.PublisherHostId;
09
}
10
return m_DeviceUniqueId;
11 }
12 }

Erro

Descrio

PushErrorTypeChannelOpenFailed

O canal no existe, portanto no pode ser aberto. A App deve tentar abrir novamente.

PushErrorTypeMessageBadContent

Para uma mensagem do tipo Tile, a mesma no se enquadrou nas condies:


1) A URL no http://,
2) O nome do servidor excedeu 256 caracteres,
3) A URL excedeu 2055 caracteres,
4) O domnio no foi especificado dentro dos domnios permitidos.
Para uma mensagem do tipo Toast, o valor da tag Param excedeu o limite de 256 caracteres.

PushErrorTypeNotificationRateTooHigh A taxa de notificaes recebidas est muito alta. Diminuir a taxa de notificaes recebidas para evitar mensagens descartadas.
PushErrorTypePayloadFormatInvalid

O XML da mensagem est mal formatado ou com erros, ou o tipo de notificao no foi definido no cabealho da requisio, ou no se enquadra no tipo da requisio efetuada, com isso, o canal ser fechado. Portanto, devemos verificar o XML
da requisio e reabrir o canal para obter uma nova URI de notificao.

PushErrorTypeUnknown

Ocorreu um erro interno. O telefone talvez necessite ser reiniciado.

Tabela 1. Possveis erros que podem ser retornados no evento ErrorOccurred


Edio 110 .Net Magazine

Notificaes Push no Windows Phone 8

A App deve se autenticar ao servio web;


A App deve criptografar a sua URI de notificao antes de
enviar ao servio web;
Se o usurio desligar o recebimento das notificaes dentro da
App, esta deve fechar o canal atravs do mtodo Close;
O envio das notificaes Push

pode ser feito de modo autenticado ou no. No modo no autenticado, o nmero e frequncia das
notificaes enviadas ao MPNS so controlados, no caso, o limite
atual de 500 por canal (telefone), por dia. Para utilizar o modo
autenticado, o qual no apresenta restries, o desenvolvedor
primeiro precisa registrar um certificado com o servio de notificaes Push atravs da loja do Windows Phone. O certificado
precisa ser expedido por uma unidade certificadora confivel
por parte da Microsoft, e ento esse certificado usado para
estabelecer uma conexo segura atravs de SSL entre o servio
web e o servio de notificaes push.
Aps a explicao sobre o que e como funciona o envio de
notificaes push, iremos falar dos trs tipos de notificaes, que
so Tile, Toast e Raw.

Figura 3. Imagem demonstrando o funcionamento para um Tile no padro Flip para


Windows Phone 7.8 e 8 - Fonte: MSDN

Tile Notification
Como o prprio nome diz, a notificao para Tile deve ser utilizada para atualizar o contedo de um Tile, seja ele o principal
ou no. Caso seja o principal, no existe a possibilidade de trocar
seu template para o outro sem submeter outra verso da App, j
para o secundrio possvel cri-lo e alter-lo em tempo de execuo. Esse tipo de notificao funciona mesmo quando a App
no est aberta.
O Windows Phone 7.8 (atravs de reflection, documentao disponibilizada na seo Links) e Windows Phone 8 suportam trs
tipos de templates para Tiles: Flip, Iconic e Cycle. A escolha do
template ir depender da finalidade da App, j que cada um tem
uma caracterstica prpria. Os Tiles tm os tamanhos descritos
na Tabela 2. No caso de telas WVGA, para os tamanhos 720p e
1080p (a partir do Update 3 do Windows Phone 8) as imagens so
automaticamente ajustadas.
Flip e Cycle

Iconic

Pequeno

159 159 pixels

110 110 pixels

Mdio

336 336 pixels

202 202 pixels

Largo

691 336 pixels

N/A

Tabela 2. Tamanho dos Tiles para telas no tamanho WXGA


O Flip template nico tipo de notificao para Tiles anterior
ao Windows Phone 7.8, que prov duas superfcies no tamanho
mdio e largo, na qual possvel inserir uma quantidade de texto
considervel, conforme Figura 3.
O padro Iconic exibe uma imagem no centro do Tile, juntamente
com um nmero, que opcional, conforme Figura 4. Esse tipo de
padro recomendado se deseja exibir um contador.

6 .Net Magazine Edio 110

Figura 4. Imagem demonstrando o funcionamento para um Tile no padro Iconic - Fonte: MSDN
O padro Cycle exibe uma serie de at nove imagens em sequncia, conforme Figura 5. O uso desse template recomendado
para exibio de imagens.

Toast Notification
A notificao por Toast exibe uma mensagem por cerca de dez
segundos. Se o usurio clicar sobre o Toast, a App ser aberta na
pgina inicial ou, caso seja definido no parmetro Param do
Toast, a pgina especificada.
Em telefones com Windows Phone 8 sem o Update 3, as notificaes Toast no so exibidas se a App estiver em execuo em
primeiro plano, j nos aparelhos com essa atualizao os Toasts
so exibidos, mas ficam obscuros por outra atividade como uma
chamada telefnica ou a tela de bloqueio. Outra funcionalidade
que tambm ser possvel com a atualizao customizar o som
da notificao quando o Toast for exibido.
Em um Toast, exibida uma verso miniatuarizada do cone da
App, um ttulo e uma mensagem, conforme Figura 6. No caso do
ttulo e da mensagem, ambos so truncados, caso o tamanho do
texto seja maior que o espao disponvel para exibio.

Raw Notification
Esse tipo de notificao no oferece nenhuma interao direta
com o usurio, ele utilizado principalmente para recebimento

de dados quando a App est aberta, j que quando encerrada, o


canal de comunicao com cliente Push finalizado. A utilizao
de uma notificao Push, ao invs fazer a App consumir servios
ou APIs, faz com que o uso de recursos do telefone, principalmente
a bateria, seja minimizado. Adiante no artigo veremos na prtica
como o esse tipo de notificao bastante til.

O projeto
A fim de exemplificar como funcionam os tipos de notificao
j explicados, criaremos um projeto Web que far as requisies
ao MPNS enviando um XML de acordo com o template de cada
tipo de notificao especificado pela Microsoft. Nesse caso, o
projeto tem o objetivo de mostrar como funciona a comunicao
entre o servidor Web e o MPNS, e entre o Windows Phone e o
cliente Push. Portanto, em um ambiente real teramos outra comunicao, entre o servidor Web e Windows Phone, para que os
telefones pudessem enviar os canais de Push ao servidor atravs
de um servio ou API.

Windows Phone 8
Para os projetos, estaremos utilizando o Visual Studio 2012.
Dessa forma, abriremos esse IDE em modo administrador e criaremos o primeiro projeto, Windows Phone 8.
Aproveitando a prpria pgina MainPage.xaml que criada
por padro na soluo, alteraremos o grid LayoutRoot conforme
a Listagem 3. No caso, criaremos um elemento do tipo LongListSelector, que ir listar os lances do jogo de futebol e um TextBlock
que dever informar quais so os times que esto se enfrentando.
Tambm ser necessrio adicionar algumas imagens que sero
utilizadas no Tile do tipo Cycle, o qual no permite o uso de
imagens externas ao telefone, conforme a Figura 7.
Listagem 3. Contedo do grid que mostrar as informaes ao usurio

Figura 5. Imagem demonstrando o funcionamento para um Tile no padro Cycle - Fonte: MSDN

Figura 6. Imagem demonstrando como a notificao Toast exibida - Fonte: MSDN

01 <!--LayoutRoot is the root grid where all page content is placed-->


02 <Grid x:Name=LayoutRoot Background=Transparent>
03 <Grid.RowDefinitions>
04
<RowDefinition Height=Auto/>
05
<RowDefinition Height=*/>
06 </Grid.RowDefinitions>
07
08 <!--TitlePanel contains the name of the application and page title-->
09 <StackPanel x:Name=TitlePanel Grid.Row=0 Margin=12,17,0,28>
10
<TextBlock Text=EXEMPLO PUSH
11
Style={StaticResource PhoneTextNormalStyle} Margin=12,0/>
12
<TextBlock Text={Binding TituloJogo} Margin=9,-7,0,0
13
Style={StaticResource PhoneTextTitle1Style}/>
14 </StackPanel>
15
16 <!--ContentPanel - place additional content here-->
17 <Grid x:Name=ContentPanel Grid.Row=1 Margin=12,0,12,0>
18
<ScrollViewer>
19
<StackPanel Orientation=Vertical>
20
<TextBlock Text=Informaes do jogo Margin=0,0,0,10
21
Style={StaticResource PhoneTextSubtleStyle}/>
22
<phone:LongListSelector Grid.Row=1
23
ItemsSource={Binding InformacoesJogo} LayoutMode=List/>
24
</StackPanel>
25
</ScrollViewer>
26 </Grid>
27 </Grid>

Aps definido o layout da tela e seus elementos, implementaremos a lgica para abertura do canal de comunicao das
notificaes push e o mecanismo de exibio das informaes
recebidas nas notificaes para a tela do usurio, como tambm
as configuraes dos Tiles. Para isso, criaremos uma varivel na

Edio 110 .Net Magazine

Notificaes Push no Windows Phone 8

classe que conter no nome do canal a ser utilizado pela App,


a do endereo da URI do nosso projeto Web que criaremos em
seguida e um objeto do tipo HttpNotificationChannel, que concentrar todas as informaes das notificaes do App, conforme
a Listagem 4.
Listagem 4. Vriaveis globais da classe
01 // Nome do canal push do App
02 private readonly string channelName = WP8PushChannel;
03
04 //Uri do Projeto WebServer
05 private readonly string uriBaseImagesTile = http://169.254.80.80:2704;
06
07 // Objeto que contem as informaes do canal Push.
08 HttpNotificationChannel pushChannel;

Figura 7. Adicione imagens configurando para serem copiadas quando compilar o projeto

8 .Net Magazine Edio 110

Depois disso, adicionamos os bindings das propriedades InformacoesJogo e TituloJogo, que atualizaro os elementos da pgina
da App, conforme a Listagem 5.
Listagem 5. Propriedades, mtodo e evento utilizado no binding
01 private string _tituloJogo;
02 public string TituloJogo
03 {
04 get
05 {
06
return _tituloJogo;
07 }
08 set
09 {
10
if (value != _tituloJogo)
11
{
12
_tituloJogo = value;
13
NotifyPropertyChanged(TituloJogo);
14
}
15 }
16 }
17
18 private ObservableCollection<string> _informacoesJogo;
19 public ObservableCollection<string> InformacoesJogo
20 {
21 get
22 {
23
if (_informacoesJogo == null)
24
_informacoesJogo = new ObservableCollection<string>();
25
26
return _informacoesJogo;
27 }
28 set
29 {
30
if (value != _informacoesJogo)
31
{
32
_informacoesJogo = value;
33
NotifyPropertyChanged(InformacoesJogo);
34
}
35 }
36 }
37 // Evento para notificao de atualizao dos elementos da
38 // pagina que esto atrelados s propriedades
39 public event PropertyChangedEventHandler PropertyChanged;
40 private void NotifyPropertyChanged(String propertyName)
41 {
42 PropertyChangedEventHandler handler = PropertyChanged;
43 if (null != handler)
44 {
45
handler(this, new PropertyChangedEventArgs(propertyName));
46 }
47 }

Pelo fato da App ser um exemplo para todos os tipos de notificao hoje existentes, ao abrir a App pela primeira vez esta ir criar
trs Tiles secundrios, um de cada tipo, que sero atualizados
pelas notificaes. Para isso, adicionamos no evento de abertura
da pgina, OnNavigatedTo, a criao de todos eles. Tambm nesse
evento onde atualizamos os times que esto se enfrentando.
Quando esses times forem enviados por um parmetro na URL,
esse parmetro ser utilizado nas notificaes Tile e Toast, assim,
quando o usurio clicar sobre Tile ou Toast, ele ser redirecionado
para essa pgina com os seus devidos parmetros, conforme a
Listagem 6.

Listagem 6. Rotina executada na abertura da pgina


01 protected override void OnNavigatedTo(NavigationEventArgs e)
02 {
03 if (NavigationContext.QueryString.Keys.Contains(TituloJogo))
04 {
05
this.TituloJogo = NavigationContext.QueryString[TituloJogo];
06
07
if (NavigationService.CanGoBack)
08
NavigationService.RemoveBackEntry();
09 }
10
11 //Cria todos os Tiles secundarios que sero usados: Flip, Iconic e Cycle
12 CriarTilesSecundarios();
13
14 base.OnNavigatedTo(e);
15 }
16 private void CriarTilesSecundarios()
17 {
18 var tile = ShellTile.ActiveTiles.Where
(t => t.NavigationUri.OriginalString.Contains
(Tile=iconic)).FirstOrDefault();
19
20 if (tile == null)
21 {
22
IconicTileData iconicTile = new IconicTileData();
23
iconicTile.Title = Iconic;
24
ShellTile.Create(new Uri(/MainPage.xaml?TituloJogo=BRA x ESP&Tile=iconic,
25
UriKind.Relative), iconicTile, true);
26
27
return;

Alm das criaes dos Tiles, se executarem o projeto em modo Debug, na aba
output do Visual Studio deve ser exibida a
URI do canal criado com o servio de Push,
o que ilustrado na Figura 8. Essa URI ser
utilizada na requisio das notificaes.
Por fim, criaremos os mtodos que iro
se registrar junto ao cliente Push do telefone todas as notificaes para a App.
Alguns passos so comuns para todos os
tipos de notificao, como a verificao
da existncia do canal antes de abri-lo, o
registro no evento ChannelUriUpdated,
que ir informar quando houver alterao
no endereo do canal. Nesse momento, em
um cenrio real, precisaramos enviar essa
nova URI ao servio Web. Outro evento
comum o ErrorOccurred, que deve informar a ocorrncia de algum dos erros
da Tabela 1.
Iniciando pela notificao do tipo Tile,
podemos dizer que essa notificao funciona mesmo quando a App no est em
execuo, e pode ser usado para baixar
recursos, como imagens externas ao
telefone. Para isso, precisamos informar
todas as URIs absolutas confiveis no

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 }

}
tile = ShellTile.ActiveTiles.Where
(t => t.NavigationUri.OriginalString.Contains(Tile=flip)).FirstOrDefault();
if (tile == null)
{
FlipTileData flipTile = new FlipTileData();
flipTile.Title = Flip;
ShellTile.Create(new Uri(/MainPage.xaml?TituloJogo=BRA x ESP&Tile=flip,
UriKind.Relative), flipTile, true);
return;
}
tile = ShellTile.ActiveTiles.Where
(t => t.NavigationUri.OriginalString.Contains(Tile=cycle))
.FirstOrDefault();
if (tile == null)
{
CycleTileData cycleTile = new CycleTileData();
cycleTile.Title = Cycle;
ShellTile.Create(new Uri(/MainPage.xaml?TituloJogo=BRA x ESP&Tile=cycle,
UriKind.Relative), cycleTile, true);
return;
}

Figura 8. URI a ser utilizada nas requisies das notificaes


momento do binding do canal, BindToShellTile, atravs do parmetro do tipo
Collection<Uri>, caso contrrio, se for
utilizada a sobrescrita do tipo void, a
notificao acessar somente recursos locais da App, de acordo com a Listagem 7.
Apesar disso, existe uma exceo para
a notificao de Tiles do tipo Cycle que
no permite o uso de recursos externos,
nesse caso, para utilizar recursos externos preciso utilizar um Background
Agent para baixar qualquer recurso de
um servidor, e assim salvar localmente
para depois ser utilizado no momento
do Push.

A notificao do tipo Toast tambm funciona com a App fechada, a diferena que
ao receber a notificao, pode existir uma
interao direta com o usurio temporariamente. Caso o mesmo clique sobre a rea
do Toast, a App ir se abrir em uma URI
determinada no XML da notificao, caso
contrrio, a notificao desaparece aps
alguns segundos. Essa situao ocorrer
quando a App no estiver em execuo
em primeiro plano, seno, ser preciso
registrar-se no evento ShellToastNotificationReceived para que a App possa
identificar que uma notificao Toast foi
recebida. Nesse caso, a deciso sobre o que

Edio 110 .Net Magazine

Notificaes Push no Windows Phone 8

fazer fica a cargo do desenvolvedor. No exemplo da Listagem 8


apenas ser exibida uma mensagem com os parmetros recebidos
na notificao.
Alem disso, para registrar no canal a utilizao do Toast, necessrio efetuar o bind atravs do mtodo BindToShellToast.
Alm do tipo de notificao Tile e Toast, tambm possvel utilizar no Windows Phone a notificao do tipo Raw, que se diferencia
das demais pelo fato do canal de comunicao para o recebimento
das notificaes permanecerem operacional apenas enquanto a
App est em primeiro plano. Alm disso, para o recebimento das
notificaes preciso registrar-se no evento HttpNotificationReceived, conforme a Listagem 9. Os XMLs enviados atravs das

requisies no requerem um modelo especificado pela Microsoft


e podem ser utilizados pelos desenvolvedores livremente, nesse
caso, o XML trafegado contm apenas dois elementos que sero
utilizados, mostrados no projeto Web.

Projeto Web
O projeto Web consiste em demonstrar parte da funcionalidade
que um servio web faria em um ambiente real para enviar as
notificaes ao MPNS. Desse modo, montaremos uma pgina
que servir para parametrizar o XML a ser enviado na requisio
ao MPNS. Neste exemplo, esse projeto est configurado para ser
executado no IIS Express, na porta 2704, conforme Figura 9.

Listagem 7. Inicializao para as notificaes do tipo Tile


01 // Construtor
02 public MainPage()
03 {
04 InitializeComponent();
05
06 DataContext = this;
07
08 Loaded += MainPage_Loaded;
09 }
10 void MainPage_Loaded(object sender, RoutedEventArgs e)
11 {
12 InicializarRaw();
13
14 InicializarTile();
15
16 InicializarToast();
17 }
18 private void InicializarTile()
19 {
20 // Tenta encontrar o canal
21 pushChannel = HttpNotificationChannel.Find(channelName);
22
23 // Se no encontrado tenta criar uma nova conexo com o cliente Push.
24 if (pushChannel == null)
25 {
26
pushChannel = new HttpNotificationChannel(channelName);
27
28
// Registra em todos o eventos antes de abrir o canal
29
pushChannel.ChannelUriUpdated +=
new EventHandler<NotificationChannelUriEventArgs>
(PushChannel_ChannelUriUpdated);
30
pushChannel.ErrorOccurred +=
new EventHandler<NotificationChannelErrorEventArgs>
(PushChannel_ErrorOccurred);
31
32
pushChannel.Open();
33
34
// Adiciona o endereo do nosso Web Server como confivel
35
Collection<Uri> remoteUris = new Collection<Uri>();
36
remoteUris.Add(new Uri(uriBaseImagesTile));
37
38
// Fixa ao canal os eventos de tile.
39
pushChannel.BindToShellTile(remoteUris);
40 }
41 else
42 {
43
// Fixa ao canal os eventos de tile.
44
if (!pushChannel.IsShellTileBound)
45
{
46
// Adiciona o endereo do nosso Web Server como confivel

10 .Net Magazine Edio 110

47
48
49
50
51
52
53
54
55

56

57
58
59
60

Collection<Uri> remoteUris = new Collection<Uri>();


remoteUris.Add(new Uri(uriBaseImagesTile));
// Fixa ao canal os eventos de tile.
pushChannel.BindToShellTile(remoteUris);
}
//Se o canal j existir, apenas se registra aos eventos
pushChannel.ChannelUriUpdated +=
new EventHandler<NotificationChannelUriEventArgs>
(PushChannel_ChannelUriUpdated);
pushChannel.ErrorOccurred +=
new EventHandler<NotificationChannelErrorEventArgs>
(PushChannel_ErrorOccurred);
if (pushChannel.ChannelUri != null)
{
// Exibe a nova URI, apenas para exemplo. Em um ambiente real,
// a nova URI dever ser enviada ao servidor Web.
System.Diagnostics.Debug.WriteLine(pushChannel.ChannelUri.ToString());
MessageBox.Show(String.Format(Channel Uri is {0},
pushChannel.ChannelUri.ToString()));
}

61
62
63
64
65 }
66 }
67 void PushChannel_ErrorOccurred(object sender, NotificationChannelError
EventArgs e)
68 {
69 // Passivel para tratamento de erro por parte da aplicao.
70 Dispatcher.BeginInvoke(() =>
71
MessageBox.Show(String.Format(Um erro de notificao
{0} ocorreu. {1} ({2}) {3},
72
e.ErrorType, e.Message, e.ErrorCode, e.ErrorAdditionalData))
73
);
74 }
75
76 void PushChannel_ChannelUriUpdated(object sender, NotificationChannelUri
EventArgs e)
77 {
78 Dispatcher.BeginInvoke(() =>
79 {
80
// Exibe a nova URI, apenas para exemplo. Em um ambiente real,
// a nova URI dever ser enviada ao servidor Web.
81
System.Diagnostics.Debug.WriteLine(e.ChannelUri.ToString());
82
MessageBox.Show(String.Format(A nova Uri {0},
83
e.ChannelUri.ToString()));
84
85 });
86 }

Listagem 8. Inicializao para as notificaes do tipo Toast


01 private void InicializarToast()
02 {
03 // Tenta encontrar o canal
04 pushChannel = HttpNotificationChannel.Find(channelName);
05
06 // Se no encontrado tenta criar uma nova conexo com o cliente Push.
07 if (pushChannel == null)
08 {
09
pushChannel = new HttpNotificationChannel(channelName);
10
11
// Registra em todos o eventos antes de abrir o canal
12
pushChannel.ChannelUriUpdated +=
new EventHandler<NotificationChannelUriEventArgs>
(PushChannel_ChannelUriUpdated);
13
pushChannel.ErrorOccurred +=
new EventHandler<NotificationChannelErrorEventArgs>
(PushChannel_ErrorOccurred);
14
15
// Registra esse evento, caso seja necessrio receber
// uma notificao Toast enquanto o App estiver aberto.
16
pushChannel.ShellToastNotificationReceived +=
new EventHandler<NotificationEventArgs>
(PushChannel_ShellToastNotificationReceived);
17
18
pushChannel.Open();
19
20
// Fixa ao canal os eventos toast.
21
pushChannel.BindToShellToast();
22
23 }
24 else
25 {
26
// Fixa ao canal os eventos toast.
27
if(!pushChannel.IsShellToastBound)
28
pushChannel.BindToShellToast();
29
30
//Se o canal j existir, apenas se registra aos eventos
31
pushChannel.ChannelUriUpdated +=
new EventHandler<NotificationChannelUriEventArgs>
(PushChannel_ChannelUriUpdated);
32
pushChannel.ErrorOccurred +=
new EventHandler<NotificationChannelErrorEventArgs>
(PushChannel_ErrorOccurred);
33
34
// Registra esse evento, caso seja necessrio receber
// uma notificao Toast enquanto o App estiver aberto.
35
pushChannel.ShellToastNotificationReceived +=
new EventHandler<NotificationEventArgs>

Sendo assim, temos que liberar o acesso do emulador do Windows Phone, o qual roda em um ambiente virtualizado, atravs
da execuo da linha de comando exibida na Figura 10. Apenas
substitua pela porta especificada no projeto, caso seja diferente,
em um prompt de comando (cmd.exe) em modo administrador
para liberar o acesso atravs do firewall do Windows Vista, 7 e 8.
Caso voc tenha outro programa de firewall, provavelmente
precisar liberar acesso a essa porta tambm.
Ento, por ltimo, temos que configurar o acesso ao site do IIS
Express ao endereo IP em que o emulador do Windows Phone
est trabalhando. Para isso, podemos utilizar esse mesmo prompt
de comando e executar ipconfig, e assim localizar o endereo
IP do adaptador cujo nome aparece Windows Phone Emulator
Internal Switch, como se v na Figura 11.

(PushChannel_ShellToastNotificationReceived);
36
37
38
39

if (pushChannel.ChannelUri != null)
{
// Exibe a nova URI, apenas para exemplo. Em um ambiente real,
// a nova URI dever ser enviada ao servidor Web.
System.Diagnostics.Debug.WriteLine(pushChannel.ChannelUri.ToString());
MessageBox.Show(String.Format(A Uri do canal {0},
pushChannel.ChannelUri.ToString()));
}

40
41
42
43
44
45 }
46
47 }
48
49 private void PushChannel_ShellToastNotificationReceived
(object sender, NotificationEventArgs e)
50 {
51 StringBuilder message = new StringBuilder();
52 string relativeUri = string.Empty;
53
54 // Criao de mensagem apenas para demontrar o recebimento
// do toast enquanto o App est aberto
55 message.AppendFormat(Toast recebido {0}:\n, DateTime.Now.ToShortTime
String());
56
57 // Recupera todas as informaes que esto na mensagem.
58 foreach (string key in e.Collection.Keys)
59 {
60
message.AppendFormat({0}: {1}\n, key, e.Collection[key]);
61
62
if (string.Compare(
63
key,
64
wp:Param,
65
System.Globalization.CultureInfo.InvariantCulture,
66
System.Globalization.CompareOptions.IgnoreCase) == 0)
67
{
68
relativeUri = e.Collection[key];
69
}
70 }
71
72 // Exibe todos os campos da mensagem do toast
73 Dispatcher.BeginInvoke(() => MessageBox.Show(message.ToString()));
74
75 //Navega para a pgina recebida no toast
76 Dispatcher.BeginInvoke(() => NavigationService.Navigate
(new Uri(e.Collection[wp:Param], UriKind.Relative)));
77 }

Depois de recuperar o IP, iremos utiliz-lo para adicionar o


acesso atravs do arquivo de configurao do IIS Express, localizado na pasta IISExpress dentro da pasta Meus Documentos,
que pode ser facilmente acessada pelo caminho: %userprofile%\
documents\IISExpress\config\applicationhost.config.
Abrindo o arquivo, temos que localizar o site configurado no nosso
projeto, que dever ser compilado e executado pelo menos uma vez
para que o Visual Studio possa cri-lo dentro do arquivo applicationhost.config. Assim, devemos copiar a linha j existente, colar
e editar, conforme a linha selecionada na Figura 12, onde 2704
representa a porta em que o IISExpress ir executar e 169.254.80.80
o IP referente ao emulador do Windows Phone 8.
Agora que temos o projeto devidamente configurado para funcionar junto com o Windows Phone, criaremos uma nica pagina

Edio 110 .Net Magazine

11

Notificaes Push no Windows Phone 8

ASPX que servir como entrada para parametrizar e enviar o XML


ao MPNS. Assim, criaremos a pgina EnviarPush.aspx, responsvel por enviar informaes e fotos de um jogo de futebol.
Partindo do design da pgina, criaremos apenas elementos bsicos, sem se preocupar com estilo e apresentao, com objetivo

Figura 10. Linha de comando para adicionar uma exceo ao firewall do Windows

Figura 9. Imagem com a configurao do projeto Web Forms

Figura 11. Recuperando o endereo IP do emulador do Windows Phone 8

Listagem 9. Inicializao para as notificaes do tipo Raw


01 private void InicializarRaw()
02 {
03 // Tenta encontrar o canal
04 pushChannel = HttpNotificationChannel.Find(channelName);
05
06 // Se no encontrado tenta criar uma nova conexo com o cliente Push.
07 if (pushChannel == null)
08 {
09
pushChannel = new HttpNotificationChannel(channelName);
10
11
// Registra em todos o eventos antes de abrir o canal
12
pushChannel.ChannelUriUpdated +=
new EventHandler<NotificationChannelUriEventArgs>
(PushChannel_ChannelUriUpdated);
13
pushChannel.ErrorOccurred +=
new EventHandler<NotificationChannelErrorEventArgs>
(PushChannel_ErrorOccurred);
14
pushChannel.HttpNotificationReceived +=
new EventHandler<HttpNotificationEventArgs>
(PushChannel_HttpNotificationReceived);
15
16
pushChannel.Open();
17 }
18 else
19 {
20
//Se o canal j existir, apenas se registra aos eventos
21
pushChannel.ChannelUriUpdated +=
new EventHandler<NotificationChannelUriEventArgs>
(PushChannel_ChannelUriUpdated);
22
pushChannel.ErrorOccurred +=
new EventHandler<NotificationChannelErrorEventArgs>
(PushChannel_ErrorOccurred);
23
pushChannel.HttpNotificationReceived +=
new EventHandler<HttpNotificationEventArgs>
(PushChannel_HttpNotificationReceived);
24
25
if (pushChannel.ChannelUri != null)
26
{

12 .Net Magazine Edio 110

27

// Exibe a nova URI, apenas para exemplo. Em um ambiente


// real, a nova URI dever ser enviada ao servidor Web.
System.Diagnostics.Debug.WriteLine(pushChannel.ChannelUri.ToString());
MessageBox.Show(String.Format(A Uri do canal {0},
pushChannel.ChannelUri.ToString()));
}

28
29
30
31
32 }
33 }
34
35 private void PushChannel_HttpNotificationReceived
(object sender, HttpNotificationEventArgs e)
36 {
37 string message;
38
39 //L o conteudo do corpo da notificao
40 using (System.IO.StreamReader reader = new System.IO.StreamReader
(e.Notification.Body))
41 {
42
message = reader.ReadToEnd();
43 }
44
45 // Uso de Linq to XML para recuperar o valor dos elementos do XML
46 XDocument doc = XDocument.Parse(message);
47 Dispatcher.BeginInvoke(() =>
48
{
49
TituloJogo = doc.Descendants().Where
(n => n.Name == TituloJogo).First().Value;
50
InformacoesJogo.Add(doc.Descendants().Where
(n => n.Name == InformacaoJogo).First().Value);
51
});
52
53 //Exibe uma mensagem, apenas para mostrar o contedo recebido
54 Dispatcher.BeginInvoke(() =>
55
MessageBox.Show(String.Format(Received Notification {0}:\n{1},
56
DateTime.Now.ToShortTimeString(), message))
57
);
58 }

apenas de mostrar como funciona o envio


de notificaes push. Desse modo, na
Listagem 10 criamos um primeiro menu
que ter a diviso entre os tipos Toast, Tile
e Raw de notificao, e um segundo menu
interno ao menu de Tile com os trs tipos
de notificao para Tile que existem para
o Windows Phone 8, que so: Flip, Iconic e
Cycle. Na Listagem 10 est sendo exibido
apenas o contedo do corpo da pgina, ou
seja, que se encontra dentro da tag body.
Aps o design da pgina, implementaremos a lgica para seu o funcionamento,
nesse caso, entre os eventos d pagina
utilizaremos o clique do boto Enviar
Notificao e o clique sobre os menus
de troca do tipo de Tile e notificao, de
acordo com a Listagem 11. A partir desse
momento conseguimos testar se o emulador do Windows Phone est conseguindo
acessar o nosso projeto Web, e assim
garantir que quando as notificaes para
Tile forem enviadas, o mesmo conseguir
FairCom121212BRhalffinal.pdf
1
1/3/13
baixar as imagens para exibio, como

Figura 12. Editando o arquivo de configurao do IISExpress para permitir o acesso do emulador ao site do projeto
demonstrado na Figura 13. Caso no tenha
sucesso no teste, verifique as configuraes explicadas anteriormente.
Para o envio das notificaes, chamaremos
um mtodo a partir do clique do boto. Para
cada tipo de notificao existe um modelo de
XML diferente a ser seguido, apesar disso,
2:16 PM
todos partem do mesmo princpio. Nesse

caso, preciso utilizar uma URI do canal


Push, enviar apenas requisies do tipo
POST, complementar o modelo do XML
respeitando o uso de caracteres especiais
conforme a Tabela 3, adicionar ao cabealho da requisio o tipo da notificao e a
prioridade para entrega e, por fim, enviar a
requisio e recuperar do status do envio.

Estas solues so monitoradas pela


tecnologia FairCom todos os dias!

tecnologia de banco de dados


v>VVUnn

2013 FairCom Corporation

Notificaes Push no Windows Phone 8

Listagem 10. Design da pgina que enviar as notificaes


01 <form id=form1 runat=server>

46

<asp:TextBox ID=TextBoxBackBackgroundImage

03 <asp:TextBox ID=TextBoxUri runat=server Width=50%></asp:TextBox><br />

47

Back Content:<br />

04

Tipo:

48

<asp:TextBox ID=TextBoxBackContent runat=server>

05

<asp:Menu ID=TipoPush Width=100% runat=server Orientation=Horizontal

02 URI Canal:<br />

06

runat=server></asp:TextBox><br />

</asp:TextBox><br />

StaticEnableDefaultPopOutImage=False OnMenuItemClick=

49

</asp:View>

TipoPush_MenuItemClick>

50

<asp:View ID=View2 runat=server>

07

<Items>

51

<br />

08

<asp:MenuItem Text=Toast Value=0 Selected=true></asp:MenuItem>

52

Iconic<br />

09

<asp:MenuItem Text=Tile Value=1></asp:MenuItem>

53

Title:<br />

10

<asp:MenuItem Text=Raw Value=2></asp:MenuItem>

54

<asp:TextBox ID=TextBoxIconicTitle runat=server>

11

</Items>

12

</asp:Menu>

55

Icon Image:<br />

13

<div style=border: 1px solid black; width: 75%; padding: 10px>

56

<asp:TextBox ID=TextBoxIconImage runat=server>

57

Content1:<br />

58

<asp:TextBox ID=TextBoxContent1 runat=server>

Width=50%></asp:TextBox><br />

59

Content2:<br />

Subtitle:<br />

60

<asp:TextBox ID=TextBoxContent2 runat=server>

Width=50%></asp:TextBox><br />

61

Content3:<br />

Titulo Jogo:<br />

62

<asp:TextBox ID=TextBoxContent3 runat=server>

63

Count:<br />

64

<asp:TextBox ID=TextBoxIconicCount runat=server

65

Background Color:<br />

66

<asp:TextBox ID=TextBoxBackgroundColor runat=server>

14
15
16
17
18
19
20

</asp:TextBox><br />

<asp:MultiView ID=MultiViewPush runat=server ActiveViewIndex=0>


<asp:View ID=Tab1 runat=server>
Title:<br />

</asp:TextBox><br />

<asp:TextBox ID=TextBoxTitle runat=server

</asp:TextBox><br />

<asp:TextBox ID=TextBoxSubTitle runat=server

</asp:TextBox><br />

21
<asp:TextBox ID=TextBoxTituloJogo runat=server
Width=50%></asp:TextBox><br />
22

</asp:View>

23

<asp:View ID=Tab2 runat=server>

24

<asp:Menu ID=TipoTile Width=100% runat=server

</asp:TextBox><br />

MaxLength=2></asp:TextBox><br />

Orientation=Horizontal
25
26

</asp:TextBox><br />

StaticEnableDefaultPopOutImage=False

67

</asp:View>

OnMenuItemClick=TipoTile_MenuItemClick>

68

<asp:View ID=View3 runat=server>

<Items>

69

Cycle<br />

27

<asp:MenuItem Text=Flip Value=0

70

Title:<br />

Selected=true></asp:MenuItem>

71

<asp:TextBox ID=TextBoxCycleTitle runat=server>

28

<asp:MenuItem Text=Iconic Value=1></asp:MenuItem>

29

<asp:MenuItem Text=Cycle Value=2></asp:MenuItem>

30

</Items>

</asp:TextBox><br />
72
73

Count:<br />
<asp:TextBox ID=TextBoxCycleCount runat=server

31

</asp:Menu>

32

<div style=border: 1px solid black; width: 50%; padding: 10px>

74

</asp:View>

33

<asp:MultiView ID=MultiViewTile runat=server

75

</asp:MultiView>

ActiveViewIndex=0>

76

34

<asp:View ID=View1 runat=server>

77

35

<br />

78

<asp:View ID=Tab3 runat=server>

36

Flip<br />

79

Titulo Jogo:<br />

37

Front Title:<br />

80

<asp:TextBox ID=TextBoxTituloJogoRaw runat=server

38

<asp:TextBox ID=TextBoxFrontTitle runat=server>


</asp:TextBox><br />

39

Front Background Image:<br />

40

<asp:TextBox ID=TextBoxBackgroundImage runat=server>


</asp:TextBox><br />

MaxLength=2></asp:TextBox><br />

Width=50%></asp:TextBox><br />
81
82

Front Count:<br />

84

42

<asp:TextBox ID=TextBoxCount runat=server

85

43

Back Title:<br />

44

<asp:TextBox ID=TextBoxBackTitle runat=server>


</asp:TextBox><br />

45

Back Background Image:<br />

14 .Net Magazine Edio 110

Informao Jogo:<br />


<asp:TextBox Rows=5 ID=TextBoxInformacaoJogo runat=server
TextMode=MultiLine Width=50%></asp:TextBox><br />

83

41

MaxLength=2></asp:TextBox><br />

</div>
</asp:View>

86

</asp:View>
</asp:MultiView>
</div>
<asp:Button ID=ButtonSend runat=server OnClick=ButtonSend_Click
Text=Enviar Notificacao /><br />

87
88

Resposta:<br />
<asp:Label ID=LabelRespostaMPNS runat=server Width=50%></asp:Label>

89 </form>

Listagem 11. Mtodos acionados atraves dos eventos


01 //Uri do Projeto WebServer
02 protected readonly string uriBaseImagesTile = http://169.254.80.80:2704;
03
04 protected void TipoPush_MenuItemClick(object sender, MenuEventArgs e)
05 {
06 //Troca o menu de Push ativo
07 MultiViewPush.ActiveViewIndex = Int32.Parse(e.Item.Value);
08 }
09
10 protected void TipoTile_MenuItemClick(object sender, MenuEventArgs e)
11 {
12 //Troca o menu de Push de Tile ativo
13 MultiViewTile.ActiveViewIndex = Int32.Parse(e.Item.Value);
14 }
15
16 protected void ButtonSend_Click(object sender, EventArgs e)

Caracter

Codificao XML

<

&lt;

>

&gt;

&

&amp;

&apos;

&quot;

Tabela 3. Caracteres que devem ser tratados quando inseridos dentro


das tags do XML da notificao.

17 {
18
19
20
21
22
23
24
25
26
27
28
29
30
31 }

//Faz o envio da Notificao de acordo com o menu selecionado


switch (Convert.ToInt16(TipoPush.SelectedItem.Value))
{
case 0:
EnviarToast();
break;
case 1:
EnviarTile();
break;
case 2:
EnviarRaw();
break;
}

estado Connected pode ser entendido que o telefone tem uma


conexo ativa com o servidor de notificao Push e pode receber
notificaes em tempo real.
O estado Temp Disconnected um estado temporrio onde a
conexo com o servidor de notificao Push foi perdida e ser
tentado restabelecer a comunicao assim que o telefone tiver
uma conexo vlida com a Internet. Nesse estado, o aparelho pode
permanecer por 24 horas e todas as notificaes so enfileiradas

Figura 13. O emulador conseguiu abrir a pgina que criamos no projeto Web, a comunicao
no momento do Push ter sucesso
A partir do status da resposta do envio da requisio possvel
identificar alguns cenrios que dizem a respeito da entrega das
notificaes e estado do canal, de acordo com a Tabela 4.
Os estados de conexo com o telefone podem ser definidos
entre Connected, Temp Disconnected e Disconnected, os quais
possuem as transies demonstradas na Figura 14. No caso, pelo

Edio 110 .Net Magazine

15

Notificaes Push no Windows Phone 8

at que a fila no esteja cheia. Algumas razes podem levar o


telefone entrar nesse estado, como: o telefone pode estar em rea
de roaming e por isso a conexo pode ser interrompida; o sinal de
celular onde o usurio est sofre instabilidades; alguns proxys de
acesso Internet podem interromper essa conexo direta; o modo
Cdigo de Resposta

Status da
Notificao

Status da Conexo
com o telefone

Status do
Canal

economia de bateria se encontra ligado e com isso as notificaes


Push so desligadas temporariamente.
J no estado Disconnected o telefone est sem conexo com o
servidor de notificao por mais de 24 horas. Quando o telefone
entra nesse estado, todas as notificaes que foram enfileiradas
Descrio

200 OK

Received

Connected

Active

A requisio da notificao foi aceita e includa na fila para entrega. O MPNS pode responder com esse status mesmo que o telefone esteja alternando para o estado Temp Disconnected. Isso significa que a notificao no ser entregue at que o telefone retorne do
estado Temp Disconnected.

200 OK

Received

Temp Disconnected

Active

A requisio foi aceita e includa na fila para entrega. No entanto, o telefone est temporariamente desconectado.

200 OK

QueueFull

Connected

Active

O MPNS mantem no mximo 30 notificaes de cada canal para entrega. Uma vez que
esse limite atingido, todas as mensagens so descartadas at que o telefone se conecte
e a fila seja esvaziada.

200 OK

QueueFull

Temp Disconnected

Active

O MPNS mantem no mximo 30 notificaes para entrega de cada canal. Uma vez que
esse limite atingido, todas as mensagens so descartadas at que o telefone se conecte
e a fila seja esvaziada.

Active

A notificao foi recebida e foi descartada pelo servio de notificao push. O status de
descartada pode ocorrer se o tipo de notificao no foi ativado pela chamada BindToShellTile ou BindToShellToast pelo App, ou no caso de uma notificao do tipo Raw, a
requisio foi enviada enquanto o App no estava em execuo em primeiro plano, ou se
foi uma notificao do tipo Tile, nenhum Tile est fixado.

200 OK

Suppressed

Connected

200 OK

Suppressed

Temp Disconnected

Active

A notificao foi recebida e foi descartada pelo servio de notificao push. O status de
descartada pode ocorrer se o tipo de notificao no foi ativado pela chamada BindToShellTile ou BindToShellToast pelo App, ou no caso de uma notificao do tipo Raw, a
requisio foi enviada enquanto o App no estava em execuo em primeiro plano, ou se
foi uma notificao do tipo Tile, nenhum Tile est fixado.

400 BadRequest

N/A

N/A

N/A

Esse erro ocorre quando o servio Web enviou uma requisio de notificao com um XML
ou URI que contem erros.

401 Unauthorized

N/A

N/A

N/A

Uma notificao no autorizada se existe alguma divergncia entre o nome da pessoa


no certificado do servio Web com o nome da pessoa no certificado do servio de notificao push, ou mesmo se o token no valido para o canal ou foi modificado.

404 Not Found

Dropped

Connected

Expired

O canal invlido e no est presente no servio de notificao push. O servio Web deve
parar de enviar novas notificaes para esse canal.

404 Not Found

Dropped

Temp Disconnected

Expired

O canal invlido e no est presente no servio de notificao push. O servio Web deve
parar de enviar novas notificaes para esse canal.

404 Not Found

Dropped

Disconnected

Expired

O canal invlido e no est presente no servio de notificao push. O servio Web deve
parar de enviar novas notificaes para esse canal.

405 Method Not


Allowed

N/A

N/A

N/A

Apenas o mtodo POST aceito no envio das requisies das notificaes.

Active

Esse erro pode acontecer quando um servio Web est utilizando o modo sem autenticao de envio de notificao e esse atingiu o limite por dia de envio para determinado
canal. Quando ocorrer esse erro, o servio Web pode tentar enviar uma notificao a cada
hora, no entanto, pode ser necessrio esperar at 24 horas para que o envio de notificaes seja normalizado.

406 Not Acceptable

Dropped

Connected

406 Not Acceptable

Dropped

Temp Disconnected

Active

Esse erro pode acontecer quando um servio Web est utilizando o modo sem autenticao de envio de notificao e esse atingiu o limite por dia de envio para determinado
canal. Quando ocorrer esse erro, o servio Web pode tentar enviar uma notificao a cada
hora, no entanto, pode ser necessrio esperar at 24 horas para que o envio de notificaes seja normalizado.

412 Precondition
Failed

Dropped

Disconnected

N/A

O telefone est em um estado desconectado. O servio Web deve continuar enviando as


notificaes normalmente.

503 Service Unavailable

N/A

N/A

N/A

O servio de notificao Push no foi capaz de processar a requisio, desse modo, a


requisio pode ser reenviada mais tarde.

Tabela 4. Tabela com os cdigos de retorno do MPNS

16 .Net Magazine Edio 110

para esse telefone so descartadas e no sero entregue quando


o mesmo restabelecer a comunicao.
Um dos requisitos para o envio da notificao do tipo Toast
o preenchimento do cabealho da requisio, de acordo com os
cabealhos da Tabela 5. Tambm existe um modelo de XML a ser
seguido, que deve ser devidamente preenchido de acordo com a
necessidade, nesse caso, podemos ver na Listagem 12 que o XML
composto pelos elementos wp:Text1, wp:Text2 e wp:Param, demonstrados na Figura 15, onde o elemento wp:Param corresponde
pgina na qual a App ser aberta, caso o usurio clique sobre
o Toast. Caso o contedo desse elemento seja vazio, a App ser

Cabealho da Requisio

Valor

Descrio

X-WindowsPhone-Target

toast

Identificao da notificao

Entrega imediata.

12

Entrega dentro de 450 segundos.

22

Entrega dentro de 900 segundos.

X-NotificationClass

Tabela 5. Cabealhos que devem conter no envio da requisio para notificaes do tipo Toast

Figura 14. Transio entre os estados de conexo dos telefones com o servidor de notificao
Push, fonte: MSDN

Figura 15. Visualizao de cada elemento da notificao Toast - Fonte: MSDN

Listagem 12. Rotina que faz o envio da notificao do tipo Toast para o MPNS
01 private void EnviarToast()
02 {
03 try
04 {
05
// URI retornada pelo cliente Push quando criado o canal para notificao
06
string subscriptionUri = TextBoxUri.Text.ToString();
07
08
HttpWebRequest sendNotificationRequest =
(HttpWebRequest)WebRequest.Create(subscriptionUri);
09
10
// HTTP POST o unico method aceito para as nofitificaes
11
sendNotificationRequest.Method = POST;
12
13
// O cabealho X-MessageID opcional e pode ser usado
// para identificar uma mensagem de notificao.
14
// Se estiver presente, o mesmo valor retornado na resposta da requisio.
15
// sendNotificationRequest.Headers.Add(X-MessageID, <UUID>);
16
17
// Criando uma mensagem para a notificao.
18
string toastMessage = <?xml version=\1.0\ encoding=\utf-8\?> +
19
<wp:Notification xmlns:wp=\WPNotification\> +
20
<wp:Toast> +
21
<wp:Text1> + TextBoxTitle.Text + </wp:Text1> +
22
<wp:Text2> + TextBoxSubTitle.Text + </wp:Text2> +
23
<wp:Param>/MainPage.xaml?TituloJogo= +
TextBoxTituloJogo.Text + </wp:Param> +
24
</wp:Toast> +
25
</wp:Notification>;
26
27
// Convertendo para byte[].
28
byte[] notificationMessage = Encoding.UTF8.GetBytes(toastMessage);
29
30
// Apontando o tamanho e tipo do corpo da requisio.

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 }

sendNotificationRequest.ContentLength = notificationMessage.Length;
sendNotificationRequest.ContentType = text/xml;
// A configurao 2 do cabealho X-NotificationClass
// serve para solicitar uma entrega imediata.
sendNotificationRequest.Headers.Add(X-WindowsPhone-Target, toast);
sendNotificationRequest.Headers.Add(X-NotificationClass, 2);
using (Stream requestStream = sendNotificationRequest.GetRequestStream())
{
requestStream.Write(notificationMessage, 0, notificationMessage.Length);
}
// Recuperando a resposta do MPNS.
HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.
GetResponse();
string notificationStatus = response.Headers[X-NotificationStatus];
string notificationChannelStatus = response.Headers[X-SubscriptionStatus];
string deviceConnectionStatus = response.Headers[X-DeviceConnection
Status];
// Exibindo resposta recebida. Recomendado tratamento de erros,
// at porque as notificaes podem no ser enviadas ao telefone
LabelRespostaMPNS.Text = notificationStatus + | +
deviceConnectionStatus + | + notificationChannelStatus;
}
catch (Exception ex)
{
LabelRespostaMPNS.Text = Ocorreu uma exceo ao enviar a requisio:
+ ex.ToString();
}

Edio 110 .Net Magazine

17

Notificaes Push no Windows Phone 8

aberta na pgina inicial padro. Na Figura 16 vemos a aplicao


sendo testada, com a notificao sendo enviada pela pgina web
e recebida pelo telefone.

Figura 17. Visualizao de cada elemento da notificao para Tiles do tipo Flip - Fonte: MSDN

Figura 16. Notificao do tipo Toast recebida


Assim como a notificao do tipo Toast, as notificaes do tipo
Tile tambm apresentam o mesmo requisito, tanto para o preenchimento do modelo do XML, exemplificado na Listagem 13,
como o preenchimento do cabealho da requisio de acordo com
a Tabela 6. Alm dos requisitos, existem outros parmetros do
XML, todos visualmente demonstrados nas Figuras 17, 18 e 19, que
so utilizados nesse tipo de notificao, como o elemento ID, que
deve ser utilizado para indicar o Tile que ser atualizado. Sendo
assim, o valor desse elemento deve conter a URI exata do Tile
que dever ser atualizado, caso esse atributo no seja informado,
o Tile principal da App ser atualizado. Cabe observar que este
deve estar fixado na tela inicial para funcionar.
Outro atributo exclusivo para esse tipo de notificao o atributo/
valor Action=Clear, que quando utilizado ir limpar as informaes contidas no Tile. No caso de deixar um dos elementos a ser
preenchido, como wp:Count para a notificao do tipo Iconic, e no
explicitar o uso do atributo Action=Clear, o nmero exibido no
tile no ser limpo, nem sobrescrito, assim o valor que estiver no
momento da atualizao ir permanecer. Outra observao com relao ao tipo Iconic que o valor para o elemento BackgroundColor
tem que iniciar em #FF, como #FFAB4434, seno ao invs de exibir
essa cor, ser exibida a cor do tema padro do telefone.
Durante a parametrizao do XML, temos que lembrar que para
os tipos Flip e Iconic, as imagens podem ser carregadas do servidor
Web, j para o tipo Cycle, apesar de poder exibir at nove imagens,
permitido apenas a exibio de imagens que esto no gravadas
localmente telefone. Nas Figuras 20, 21 e 22 exibido o exemplo
em execuo, com as novas notificaes recebidas.

18 .Net Magazine Edio 110

Figura 18. Visualizao de cada elemento da notificao para Tiles do tipo Iconic - Fonte: MSDN

Figura 19. Visualizao de cada elemento da notificao para Tiles do tipo Cycle, fonte: MSDN
Cabealho da Requisio

Valor

X-WindowsPhone-Target token
X-NotificationClass

Descrio
Identificao da notificao

Entrega imediata.

11

Entrega dentro de 450 segundos.

21

Entrega dentro de 900 segundos.

Tabela 6. Cabealhos que devem conter no envio da requisio para notificaes do tipo Tile.

Listagem 13. Rotina que faz o envio da notificao do tipo Tile para o MPNS
01 private void EnviarTile()
02 {
03 try
04 {
05
// URI retornada pelo cliente Push quando criado o canal para notificao
06
string subscriptionUri = TextBoxUri.Text.ToString();
07
HttpWebRequest sendNotificationRequest =
(HttpWebRequest)WebRequest.Create(subscriptionUri);
08
// HTTP POST o unico method aceito para as nofitificaes
09
sendNotificationRequest.Method = POST;
10
// O cabealho X-MessageID opcional e pode ser usado
// para identificar uma mensagem de notificao.
11
// Se estiver presente, o mesmo valor retornado na resposta da requisio.
12
// sendNotificationRequest.Headers.Add(X-MessageID, <UUID>);
13
// Criando uma mensagem para a notificao.
14
string tileMessage;
15
switch (Convert.ToInt16(TipoTile.SelectedItem.Value))
16
{
17
// Iconic
18
case 1:
19
tileMessage = <?xml version=\1.0\ encoding=\utf-8\?>
20
+<wp:Notification xmlns:wp=\WPNotification\ Version=\2.0\>
21
+ <wp:Tile Id=\/MainPage.xaml?TituloJogo=BRA x
ESP&amp;Tile=iconic\ Template=\IconicTile\>
22
+ <wp:SmallIconImage + (string.IsNullOrEmpty
(TextBoxIconImage.Text) ? Action=\Clear\ : ) + >
+ uriBaseImagesTile + TextBoxIconImage.Text
+ </wp:SmallIconImage>
23
+ <wp:IconImage + (string.IsNullOrEmpty
(TextBoxIconImage.Text) ? Action=\Clear\ : )
+ > + uriBaseImagesTile + TextBoxIconImage.Text
+ </wp:IconImage>
24
+ <wp:WideContent1 + (string.IsNullOrEmpty
(TextBoxContent1.Text) ? Action=\Clear\ : )
+ > + TextBoxContent1.Text + </wp:WideContent1>
25
+ <wp:WideContent2 + (string.IsNullOrEmpty
(TextBoxContent2.Text) ? Action=\Clear\ : )
+ > + TextBoxContent2.Text + </wp:WideContent2>
26
+ <wp:WideContent3 + (string.IsNullOrEmpty
(TextBoxContent3.Text) ? Action=\Clear\ : )
+ > + TextBoxContent3.Text + </wp:WideContent3>
27
+ <wp:Count + (string.IsNullOrEmpty
(TextBoxIconicCount.Text) ? Action=\Clear\ : )
+ > + TextBoxIconicCount.Text + </wp:Count>
28
+ <wp:Title + (string.IsNullOrEmpty
(TextBoxIconicTitle.Text) ? Action=\Clear\ : )
+ > + TextBoxIconicTitle.Text + </wp:Title>

45
46
47
48

49

50
51
52
53
54
55
56
57
58
59

60

61

62

63

64
65
66

67
29

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

+ <wp:BackgroundColor + (string.IsNullOrEmpty
(TextBoxBackgroundColor.Text) ? Action=\Clear\ : )
+ > + TextBoxBackgroundColor.Text + </wp:BackgroundColor>
+</wp:Tile>
+</wp:Notification>;
break;
// Cycle
case 2:
tileMessage = <?xml version=\1.0\ encoding=\utf-8\?>
+<wp:Notification xmlns:wp=\WPNotification\ Version=\2.0\>
+ <wp:Tile Id=\/MainPage.xaml?TituloJogo=BRA x
ESP&amp;Tile=cycle\ Template=\CycleTile\>
+ <wp:SmallBackgroundImage>
/Images/taca.jpg</wp:SmallBackgroundImage>
+ <wp:CycleImage1>/Images/taca.jpg</wp:CycleImage1>
+ <wp:CycleImage2>/Images/campeao.jpg</wp:CycleImage2>
+ <wp:CycleImage3>/Images/carrinho.jpg</wp:CycleImage3>
+ <wp:CycleImage4>/Images/chute.jpg</wp:CycleImage4>
+ <wp:CycleImage5>/Images/comemoracao.jpg</wp:CycleImage5>
+ <wp:CycleImage6>/Images/comemoracao2.jpg</wp:CycleImage6>

68

69
70
71
72
73
74
75
76
77
78
79
80
81
82

+ <wp:CycleImage7>/Images/comemoracao3.jpg</wp:CycleImage7>
+ <wp:CycleImage8>/Images/expulsao.jpg</wp:CycleImage8>
+ <wp:CycleImage9>/Images/golneymar.jpg</wp:CycleImage9>
+ <wp:Count + (string.IsNullOrEmpty(TextBoxCycleCount.Text)
? Action=\Clear\ : ) + > + TextBoxCycleCount.Text
+ </wp:Count>
+ <wp:Title + (string.IsNullOrEmpty(TextBoxCycleTitle.Text)
? Action=\Clear\ : ) + > + TextBoxCycleTitle.Text
+ </wp:Title>
+</wp:Tile>
+</wp:Notification>;
break;
// Flip
default:
tileMessage = <?xml version=\1.0\ encoding=\utf-8\?>
+<wp:Notification xmlns:wp=\WPNotification\ Version=\2.0\>
+ <wp:Tile Id=\/MainPage.xaml?TituloJogo=BRA x ESP&amp;Tile=flip\
Template=\FlipTile\>
+ <wp:SmallBackgroundImage
+ (string.IsNullOrEmpty(TextBoxBackgroundImage.Text) ?
Action=\Clear\ : ) + > + uriBaseImagesTile
+ TextBoxBackgroundImage.Text + </wp:SmallBackgroundImage>
+ <wp:WideBackgroundImage
+ (string.IsNullOrEmpty(TextBoxBackgroundImage.Text) ?
Action=\Clear\ : ) + > + uriBaseImagesTile
+ TextBoxBackgroundImage.Text + </wp:WideBackgroundImage>
+ <wp:WideBackBackgroundImage
+ (string.IsNullOrEmpty(TextBoxBackBackgroundImage.Text) ?
Action=\Clear\ : ) + > + uriBaseImagesTile
+ TextBoxBackBackgroundImage.Text +
</wp:WideBackBackgroundImage>
+ <wp:WideBackContent + (string.IsNullOrEmpty
(TextBoxBackContent.Text) ? Action=\Clear\ : ) + >
+ TextBoxBackContent.Text + </wp:WideBackContent>
+ <wp:BackgroundImage + (string.IsNullOrEmpty
(TextBoxBackgroundImage.Text) ? Action=\Clear\ : ) + >
+ uriBaseImagesTile + TextBoxBackgroundImage.Text
+ </wp:BackgroundImage>
+ <wp:Count + (string.IsNullOrEmpty(TextBoxCount.Text) ?
Action=\Clear\ : ) + > + TextBoxCount.Text + </wp:Count>
+ <wp:Title + (string.IsNullOrEmpty(TextBoxFrontTitle.Text) ?
Action=\Clear\ : ) + > + TextBoxFrontTitle.Text + </wp:Title>
+ <wp:BackBackgroundImage
+ (string.IsNullOrEmpty(TextBoxBackBackgroundImage.Text) ?
Action=\Clear\ : ) + > + uriBaseImagesTile
+ TextBoxBackBackgroundImage.Text + </wp:BackBackgroundImage>
+ <wp:BackTitle + (string.IsNullOrEmpty(TextBoxBackTitle.Text) ?
Action=\Clear\ : ) + > + TextBoxBackTitle.Text
+ </wp:BackTitle>
+ <wp:BackContent + (string.IsNullOrEmpty
(TextBoxBackContent.Text) ? Action=\Clear\ : ) + >
+ TextBoxBackContent.Text + </wp:BackContent>
+</wp:Tile>
+</wp:Notification>;
break;
}
// Convertendo para byte[].
byte[] notificationMessage = Encoding.UTF8.GetBytes(tileMessage);
// Apontando o tamanho e tipo do corpo da requisio.
sendNotificationRequest.ContentLength = notificationMessage.Length;
sendNotificationRequest.ContentType = text/xml;
// A configurao 1 do cabealho X-NotificationClass serve
// para solicitar uma entrega imediata.
sendNotificationRequest.Headers.Add(X-WindowsPhone-Target, token);
sendNotificationRequest.Headers.Add(X-NotificationClass, 1);
using (Stream requestStream = sendNotificationRequest.GetRequestStream())
{

Edio 110 .Net Magazine

19

Notificaes Push no Windows Phone 8

Continuao: Listagem 13. Rotina que faz o envio da notificao do tipo Tile para o MPNS
83
84
85
86
87
88
89
90

requestStream.Write(notificationMessage, 0, notificationMessage.Length);
}
// Recuperando a resposta do MPNS.
HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.
GetResponse();
string notificationStatus = response.Headers[X-NotificationStatus];
string notificationChannelStatus = response.Headers[X-SubscriptionStatus];
string deviceConnectionStatus = response.Headers[X-DeviceConnectionStatus];
// Exibindo resposta recebida. Recomendado tratamento de erros,
// at porque as notificaes podem no ser enviadas ao telefone

91
92
93
94
95
96
97 }

LabelRespostaMPNS.Text = notificationStatus + | + deviceConnectionStatus


+ | + notificationChannelStatus;
}
catch (Exception ex)
{
LabelRespostaMPNS.Text = Ocorreu uma exceo ao enviar a requisio:
+ ex.ToString();
}

O ltimo tipo demonstrado ser a notificao do tipo Raw, que


ser recebida somente quando a App estiver aberta em primeiro
plano. Por esse motivo, a sua utilizao destinada para notificaes regulares que necessitem ser visualizadas apenas com a
App em execuo, que nesse caso, conforme a Listagem 14 est
sendo utilizada para atualizar a App com as informaes do
minuto a minuto do jogo de futebol. Conforme explicado anteriormente, o XML utilizado no possui formatao determinada
e deve ser utilizado livremente pelo desenvolvedor. Apesar disso,
a utilizao do cabealho da requisio obrigatria, conforme
a Tabela 7.
Cabealho da Requisio

X-NotificationClass

Valor

Descrio

Entrega imediata.

13

Entrega dentro de 450 segundos.

23

Entrega dentro de 900 segundos.

Tabela 7. Cabealho que devem conter no envio da requisio para notificaes do tipo Raw
Figura 20. Notificao do tipo Tile - Flip recebida

Figura 21. Notificao do tipo Tile - Iconic recebida

20 .Net Magazine Edio 110

Figura 22. Notificao do tipo Tile - Cycle recebida

Listagem 14. Rotina que faz o envio da notificao do tipo Raw para o MPNS
01 private void EnviarRaw()
02 {
03 try
04 {
05
// URI retornada pelo cliente Push quando criado o canal para notificao
06
string subscriptionUri = TextBoxUri.Text.ToString();
07
08
HttpWebRequest sendNotificationRequest =
(HttpWebRequest)WebRequest.Create(subscriptionUri);
09
10
// HTTP POST o unico method aceito para as nofitificaes
11
sendNotificationRequest.Method = POST;
12
13
// Criando um XML. Esse XML no tem template, o App ter que trata-lo.
14
string rawMessage = <?xml version=\1.0\ encoding=\utf-8\?> +
15
<WP8Push> +
16
<TituloJogo> + TextBoxTituloJogoRaw.Text + </TituloJogo> +
17
<InformacaoJogo> + TextBoxInformacaoJogo.Text +
</InformacaoJogo> +
18
</WP8Push>;
19
20
// Convertendo para byte[].
21
byte[] notificationMessage = Encoding.UTF8.GetBytes(rawMessage);
22
23
// Apontando o tamanho e tipo do corpo da requisio.
24
sendNotificationRequest.ContentLength = notificationMessage.Length;
25
sendNotificationRequest.ContentType = text/xml;
26
27
// A configurao 3 do cabealho X-NotificationClass serve
// para solicitar uma entrega imediata.
28
sendNotificationRequest.Headers.Add(X-NotificationClass, 3);

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 }

// Enviando conteudo ao MPNS


using (Stream requestStream = sendNotificationRequest.
GetRequestStream())
{
requestStream.Write(notificationMessage, 0,
notificationMessage.Length);
}
// Recuperando a resposta do MPNS.
HttpWebResponse response = (HttpWebResponse)sendNotification
Request.GetResponse();
string notificationStatus = response.Headers[X-NotificationStatus];
string notificationChannelStatus = response.Headers[X-Subscription
Status];
string deviceConnectionStatus = response.Headers[X-DeviceConnection
Status];
// Exibindo resposta recebida. Recomendado tratamento de erros,
// at porque as notificaes podem no ser enviadas ao telefone
LabelRespostaMPNS.Text = notificationStatus + | + deviceConnection
Status
+ | + notificationChannelStatus;
}
catch (Exception ex)
{
LabelRespostaMPNS.Text = Ocorreu uma exceo ao enviar a requisio:
+ ex.ToString();
}

Edio 110 .Net Magazine

21

Notificaes Push no Windows Phone 8

Autor
Felipe Farias Ferrari
Especialista em Desenvolvimento de Software, graduado em Cincia da Computao pelo Centro Universitrio da FEI. Atua como
Desenvolvedor .NET pela Hewlett-Packard Company, e Consultor
Especializado em Arquitetura OO, Web, Mobile e Plataforma .Net.

Links:
Documentao oficial referente o Microsoft Push Notification Service
http://msdn.microsoft.com/en-us/library/windowsphone/develop/ff402558(v=vs.105).aspx
Figura 23. Notificaes do tipo Raw recebidas
O resultado desse exemplo apresentado na Figura 23.

Concluso
A utilizao das notificaes Push pode fazer com que sua App
tenha maior aceitao e, por consequncia, alcance maior popularidade, visto que uma funcionalidade que permite ao usurio
estar sempre atualizado ou em contato mais vezes com a App, e
que d a sensao para o usurio de que ele est recebendo um
contedo exclusivo para ele. Para isso, necessrio que seja feita
uma anlise em relao a escolha do tipo de notificao, levando
em conta objetivo da notificao e a melhor maneira de apresentao ao usurio.

22 .Net Magazine Edio 110

Adicionando os tipos de Notificao para Tiles do Windows Phone 8, no Windows


Phone 7.8
http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj720574(v=vs.105).aspx
Documentao oficial sobre notificao Push no Windows Phone
http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202945(v=vs.105).aspx

Voc gostou deste artigo?


D seu voto em www.devmedia.com.br/netmagazine/feedback
Ajude-nos a manter a qualidade da revista!

Edio 110 .Net Magazine

23

Data Binding em WPF: interagindo com o banco de dados

Data Binding em WPF:


interagindo com o
banco de dados
Como utilizar Data Binding, LINQ to SQL e MVVM
em aplicaes reais

WPF fornece ao desenvolvedor uma forma


muito poderosa e de fcil utilizao para criar
interfaces de usurio. Porm, como tem se
enxergado ao longo dos ltimos anos, as aplicaes
precisam trabalhar com dados para serem consideradas
completas. Uma aplicao comercial, por exemplo, no
pode simplesmente se esquivar de utilizar dados, geralmente organizados em bancos de dados relacionais. E,
em tempo de execuo, esses dados sero atualizados,
provavelmente. A partir disso, como os controles iro
saber que os dados que esto exibindo so os mais
recentes?
Para essa questo, o WPF fornece uma tecnologia
chamada de Data Binding, ou ligao de dados, em uma
traduo literal. Com essa tecnologia, possvel realizar
a ligao entre as propriedades de controles, uma fonte
e um alvo, no caso. No cenrio mais comum, isso ser
utilizado para realizar a conexo entre os controles que
mostram dados com a fonte de dados que faz a populao do mesmo. Ento, quando a propriedade do objeto
fonte (no caso, os dados) alterada, a propriedade do
outro objeto (no caso, o controle) atualizada. Isso se d
de uma forma bem simplificada para o desenvolvedor, e
quem cuida de todas as atividades que existem por trs
dessa atualizao o WPF.
Outro ponto importante que as aplicaes necessitam
de uma organizao para serem mantidas. O padro
MVVM fornece ideias interessantes a esse respeito,
trazendo um padro de projetos que permite uma clara
separao entre a interface de usurio e sua lgica de negcios. Isso muito til nesse caso, porque, obviamente,
os dados devem ser buscados em algum lugar, fora dos

24 .Net Magazine Edio 110

Resumo DevMan
Porque esse artigo til::
Em geral, todas as aplicaes reais precisam trabalhar com dados
que, normalmente, vm na forma de um banco. Esse artigo til
porque traz informaes sobre como utilizar dados em aplicaes
WPF de forma segura e rpida. O Data Binding do WPF um recurso extremamente interessante e til para o desenvolvedor, que
consegue realizar a ligao de dados sem precisar criar um cdigo
muito extenso. Alm disso, o uso de LINQ se d pelo fato de ser uma
tecnologia muito til e fcil de utilizar para acesso a bancos de dados
relacionais, e o padro MVVM torna a separao entre a lgica de
negcios, os dados e a interface de usurio muito clara, criando uma
maior organizao do cdigo.

arquivos XAML que compem a interface bsica do aplicativo.


E o MVVM fornece as ferramentas necessrias para que isso seja
realizado de forma organizada e totalmente independente. Por
exemplo, os Models sero as classes do LINQ que representaro o
banco de dados, e os ViewModels sero responsveis pela ligao
entre os Models e as Views, criando todas as rotinas que envolvem
o banco de dados.

WPF Data Binding


O Data Binding uma parte fundamental da plataforma do WPF.
Com os poderes dessa tecnologia, possvel criar uma conexo
entre as propriedades de dois objetos, permitindo que, quando a
propriedade do objeto fonte alterada, a propriedade do objeto
alvo atualizada. Um excelente exemplo a utilizao de um
controle Slider para modificar a propriedade de outro controle.
A mudana refletida em tempo de execuo.

Com isso, Data Binding tambm um conceito chave na criao de animaes em WPF. importante notar que, em WPF,
possvel criar uma ligao entre objeto e fonte de dados atravs
de forma procedural, atravs de cdigo, ou de forma declarativa,
via XAML.
Basicamente, o Data Binding no WPF possui quatro peas
bsicas:
Target: o objeto que ir utilizar o resultado da ligao;
Target Property: a propriedade do objeto alvo que ir utilizar
o resultado;
Source: o objeto que fornece o valor;
Path: o caminho que localiza o valor dentro do objeto fonte.
Dessas quatro, as duas primeiras so as mais fceis de serem
entendidas. O Target o controle que contm a ligao, ou seja,
o controle que receber o valor que o Source ir enviar. J a
Target Property a propriedade desse objeto alvo que ir receber
o valor da ligao. importante notar que a Target Property de
um Binding deve ser uma dependency property (BOX 1). Como
a maioria das propriedades cujo Data Binding traria alguma
vantagem so dependency properties, isso acaba no sendo um
grande problema. A fonte do objeto (Source) o objeto do qual a
ligao busca o valor. Esse objeto pode ser um controle, dados ou
um objeto definido em code-behind.
BOX 1. Dependency Properties
O propsito de dependency properties fornecer um meio de basear o valor de uma propriedade
no valor de outras entradas. Essas outras entradas incluem propriedades de sistema, mecanismos
de determinao de propriedades em tempo de execuo, templates, estilos, etc. Alm disso, elas
podem ser implementadas para fornecer a validao dos dados que so passados a ela, valores
padro, monitoramento de mudanas em outras propriedades, entre outros. Em resumo, dependency
properties so propriedades que podem ser definidas atravs de mtodos como estilizao, data
binding, animao e herana.

interessante observar que existem trs tipos de propriedades


que podem ser definidas para a especificao da fonte, que so
ElementName, Source e RelativeSource (BOX 2). S possvel
especificar uma delas por vez, ou seja, o desenvolvedor precisa
escolher uma, dependendo da aplicao em questo. Por fim,
mas no menos importante, vem o caminho da ligao de dados
(Path). Na maior parte dos casos, ele definido pelo nome da
propriedade fonte que o desenvolvedor deseja utilizar. No caso
da utilizao de dados de um banco relacional, ele ir representar
o campo a ser mostrado.
Em WPF, alguns controles, como botes e caixas de texto, so
considerados controles de contedo, ou content controls. Eles foram criados para mostrar apenas um dado, geralmente um texto.
Outros controles, como listBoxes e comboBoxes, foram criados
para mostrar uma sequncia de valores de um mesmo tipo, e
como tal, so considerados controles de itens, ou item controls.
Como possvel perceber facilmente, realizar a ligao de dados
a controles de contedo muito simples e direto. Basta setar os

quatro elementos bsicos (Target, Target Property, Source e Path)


e est concludo o servio. No caso de controles de itens, a coisa
fica um pouco mais complexa. Para determinar o que mostrar para
cada item, o controle chama o mtodo ToString() da classe base.
No caso de nmeros ou strings, classes que existem por padro,
esse mtodo retorna a representao textual dos itens. Porm, no
caso de objetos mais complexos, como as classes de dados que
queremos definir, ele simplesmente retorna o nome da classe.
A soluo mais simples sobrescrever o mtodo ToString() na
classe de dados que foi definida para que ele retorne algo mais
til para o usurio. Uma soluo mais elaborada, e melhor do
ponto de vista da qualidade da aplicao, criar um template
que mostre os dados de outra forma. Ser nesse template que
ser realizada a ligao com os dados da classe. Essa abordagem
permite que o listBox mostre mais que um tipo de dados por
linha, transformando a experincia do usurio em algo muito
mais interessante.
BOX 2. Binding Source
Como foi dito anteriormente, a fonte da ligao de dados pode ser definida de trs formas:
atravs de ElementName, Source ou RelativeSource. Dessas trs, a primeira a mais simples.
A propriedade ElementName simplesmente recebe o nome de um controle, o controle fonte, no caso.
J a propriedade Source um pouco mais complexa, e geralmente definida atravs de um recurso
esttico (StaticResource). Ela identifica um objeto que deve ser utilizado como a fonte da ligao de
dados, ou seja, utilizada, geralmente, para realizar a ligao com dados oriundos de uma classe. Por
fim, o RelativeSource permite que o objeto fonte seja especificado pela sua relao com o controle
alvo. Normalmente utilizado quando se desejam duas propriedades no mesmo controle.
Alm desses trs, existe um meio adicional de definir a fonte de ligao em um Data Binding:
definindo a propriedade DataContext do controle. Uma vez que controles herdam essa propriedade
de seus ancestrais, esse mtodo permite que vrios controles dividam a mesma fonte de dados.

Outro recurso muito importante que o WPF traz para o Data


Binding a possibilidade de mudana de modos. O WPF possui
quatro modos de ligao de dados que permitem ao desenvolvedor
especificar a relao entre os objetos alvo e fonte. Com o modo
OneWay, como o prprio nome sugere, apenas mudanas no objeto
fonte so importantes, e atualizaro o objeto alvo. No modo TwoWay, a abordagem um pouco diferente, permitindo atualizao
em qualquer um dos objetos para refletir as mudanas em qualquer dos dois. J o modo OneWayToSource o completo inverso
do modo OneWay, e permite que mudanas no objeto alvo sejam
refletidas no objeto fonte. Por fim, o modo OneTime permite que
o objeto alvo seja alterado apenas uma vez, e as demais mudanas
tanto na fonte como no alvo no so refletidas no outro.

LINQ to SQL
L INQ, ou Language Integrated Query, uma linguagem
criada pela Microsoft que permite ao desenvolvedor escrever
consultas estruturadas seguras em torno de colees locais de
objetos e fontes remotas de dados. Basicamente, a LINQ permite
a realizao de consultas em qualquer coleo, seja um array,
uma lista ou uma fonte remota de dados, como uma tabela em

Edio 110 .Net Magazine

25

Data Binding em WPF: interagindo com o banco de dados

um banco relacional. Os tipos fundamentais que do suporte


LINQ esto definidos nos namespaces System.Linq, System.
Linq.Expressions e System.Core.
J a LINQ to SQL uma das subtecnologias que permeiam a
LINQ. Ela permite que o desenvolvedor utilize qualquer classe
para representar dados, desde que utilize alguns atributos simples. Por exemplo, o atributo [Table] diz LINQ to SQL que um
objeto deste tipo totalmente equivalente a uma linha em uma
tabela do banco de dados. Ou seja, a classe em si representa uma
das tabelas do banco.
Como em um diagrama E-R (Entidade-Relacionamento), em
LINQ to SQL tambm existe o conceito de entidades. Uma classe
com o atributo que define a mesma como uma tabela chamada
de entidade. importante ter em mente que esse mapeamento com relao a um banco de dados, para ser til, deve ser no
mnimo aproximadamente igual tabela do banco de dados. A
linguagem traz outros atributos, como [Column], responsvel
por definir colunas de uma tabela. Alm disso, cada um dos
atributos possui propriedades, que dizem se a mesma uma chave
primria, entre outras informaes importantes para bancos de
dados. Alm disso, como o que est sendo definido um banco
de dados, tambm importante definir o relacionamento entre
as tabelas, atravs de referncias a chaves estrangeiras. Isso
realizado atravs do atributo [Association].
Com as entidades j criadas, interessante partir para as consultas aos dados. A LINQ possui diversas formas de consulta aos
dados, como consultas Lambda (BOX 3), consultas de compreenso e subconsultas. As consultas Lambda so mais flexveis
e fundamentais, funcionando melhor para expresses com um
nico operador, enquanto consultas de compreenso so muito
mais simples para expresses mais complexas, e mais complexas
para expresses mais simples. Depende muito do desenvolvedor
qual utilizar em quais situaes. preciso analisar cada caso para
ter uma noo do que melhor.
BOX 3. Consultas Lambda
Expresses Lambda so expresses e mtodos annimos com uma sintaxe no sentido de tornar
mais agradvel e elegante a leitura do cdigo. As expresses Lambda surgiram dos delegates, que
nada mais so do que ponteiros para funes. Logo, expresses Lambda so funes, onde a parte
esquerda do smbolo => (operador lambda) so os argumentos da funo e a parte direita da
mesma contm o corpo do mtodo. Elas so utilizadas para expresses simples de consulta a dados,
por serem extremamente flexveis e elegantes, com pouco cdigo para realizar muita coisa.

O designer LINQ to SQL no Visual Studio traz uma ferramenta


de gerao automtica de entidades que muito simples e interessante. No caso de uma aplicao que possui um banco de dados
existente, muito mais interessante pedir a uma ferramenta para
gerar o cdigo automaticamente do que simplesmente construir
todas as tabelas e colunas em cdigo. Alm disso, para muitos
bancos de dados reais, isso impraticvel, devido grande extenso dos mesmos. Alm desse designer, existe uma ferramenta de
linha de comando chamada SqlMetal que faz o mesmo servio.

26 .Net Magazine Edio 110

Ambas geram entidades como classes parciais, de forma que


lgica adicional possa ser incorporada em arquivos separados.
Mais importante, as duas ferramentas tambm so responsveis
pela gerao das associaes entre as tabelas.

Padro MVVM (Model-View-View Model)


Para todo desenvolvedor, importante considerar que a interface
de usurio, alm de expor o sistema abaixo dela, deve satisfazer
os imprevisveis requerimentos estilsticos dos usurios. Logo, ela
deve ser a parte mais voltil da aplicao. Existem muitos padres
de design que auxiliam o desenvolvedor na tarefa de tornar a
interface de usurio mais independente do cdigo, entre eles o
MVP (Model-View-Presenter), o MVC (Model-View-Controller) e o
prprio MVVM. Com vrias possibilidades, importante entender
bem todas elas, para que a melhor escolha seja feita.
Porm, antes de tudo, interessante notar que padres de design
nem sempre so necessrios. Em aplicaes simples, pequenas,
totalmente desnecessrio e contra produtivo utiliz-los, uma vez
que qualquer desenvolvedor capaz de entender algumas poucas
linhas de cdigo. Mas, conforme a aplicao comea a crescer,
importante, essencial at, que haja um padro de design por
trs da mesma. Isso ir auxiliar na manuteno da aplicao, ir
permitir que outros desenvolvedores possam dar continuidade
mesma, alm de que a organizao estar l, permitindo que a
complexidade da aplicao continue a aumentar atravs de novas funcionalidades adicionadas. Para cada caso, interessante
analisar os possveis padres a serem utilizados, e escolher o que
melhor se encaixa no escopo do aplicativo.
O MVP um dos mais populares padres de design do mercado.
Ele contm trs componentes: View, Model e Presenter. A primeira
a interface com o usurio, sendo que os dados que ela mostra
compem o Model, e o Presenter a interface entre os dois. J o
MVC tambm muito popular e vem sendo usado h dcadas.
MVP e MVVM nada mais so do que adaptaes do MVC a alteraes de tecnologia. O MVC tambm possui um modelo e uma
view, porm o elemento que une os dois o Controller. Existem
algumas diferenas entre o Controller e o Presenter, entre as quais o
fato de que o controlador responsvel por determinar qual View
ser mostrada em resposta a qualquer ao, incluindo quando a
aplicao iniciada, enquanto o Presenter utilizado pela View
para trabalhar com dados, reagir a entradas do usurio e prover
validao das entradas do mesmo.
J o padro MVVM foi criado em 2005 por John Goosman, um
dos arquitetos do WPF e Silverlight na Microsoft. Conceitualmente, o MVVM muito parecido com o MVP, diferenciando-se
pelo fato de que o MVVM tpico para WPF e Silverlight (e, posteriormente, Windows Phone e Windows Store Apps), enquanto
o MVP completamente independente de plataforma. Ou seja,
no MVVM as Views so definidas atravs de arquivos XAML que
contm todos os elementos de interface com o usurio.
Em termos de utilidade, o MVVM visa estabelecer uma clara
separao entre o modelo de objetos e a interface com o usurio,
definida em XAML. Ele traz uma clara separao de camadas

(Figura 1), em que a View Model utilizada para realizar a ligao


entre a View e o Model, que no se conhecem. A comunicao entre
a View e a View Model se d atravs do mecanismo de binding do
WPF, alm de routed events e routed commands (BOX 4). So esses
trs ltimos elementos que, juntos, fazem do MVVM um padro
extremamente poderoso para construo de aplicaes WPF,
Silverlight, Windows Phone e Windows Store.

View

Data Binding/
Commands

ViewModel

Model

Notifications

Figura 1. Interao entre camadas MVVM


BOX 4. Routed Events e Routed Commands
Eventos roteados so eventos que navegam para cima ou para baixo na rvore de visual da aplicao,
dependendo da estratgia de roteamento. Isso significa que ele pode invocar manipuladores em
mltiplos ouvintes ao longo da rvore de elementos, ao invs de apenas no prprio elemento que
levantou o evento. As estratgias de roteamento so Tunneling, Bubbling ou Direct. Normalmente,
eventos roteados aparecem em pares, sendo o primeiro um evento Tunneling e o segundo um
Bubbling, sempre nessa ordem.
Comandos roteados so comandos que implementam a interface ICommand, ao invs de apenas
herdarem da mesma, como fazem os comandos comuns. Assim como eventos roteados, eles podem
navegar pela hierarquia de elementos do WPF. Basicamente, pelo fato de implementarem a interface
ICommand, Routed Commands so comandos que no sabem o que fazem. Quando recebem a
ordem de executar, eles simplesmente delegam essa responsabilidade a outro, navegando para
cima ou para baixo (dependendo da estratgia de roteamento) na rvore de visual da aplicao,
procurando algum que seja capaz de executar o comando.
Esses dois elementos Routed Events e Routed Commands esto relacionados um ao outro. Eles
formam a base para a comunicao ao longo das partes da interface de usurio, sejam essas partes
controles ou mesmo toda a janela.

Criando e organizando a aplicao no padro MVVM


Antes mesmo de se falar de forma mais aprofundada em MVVM,
preciso ter uma noo do que significa, e porque feita, a separao entre Model e View. O modelo a representao via software
da soluo a um problema, enquanto a vista utilizada para permitir que o usurio interaja com o modelo para resolver o mesmo
problema. A separao entre eles exige uma grande quantidade de
trabalho extra, portanto, preciso entender porque eles precisam
ser separados. Geralmente, em software, aceito que um design
modular melhor do que um monoltico. E designs modulares
bons possuem duas caractersticas em comum: loose coupling e high
cohesion. A primeira diz respeito ao nvel de dependncia entre os
dois mdulos, ou seja, quanto menos dependente os mdulos so
uns dos outros, melhor. J o segundo uma questo de coeso: o
mdulo deve fazer apenas aquilo a que se prope, nem mais, nem
menos. Um mdulo com baixa coeso normalmente possui vrias
funes irrelevantes para a resoluo do problema.
Os programadores vm enxergando o valor de dividir o modelo
e as views por um longo tempo. Separando esses dois elementos,

possvel obter a primeira fase na diferenciao das responsabilidades de subsistemas dentro do produto. Porm, preciso que
haja uma ligao entre eles. Implementaes de padres de projetos mais recentes, do conta de uma arquitetura Model-View-X,
onde X o elemento responsvel por realizar a integrao entre
o Model e a View. No caso do MVVM, a integrao realizada
atravs da ViewModel.
A partir daqui, interessante focar o desenvolvimento da aplicao no modelo MVVM. Como possvel notar a partir do que
foi visto, a ViewModel o elemento mais importante dessa trinca
que compe o MVVM. Mas, ao mesmo tempo, a menos familiar,
e a mais complicada de entender. Aqui, ser criada a estrutura
completa de uma aplicao com o padro MVVM, bem como uma
classe ViewModelBase, utilizada para trazer operaes bsicas que
dizem respeito ViewModel e sero posteriormente sobrescritas
para mais especificidade.
A ntes de tudo, preciso definir o que sero os Models, as
ViewModels e as Views. As Views so as mais simples de serem
definidas. Como se trata de uma aplicao WPF, as vistas sero
os arquivos XAML contendo as interfaces com o usurio. Alm
disso, eles sero responsveis por realizar o Data Binding com as
ViewModels. J os modelos so um pouco mais complexos. Aqui,
ser criada apenas uma pasta no projeto, chamada Models, que
conter todos os modelos de dados. Essas classes modelo sero
criadas posteriormente, quando o banco de dados for criado e
mapeado como classes do LINQ. Por fim, e mais importante,
preciso que se criem as ViewModels. Elas sero colocadas em uma
pasta separada no projeto, com esse mesmo nome, e essa pasta,
inicialmente, conter apenas a classe ViewModelBase, que ser
criada a seguir. Vale ressaltar que esse modelo de pastas em um
projeto s no o nico possvel para aplicaes com o padro
MVVM. Models, Views e ViewModels poderiam ser criados em
projetos separados, referenciando uns aos outros. A Figura 2
mostra a organizao do projeto no Visual Studio.
Nota
interessante ressaltar que, no caso de projetos diferentes para Models, Views e ViewModels,
preciso haver referncias entre eles. Porm, essas referncias devem ser cuidadas, pois sabido que,
pelo padro MVVM, ViewModels referenciam Models e Views referenciam ViewModels. Qualquer
referncia direta entre Views e Models pode levar a problemas no futuro, seja ela implcita ou
explcita, alm de quebrar o padro MVVM.

A partir da, preciso que haja alguma coisa na classe bsica das
ViewModels, ou seja, a classe ser utilizada como uma base para
as demais. Ela ir simplesmente implementar a interface INotifyPropertyChanged. Isso necessrio para que os ViewModels
sejam capazes de entender quando as propriedades so alteradas
pela View. Isso fundamental, pois, essencialmente, no haver
nenhum tipo de cdigo administrvel na View, de acordo com
o padro MVVM. A questo aqui que a interface em questo
contm apenas um evento, chamado PropertyChanged, que
deve ser implementado. Esse evento deve ser pblico, pois pode

Edio 110 .Net Magazine

27

Data Binding em WPF: interagindo com o banco de dados

ser acessado por qualquer classe. Para as classes que implementam esse evento, faz sentido escrever um ajudante simples, que
simplifica a chamada do evento. Esse mtodo aqui chamado
de OnPropertyChanged(string prop). A Listagem 1 mostra o
resultado da classe base de ViewModels. Posteriormente, ser
visto como esse mtodo utilizado para controlar a mudana de
propriedades na View.

Figura 2. Organizao do projeto


Listagem 1. Classe ViewModelBase
01 namespace DadosEmWPFArtigo.ViewModels
02 {
03 class ViewModelBase : INotifyPropertyChanged
04 {
05
public event PropertyChangedEventHandler PropertyChanged;
06
protected virtual void OnPropertyChanged(string prop)
07
{
08
if (PropertyChanged != null)
09
{
10
PropertyChanged(this, new PropertyChangedEventArgs(prop));
11
}
12
}
13 }
14 }

A partir da, a classe bsica est definida. Porm, com essa classe
base, a comunicao entre ViewModel e View ser realizada somente atravs de eventos. Mas essa comunicao tambm pode ser
realizada atravs de comandos. Para isso, ser criada uma classe
bsica, chamada RelayCommand, ou comando de transmisso,
em uma traduo literal. a classe base de todos os comandos
que podero ser chamados na ViewModel que ser criada. Essa
classe vista em muitos projetos MVVM, e se tornou quase um
padro. Embora varie de projeto para projeto, em essncia ela
sempre muito parecida, servindo como uma base a qualquer comando. Porm, preciso entender que existem alguns requisitos
que a classe RelayCommand deve atender. Ela deve manter a
separao entre os controles e o mtodo que ir ser chamado, a
implementao deve ser to artificial quanto for necessrio, nem
mais, nem menos, fazendo com que a mesma seja extremamente
intuitiva para usar, e tambm que dependncias extras devem
ser mantidas ao mnimo, sempre lembrando que dependncias

28 .Net Magazine Edio 110

em excesso podem quebrar o padro MVVM, gerando problemas


futuros.
Com essas tcnicas de design em mente, a criao da classe
RelayCommand muito simples. Ela implementar a interface
ICommand e, como tal, ter disposio os mtodos CanExecute(), Execute() e o evento CanExecuteChanged, que como o nome
sugere, ser disparado quando a possibilidade de execuo passar de true para false ou vice-versa. Como visvel na Listagem 2,
trata-se de uma implementao bastante simples, genrica, mas
que contm todos os elementos necessrios a um comando, sendo
intuitiva para usar. Como vemos na linha 27, a tarefa de executar
o comando delegada ao delegate Action<object>, portanto no
h sobrecarga de dependncias extras, o que aconteceria se fosse
utilizado um CommandExecuteHandler, por exemplo. Outro delegate utilizado com o mesmo propsito foi o Predicate<object>,
que evita uma chamada ao CanCommandExecuteHandler. Como
a presena do canExecute opcional, foram criados dois construtores (linhas 03 e 05). J o mtodo CanExecute() simplesmente
diz que caso o campo _canExecute no tenha sido especificado
no construtor, o comando pode ser executado sim, delegando a
responsabilidade da execuo para o Predicate<object>. Por fim,
o evento criado diz respeito a quando o mtodo CanExecute()
muda seu valor de retorno. Como possvel ver nas linhas 20 e 21,
o CommandManager (BOX 5) fornece um evento chamado RequerySuggested, que chamado quando ele acredita que houve
mudana no valor de retorno.
Listagem 2. Classe RelayCommand
01 class RelayCommand : ICommand
02 {
03 public RelayCommand(Action<object> execute) : this(execute, null)
04 { }
05 public RelayCommand(Action<object> execute,
Predicate<object> canExecute)
06 {
07
if (execute == null)
08
{
09
throw new ArgumentNullException(execute);
10
}
11
_execute = execute;
12
_canExecute = canExecute;
13 }
14 public bool CanExecute(object parameter)
15 {
16
return _canExecute == null ? true : _canExecute(parameter);
17 }
18 public event EventHandler CanExecuteChanged
19 {
20
add { CommandManager.RequerySuggested += value; }
21
remove { CommandManager.RequerySuggested -= value; }
22 }
23 public void Execute(object parameter)
24 {
25
_execute(parameter);
26 }
27 private readonly Action<object> _execute;
28 private readonly Predicate<object> _canExecute;
29 }

Edio 110 .Net Magazine

29

Data Binding em WPF: interagindo com o banco de dados

BOX 5. CommandManager
uma classe selada que prov mtodos teis para utilizao em comandos. Alm disso, a classe
fornece servios que permitem descobrir o status de um comando. Os mtodos teis variam desde
mtodos de registro de objetos de binding at handlers de eventos de comandos. Como visto h
pouco, o nico evento da classe o RequerySuggested, que ocorre quando ele detecta condies que
podem alterar a capacidade do comando de executar.

Criando o banco de dados com LINQ


Como foi visto, a LINQ to SQL oferece uma srie de ferramentas
que permitem ao desenvolvedor representar dados atravs de
classes. Para isso, basta que estas sejam decoradas com alguns
atributos especiais, como [Table] ou [Column]. Cada atributo
possui um propsito e vrias propriedades, todas elas dizendo
respeito a bancos de dados. Por exemplo, o atributo [Column]
possui uma propriedade chamada IsPrimaryKey, do tipo boolean,
para indicar se a coluna corresponde chave primria da tabela.
Esse um conceito unicamente de bancos de dados relacionais,
o que refora a ideia de que a LINQ foi feita para que as classes
sejam transformadas em tabelas de bancos de dados.
Para este exemplo, ser criada uma tabela de consumidores, chamada Customer. Essa tabela conter as colunas correspondentes
ao Nome do consumidor, seu CPF e seu Endereo, apenas, como
uma forma de simplificao da mesma, alm, obviamente, de seu
identificador nico, Id. Como possvel observar na Listagem 3, a
classe Customer possui o atributo [Table] decorando-a, indicando
que se trata de uma tabela. Alm disso, tambm se v que todas as
propriedades da classe foram transformadas em colunas, atravs
do atributo [Column]. possvel notar uma propriedade comum
a todos eles, chamada Storage. Essa propriedade responsvel
por indicar ao banco de dados que o local de onde o dado deve
ser buscado, e onde ele deve ser armazenado, no aquela propriedade pblica ali, e sim o campo privado que foi declarado no
comeo da classe.
Listagem 3. Classe de dados Customer
01 [Table]
02 public class Customer
03 {
04 private int id;
05 private string name;
06 private string cpf;
07 private string endereco;
08 [Column (IsPrimaryKey=true, Storage=id)]
09 public int Id {...}
10 [Column (Storage=name)]
11 public string Name {...}
12 [Column (Storage=cpf)]
13 public string Cpf {...}
14 [Column (Storage=endereco)]
15 public string Endereco {...}
16 }

Porm, como facilmente perceptvel, essa classe apenas uma


representao do banco de dados; o banco em si ainda no foi
criado. Para isso, ser criada uma segunda classe, que representar

30 .Net Magazine Edio 110

o DataContext do banco de dados. Na LINQ, essa classe que


efetua a comunicao com a fonte de dados. A classe que ser
criada deve derivar da classe base em System.Data.Linq.DataContext. Ela contm a informao e os mtodos para efetuar a
conexo com o banco de dados, alm de manipular esses dados.
Como visvel na Listagem 4, essa classe simples, DBDataContext,
apenas possui um campo, cust, para a tabela de consumidores
do banco de dados. Essa ser a nica tabela do banco, mas, caso
existissem outras, elas tambm seriam definidas aqui. Tambm
possvel ver que o construtor da classe simplesmente chama o
construtor da classe base DataContext, com a string de conexo ao
banco. Essa abordagem de classes parciais dita como fortemente
tipada, e muito mais elegante e recomendada que a abordagem
comum, onde se instancia um DataContext genrico e passa-se
as tabelas a ele.
Listagem 4. Classe DBDataContext
public partial class DBDataContext : DataContext
{
public Table<Customer> cust;
public DBDataContext(String connectionString) : base(connectionString)
{...}
}

Mas um problema persiste. Embora a classe de conexo ao banco


de dados tenha sido criada, o banco em si ainda no existe. Para
isso, ser criada uma terceira classe, chamada CustomerData. Essa
classe ser responsvel pela criao e por toda a manipulao
dos dados na aplicao. Ou seja, ela ser responsvel por adicionar, atualizar, excluir e buscar dados no banco. E, para isso, ela
utilizar o DBDataContext criado anteriormente. Inicialmente,
conforme mostrado na Listagem 5, a classe simplesmente ir,
em seu construtor, realizar uma chamada ao DataContext. Com
isso, ir ser realizada uma simples verificao: se o banco de
dados existe ele continua, se no existe ele cria o banco. Isso
uma funo que a LINQ traz que muito importante, pois ele
garante que o banco de dados existir antes de comear a realizar
qualquer operao nele.
Listagem 5. Construtor da Classe CustomerData
01 public CustomerData()
02 {
03 using (var c = new DBDataContext(conn))
04 {
05
if (!c.DatabaseExists())
06
{
07
c.CreateDatabase();
08
}
09 }
10 }

A seguir, temos a criao dos mtodos responsveis pela adio, atualizao e excluso de linhas do banco de dados, alm do
mtodo responsvel por criar uma lista de consumidores. Esses

mtodos foram criados tambm dentro da classe CustomerData,


e utilizam novamente o mesmo DBDataContext que responsvel pela conexo ao banco de dados. O mtodo Add(Customer
c), basicamente, realiza a insero do consumidor passado como
parmetro na tabela do banco de dados. Isso realizado conforme a Listagem 6, que mostra que primeiramente realizado
um InsertOnSubmit(c), na tabela de consumidores do banco, e
posteriormente essas mudanas so enviadas ao banco de dados
pelo DataContext. Os demais mtodos, Update(Customer c) e
Delete(Customer c) seguem o mesmo padro, recuperando, entretanto, o consumidor do banco de dados atravs de uma consulta,
para realizar a alterao e a excluso dos dados. Isso necessrio,
pois o mtodo no sabe que o valor passado por parmetro corresponde a um dado do banco de dados. A Listagem 7 mostra em
detalhes esse comportamento. Por fim, o mtodo List() retorna
uma lista que contm todos os elementos da tabela Customer do
banco de dados.
Listagem 6. Mtodo Add da classe CustomerData
01 public void Add(Customer c)
02 {
03 using (var ctx = new DBDataContext(conn))
04 {
05
ctx.cust.InsertOnSubmit(c);
06
ctx.SubmitChanges();
07 }
08 }
Listagem 7. Mtodo Delete da classe CustomerData
01 public void Delete(Customer c)
02 {
03 Customer aux = new Customer();
04 using(var ctx = new DBDataContext(conn))
05 {
06
var query = from cust in ctx.cust
where cust.Id == c.Id select cust;
07
foreach (Customer cus in query)
08
{
09
aux = cus;
10
}
11
ctx.cust.DeleteOnSubmit(aux);
12
ctx.SubmitChanges();
13 }
14 }

Como vimos, essas trs classes so os modelos da aplicao.


Elas contm a representao dos dados, bem como o acesso aos
mesmos. Porm, esses dados ainda esto completamente sem
uso, isolados nos Models. Para que eles possam ser acessados,
necessrio que ViewModels sejam criadas para buscar esses dados
e envi-los, de alguma forma, para a View exibi-los e para que o
usurio tenha alguma liberdade para realizar alguma atividade
com esses dados. Isso ser feito a seguir.

Criando a ViewModel
Agora, chegou a hora da criao das ViewModels. Como sabemos, pelo padro MVVM, cada uma das Views deve possuir uma

ViewModel, que ir realizar toda a interface entre o Model e a


prpria View. Ou seja, como a aplicao exemplo possui apenas
uma View (MainWindow), s existir uma ViewModel, que ser
chamada de MainWindowViewModel. importante notar que,
como a declarao da classe base de ViewModels tinha apenas um
evento, ele que ser utilizado para saber quando a propriedade
ser alterada pelo usurio.
Como sabido, a comunicao entre as ViewModels e as Views
realizada atravs de eventos e comandos. No necessrio
declarar ambos, mas pelo menos um deles sempre preciso; do
contrrio no haver meio de comunicao entre a ViewModel e
a View e a aplicao ficar completamente sem propsito. Neste
caso, a comunicao entre ambos consistir da verificao de se
a propriedade do objeto do Binding foi alterada ou no, como
j foi comentado. Alm disso, como tambm foi criada uma
classe base de comandos, a ViewModel ir utilizar essa classe
base para realizar comandos de adio, remoo e atualizao
no banco de dados.
Antes da criao das ViewModels, preciso ter em mente que
as ViewModels so modelos das Views. Embora bvio, a maior
parte dos desenvolvedores no d ateno a esse detalhe, e acaba
no sabendo exatamente onde colocar o cdigo: na ViewModel
ou no code-behind da View. Pode ser tentador colocar o cdigo
diretamente na View, por uma simples questo de convenincia.
Porm, isso quase sempre acarreta problemas futuros e, como foi
explicada anteriormente, uma boa aplicao MVVM precisa ser
loosely coupled, ou seja, quanto menos dependente a View for da
ViewModel, e vice-versa, melhor. importante limitar as Views a
apenas o cdigo que especfico aos eventos, elementos, recursos,
entre outros. Essa separao um objetivo que vale a pena, e deve
ser muito claro quando da criao das aplicaes.
Nessa criao de ViewModel especfica, toda a lgica ser feita
atravs da ViewModel, como ser visto. Ou seja, a View no ter
responsabilidade alguma, em termos de lgica de negcios, confiando na ViewModel para isso, o que totalmente condizente
com o padro MVVM. importante ter em mente que, como a
ViewModel ir referenciar o Model, ela poder utilizar algumas
aes que foram colocadas no modelo. Em outras palavras, as
aes que o Model realiza e que devem ser expostas View devem
ser utilizadas pela ViewModel. Aqui, vale um adendo: o modelo
apenas define funes. J a ViewModel deve definir comandos ou
eventos que sirvam para utilizar essas funes na View, atravs
do Data Binding.
Com esses conceitos em mente, hora da construo da ViewModel em si. Como foi criada anteriormente uma classe base de
ViewModels, chamada ViewModelBase, que implementa INotifyPropertyChanged, no necessrio fazer isso agora. Basta que
a classe que ser criada herde dessa classe bsica. Como vimos,
ela possui apenas um evento e um mtodo que trata esse evento.
Ou seja, todo o resto ter que ser implementado pela MainWindowViewModel, a ViewModel especfica nesse caso.
Primeiramente: a classe deve referenciar o modelo. Ou seja,
necessrio trazer um objeto do tipo CustomerData para que ele

Edio 110 .Net Magazine

31

Data Binding em WPF: interagindo com o banco de dados

possa ter acesso ao banco de dados. Alm disso, a classe CustomerData traz uma srie de mtodos, como vimos anteriormente,
para adio, remoo e atualizao de dados no banco. Agora,
na ViewModel, preciso realizar a ponte entre o modelo e a
vista. Basicamente, o que ser feito aqui a transformao
desses mtodos em comandos que podem ser entendidos pela
View. Repare que poderiam ser utilizados eventos, sem problema
nenhum. Porm, a abordagem por comandos se justifica devido
sua maior simplicidade de operao e codificao.
Em um segundo momento, preciso estabelecer os requisitos.
importante lembrar que antes de tudo, a ViewModel uma classe
e, como tal, ela ter atributos, propriedades e mtodos. Portanto, em
termos de atributos, necessrio que haja um do tipo CustomerData, para criao do banco de dados. Esse objeto ser inicializado no
construtor da classe e somente l. Por outro lado, tambm necessria a criao de trs objetos do tipo RelayCommand, que sero os
comandos de adio, remoo e atualizao do banco. Tambm so
necessrios dois atributos do tipo Customer, uma vez que a View
precisa indicar quem ser adicionado, atualizado ou removido do
banco de dados. Um deles ser o consumidor atual, que pode ser
excludo ou atualizado, enquanto o outro ser o consumidor a ser
adicionado. Tudo isso mostrado na Listagem 8. Todos esses atributos possuiro suas respectivas propriedades, para que possam
ser acessados pelo arquivo XAML.
Listagem 8. Atributos e Construtor da classe MainWindowsViewModel
01 class MainWindowViewModel : ViewModelBase
02 {
03
private CustomerData cData;
04
private RelayCommand addCommand;
05
private RelayCommand updateCommand;
06
private RelayCommand delCommand;
07
private Customer currentCustomer;
08
private Customer newCustomer;
09
10
public MainWindowViewModel()
11
{
12
cData = new CustomerData();
13
}
14 ...
15 }

A questo dos comandos importante de ser ressaltada, uma


vez que no muito trivial. Caso no seja a primeira vez que eles
esto sendo chamados, ou seja, o comando diferente de nulo,
o cdigo ir criar uma nova instncia de RelayCommand, para
tratar daquela chamada de comando. Cada um dos comandos
define uma chamada de funo como parmetro, sendo que essas
funes so simplesmente chamadas quelas definidas no Model
CustomerData. Alm disso, eles s possuem o getter; o setter
desnecessrio, uma vez que eles no recebero atribuies ser
somente leitura. A Listagem 9 mostra o resultado para o comando
de adio. Os demais comandos (atualizao e remoo) utilizam
o consumidor atual (currentCustomer) para realizar a operao,
conforme dito anteriormente.

32 .Net Magazine Edio 110

Listagem 9. Comando Add


01 public RelayCommand AddCommand
02 {
03 get
04 {
05
if (addCommand == null)
06
{
07
addCommand = new RelayCommand(param => this.Add());
08
}
09
return addCommand;
10 }
11 }
12 public void Add()
13 {
14 cData.Add(newCustomer);
15 ListData = cData.List();
16 }

Por fim, preciso que a ViewModel utilize a lista que foi criada
na classe CustomerData. Para isso, foi criada uma propriedade
chamada ListData, que receber a lista no construtor da ViewModel. Ou seja, quando for criada uma instncia da ViewModel,
ser criada a lista que corresponde a todos os dados do banco.
Esses dados sero atualizados a cada comando, como foi visto na
Listagem 9. importante ressaltar a necessidade de se referenciar
a propriedade ListData, e no o atributo listData. Isso essencial
porque, do contrrio, no haveria chamada ao mtodo OnPropertyChanged() (pois no seria a propriedade que mudaria) e o
listBox da View no seria atualizado.

Realizando o Data Binding com a View do WPF


Finalmente, a hora de realizar o to falado Data Binding entre
a MainWindowViewModel e a View. Para tanto, so necessrios
alguns elementos. O primeiro e principal deles: preciso referenciar o namespace dos ViewModels no cdigo XAML. Com
isso, possvel referenciar qualquer uma das classes (no caso, as
ViewModels) dentro do cdigo da janela. A partir disso, preciso definir um recurso que ser utilizado por toda a janela da
aplicao. Ou seja, esse recurso ser definido localmente, e ser
simplesmente a classe MainWindowViewModel. Ele declarado
como recurso porque contm uma srie de elementos que foram
criados especialmente para a View ter acesso aos dados dos modelos. Por fim, preciso definir os controles que recebero esses
dados, e faro tambm a sua atualizao, mas vamos por etapas.
A Listagem 10 mostra a importao do namespace e definio
do recurso MainWindowViewModel. O namespace foi rotulado
como vm, e o recurso, vmMainWindow.
Listagem 10. Cdigo inicial da View
01 <Window x:Class=DadosEmWPFArtigo.MainWindow
02
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
03
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
04
xmlns:vm=clr-namespace:DadosEmWPFArtigo.ViewModels
05
Title=MainWindow Height=350 Width=525>
06 <Window.Resources>
07
<vm:MainWindowViewModel x:Key=vmMainWindow/>
08 </Window.Resources>
09 <Grid DataContext={StaticResource vmMainWindow}>

Agora que h uma definio com relao ao recurso a ser utilizado, interessante preparar a interface. Trata-se de uma interface
bastante simples, dividida, basicamente, em trs partes: uma com
os campos para adio de novos consumidores, uma com os campos para atualizao e excluso dos mesmos e outra com o listBox
que contm todos os consumidores do banco de dados. A Figura 3
mostra como ficou a interface, ainda sem nenhum dado. Repare
que, como no h nenhum dado, o listBox direita se encontra
totalmente vazio. interessante ressaltar um detalhe com relao Listagem 10. Na ltima linha, definido um DataContext
para o Grid. Os controles WPF possuem a capacidade de herdar
propriedades de seus pais. Com isso, todos os controles filhos
do Grid que no possurem uma definio de DataContext iro
procurar, e encontrar essa definio, no prprio GridView.

BOX 6. DataTemplates
Templates de dados so utilizados para mostrar dados de um jeito particular. Basicamente, eles so
utilizados juntamente com objetos complexos, ou seja, objetos que possuem vrias propriedades
bsicas, como os Customers que foram criados nesse artigo. No caso, possvel mostrar em listBoxes,
comboBoxes e controles similares vrios tipos de itens de uma maneira particular, definida no prprio
template. Como um exemplo, com o advento desses templates, possvel para o desenvolvedor
mostrar Nome, Endereo e Telefone dos consumidores de uma forma organizada e rica. um dos
principais diferenciais do WPF para criao de interfaces de usurio ricas.

Figura 4. Sada sem definio da propriedade a ser mostrada

Figura 3. UI sem Data Binding


A primeira ao a ser realizada garantir que o listBox ir
receber os dados referentes do banco. Ou seja, realizar um
DataBinding com a propriedade ListData, da MainWindowViewModel. Como se trata de um listBox, a propriedade que
deve ser setada com esse binding a propriedade que contm
a fonte dos itens, ou ItemsSource. Essa propriedade foi definida, conforme a Listagem 11. Como observvel nessa mesma
listagem, a propriedade DisplayMemberPath foi definida para
mostrar o nome do consumidor no listBox. Caso essa propriedade no fosse definida, ele chamaria o mtodo ToString()
da classe Customer, o que no aconselhvel, pois mostraria
uma sada mais ou menos como mostra a Figura 4. O mtodo
ToString() poderia ser sobrescrito, porm essa no uma prtica recomendada de programao. Caso o interessante seja
mostrar algo mais elaborado no listBox, recomendado o uso
de DataTemplates (BOX 6).
Listagem 11. Cdigo do ListBox
<ListBox Grid.Column=1 Grid.Row=0 Grid.RowSpan=18
ItemsSource={Binding Path=ListData, Mode=OneWay}
DisplayMemberPath=Name Name=lstDados/>

Agora que o listBox j est habilitado para mostrar os objetos


Customer, necessrio criar meios de adio, atualizao e excluso desses mesmos objetos atravs do XAML. Para isso, sero
utilizados os vrios textBoxes criados esquerda da interface de
usurio. Para tanto, necessria a realizao de uma DataBinding.
Para a adio, essa ligao realizada com a propriedade NewCustomer, que enviado juntamente com o comando de adio para
ser adicionado ao banco de dados. Como visvel na Listagem 12,
trata-se de um binding de modo OneWayToSource. Isso realizado
dessa forma, pois no h nenhuma necessidade de os textBoxes
receberem de volta os dados que esto sendo enviados para o
banco de dados. interessante ressaltar tambm o binding adicionado ao comando do boto, pois ele ir simplesmente realizar
uma chamada e executar o comando de adio definido na
ViewModel.
Porm, com isso ainda existem alguns textBoxes sem utilizao.
Eles sero utilizados para realizar a atualizao de dados do
banco. Os trs recebero os dados do item selecionado no listBox,
sendo responsveis pela atualizao do mesmo quando houver
mudanas. O cdigo se assemelha muito quele verificado para a
adio de um novo consumidor, com algumas diferenas bsicas.
Ao invs de realizar a ligao com a propriedade NewCustomer,
ele liga os dados com a propriedade CurrentCustomer. Alm disso,
esse novo binding utiliza uma propriedade diferente, chamada
UpdateSourceTrigger, nesse caso o evento PropertyChanged. Esse
gatilho utilizado cada vez que a propriedade alterada, e funciona para garantir que o valor ser atualizado quando alterado.

Edio 110 .Net Magazine

33

Data Binding em WPF: interagindo com o banco de dados

J o comando de excluso chamado atravs do boto Delete, que


responsvel por chamar o comando atravs do mecanismo de
binding e excluir a linha correspondente ao CurrentCustomer no
banco. Por fim, a Figura 5 mostra o resultado desses DataBindings
na interface com o usurio. Por questes de simplificao, o cdigo
XAML desses textBoxes foram omitidos desse artigo, mas o leitor
pode ter acesso ao cdigo completo da aplicao, na pgina de
download da revista, no portal DevMedia.
Listagem 12. DataBinding para adio de Customers
01 <TextBlock Text=Nome: Grid.Row=0
Grid.Column=0/>
02 <TextBox Text={Binding Path=NewCustomer.Name,
Mode=OneWayToSource}
03 Grid.Row=1 Grid.Column=0/>
04 <TextBlock Text=Endereo: Grid.Row=2
Grid.Column=0/>
06 <TextBox Text={Binding Path=NewCustomer.Endereco,
Mode=OneWayToSource}
06 Grid.Row=3 Grid.Column=0/>
08 <TextBlock Text=CPF: Grid.Row=4 Grid.Column=0/>
09 <TextBox Text={Binding Path=NewCustomer.Cpf,
Mode=OneWayToSource}
10 Grid.Row=5 Grid.Column=0/>
11 <Button Content=Add Grid.Column=0 Grid.Row=6
Grid.RowSpan=2
12 Command={Binding Path=AddCommand}/>

O MVVM um padro de design que foi criado principalmente


para criao de aplicaes WPF e Silverlight. Isso porque, na poca,
eram as duas tecnologias permeadas pelo XAML. Hoje em dia,
h outras tecnologias que utilizam o poder dessa linguagem de
marcao e, por isso, o MVVM se aplica a elas tambm. Realizando
uma citao, aplicaes para Windows Phone e Windows Store
utilizam essa linguagem para criao de interfaces com o usurio.
Alm do MVVM, outros padres podem ser utilizados tranquilamente para criao de aplicaes empresariais, como MVP ou
MVC. Todos eles possuem suas particularidades, vantagens e
desvantagens. A principal vantagem na abordagem com MVVM
que ele foi criado para ser utilizado com o WPF, sendo, portanto,
o melhor meio de tirar vantagem dos poderes dessa tecnologia.
Por fim, a questo do acesso a dados tambm poderia ter sido
realizada de outra forma. A escolha por LINQ to SQL se deu pelo
fato de ser uma tecnologia do .NET framework que simplificou
muito as coisas para o acesso e consulta a dados. O principal poder
da tecnologia LINQ so suas consultas a dados, que podem ser
feitas de vrias formas. Alm disso, a LINQ oferece uma forma
interessante, simples e intuitiva de representar dados no formato de classes de dados, o que encaixa perfeitamente no modelo
MVVM para aplicaes WPF, como foi visto ao longo do artigo.

Autor
Henrique Machado Gasparotto
hmgasparotto@hotmail.com
Estudante de Engenharia de Computao na Universidade Federal
de Santa Maria UFSM e Tcnico em Informtica pelo SENAC
Santa Maria. Experincia em programao C# .NET e Java. Atualmente,
trabalha como bolsista no Laboratrio de Computao para Clima Espacial
no Centro Regional Sul de Pesquisas Espaciais (LCCE/CRS/INPE), com atividades voltadas
computao de alto desempenho.

Links e Referncias:
LINQ to SQL: .NET Language-Integrated Query for Relational Data
http://msdn.microsoft.com/en-us/library/bb425822.aspx

Figura 5. UI concluda

Concluso
Esse artigo trouxe uma nova abordagem a respeito de Data Binding em WPF. Alm disso, trouxe uma srie de conceitos, tericos
e prticos, a respeito de MVVM, que no possui muita literatura a
respeito, e a respeito de LINQ to SQL, com a criao de um banco
de dados puramente em classes do C#. So ferramentas muito
poderosas, que podem ser utilizadas juntas ou separadamente,
trazendo uma excelente forma de trabalhar com dados em aplicaes WPF.

34 .Net Magazine Edio 110

Entendendo o pattern Model-View-ViewModel (MVVM)


http://imasters.com.br/artigo/18900/desenvolvimento/entendendo-o-pattern-model-viewviewmodel-mvvm/
Data Binding (WPF)
http://msdn.microsoft.com/en-us/library/ms750612(v=vs.110).aspx

Voc gostou deste artigo?


D seu voto em www.devmedia.com.br/netmagazine/feedback
Ajude-nos a manter a qualidade da revista!

Edio 110 .Net Magazine

35

Integration Services2012: implementando solues de ETL - Parte 1

Integration Services2012:
implementando solues
de ETL - Parte 1
Construindo solues para a integrao entre
sistemas
Este artigo faz parte de um curso

Resumo DevMan
Porque esse artigo til::

necessidade de implementao de projetos envolvendo a integrao de diferentes sistemas


algo extremamente comum nos dias atuais. As
solues resultantes podem se basear tanto no compartilhamento de dados em tempo real atravs do uso de
Web Services, quanto na transferncia em lotes e num
horrio especfico de informaes que partam de uma
origem para um determinado repositrio de destino.
Embora Web Services representem um meio rpido
e instantneo para a troca de dados entre aplicaes,
o comum que a utilizao destes componentes esteja
restrita a contextos caracterizados por um trfego menor
de informaes. Por outro lado, grandes quantidades
de dados so geralmente manipuladas por softwares
executados dentro de intervalos de tempo pr-definidos,
de forma a no comprometer com isto a performance na
utilizao de um ou mais sistemas.
No caso especfico desta segunda alternativa, as rotinas
responsveis por essas tarefas de integrao costumam
ser implementadas empregando as mais variadas tecnologias. bastante comum que tais solues possuam
um cdigo extenso e complexo, dificultando no apenas
a sua manuteno, como tambm o entendimento do
processo como um todo. A inexistncia de uma documentao que detalhe o fluxo das diferentes atividades
realizadas durante o processamento s vem agravar esta
situao, no sendo raro que modificaes em aplicaes
deste tipo produzam efeitos indesejveis e exijam esforos posteriores na correo de problemas.

36 .Net Magazine Edio 110

Este artigo tem por finalidade apresentar o SQL Server Integration


Services 2012 e de que maneira este servio (que parte integrante
do SQL Server) pode ser til na integrao entre diferentes aplicaes.
Combinando recursos do .NET Framework a funcionalidades para a
manipulao de bases relacionais, XML e outros formatos para a representao de informaes, esta ferramenta permite a implementao
dos mais variados tipos de solues voltadas ao gerenciamentos de
dados. A implementao de projetos baseados no Integration Services
acontece atravs do Visual Studio, sendo que demonstraremos isto
atravs de dois exemplos (o primeiro envolvendo a exportao de
informaes, ao passo que um segundo exemplo descreve de que maneira informaes podem ser carregadas em uma base de dados).

O SQL Server Integration Services (SSIS) representa a soluo


oferecida pela Microsoft para atender a esses cenrios de integrao. Combinando a utilizao de tecnologias heterogneas para
a manipulao de dados (tais como bancos de dados relacionais,
XML, arquivos texto, planilhas do Excel, dentre outras alternativas) a recursos do .NET Framework, esta ferramenta possibilita
a construo de aplicaes capazes de se comportar de uma
forma robusta e escalvel (BOX 1) diante de grandes volumes de
informaes.
Outro ponto que pesa a favor do uso do Integration Services
est na construo de projetos a partir da modelagem grfica
de fluxos divididos em tarefas. Isto contribui para tornar mais
simples o desenvolvimento de novas aplicaes, evitando assim a
implementao de extensos trechos de cdigo que coordenem as
interaes entre atividades. O entendimento de como uma soluo
do Integration Services funciona tambm se torna mais intuitivo,

caracterstica esta que facilita o aprendizado desta ferramenta


por parte de desenvolvedores que no estejam familiarizados
com a mesma.
A meta da primeira parte deste artigo apresentar as principais
caractersticas do Integration Services e de que maneira esta ferramenta pode ser til na integrao entre sistemas. Para isto ser
apresentada uma aplicao que aborda a exportao de dados de
uma base relacional, gerando como resultado arquivos no formato
.csv. Numa prxima edio demonstraremos o processo inverso,
com a importao de informaes para um banco de dados a partir
de arquivos em diferentes formatos.
BOX 1. Escalabilidade
O conceito de escalabilidade refere-se capacidade de um sistema se adequar a uma demanda
crescente no seu uso, sem que com isto deixe de corresponder ao que se esperava inicialmente para
o mesmo.

SQL Server Integration Services: uma viso geral


O SQL Server Integration Services pode ser considerado uma
evoluo de outra ferramenta de ETL (BOX 2) da Microsoft: tratase do Data Transformation Services (DTS), que foi disponibilizado
quando do lanamento da verso 7 do SQL Server. J a primeira
verso daquilo que atualmente se conhece como Integration Services surgiu com o SQL Server 2005.
Desde ento, cada novo release do SQL Server vem acompanhado por avanos no que se refere aos recursos oferecidos pelo
Integration Services. Na verso 2012 isto no foi diferente, com
melhorias em questes como a configurao e o deployment
de solues, monitoramento de aplicaes e resoluo de problemas, mecanismos que possibilitam uma maior qualidade
em transformaes de dados, dentre outros aspectos. Uma
relao completa dos novos recursos do Integration Services
pode ser encontrada num dos endereos listados na seo de
Links deste artigo.
BOX 2. ETL
O processo conhecido como ETL (sigla do ingls Extraction, Transformation and Load) funciona,
em termos gerais, da seguinte forma: a partir de um repositrio de origem sero extrados dados,
com os mesmos sendo transformados seguindo critrios especficos a um determinado contexto.
Por fim, tais dados sero carregados numa base de destino. Solues prprias de ETL podem vir a ser
desenvolvidas, muito embora existam ferramentas prticas e bastante flexveis como o SQL Server
Integration Services.

Do ponto de vista arquitetural, uma aplicao do Integration


Services constituda por um ou mais packages (pacotes). J um
package formado por tasks (tarefas) que seguem geralmente
um fluxo de execuo contnuo. A implementao de um pacote
feita por meio do Visual Studio, atravs da modelagem grfica
de um fluxo com as tarefas que iro compor o mesmo; essa ltima
caracterstica torna a construes de solues para o Integration
Services um processo intuitivo e, portanto, mais fcil de ser as-

similado por desenvolvedores que comeam a ter os primeiros


contatos com esta ferramenta.
Na prtica, um package nada mais do que um arquivo XML
com a extenso .dtsx, podendo combinar instrues para o acesso a bancos de dados, arquivos e outros tipos de repositrios a
trechos de cdigo baseados em recursos da plataforma .NET.
No caso especfico da verso 2012, o SQL Server conta com o suporte para bibliotecas geradas sob do .NET Framework 4.0, sendo
que essa caracterstica se estende ao Integration Services.
Packages podem acessar repositrios de dados dos mais variados tipos:
Bases de dados relacionais que suportem drivers ODBC, OLE
DB e ADO.NET;
Bases multidimensionais mantidas atravs da ferramenta Analysis Services (BOX 3);
Arquivos de texto;
Planilhas do Excel;
Web Services.
BOX 3. Analysis Services
O Analysis Services um servio que integra o SQL Server, sendo utilizado na construo de
aplicaes baseadas em conceitos de Business Intelligence. Esta ferramenta viabiliza a realizao de
sofisticadas anlises, as quais normalmente servem de suporte para a tomada de decises no meio
corporativo. Isto acontece atravs da implementao de bases histricas alimentadas a partir de
bancos de dados transacionais, sendo que tais repositrios costumam ser modelados de uma forma
multidimensional (empregando para isto estruturas como cubos e dimenses).

Quanto sua forma de execuo, packages podem ser acionados


das seguintes maneiras:
A partir de uma aplicao .NET que tenha acesso ao diretrio
em que se encontra um determinado package;
Remotamente, atravs de instrues .NET para se acessar um
package previamente instalado num servidor SQL Server.
Maiores detalhes a respeito do funcionamento e da implementao de packages do Integration Services sero abordados mais
adiante nos exemplos prticos deste artigo.

Possveis cenrios de utilizao do Integration Services


Graas sua flexibilidade e ao suporte no acesso a diferentes
repositrios de dados, diversos so os cenrios em que o Integration Services poder ser empregado. A seguir esto listadas
algumas das possibilidades de uso desta ferramenta:
Na replicao de informaes entre diferentes bases de
dados;
Na integrao entre sistemas fiscais/contbeis e rgos
governamentais, sendo possvel destacar iniciativas como o
SPED (sigla de Sistema Pblico de Escriturao Digital). Este
ltimo um projeto do governo federal que procura automatizar o recebimento de informaes relativas a Livros Fiscais,
Contbeis e de PIS / COFINS mantidos por organizaes dos
mais variados segmentos;

Edio 110 .Net Magazine

37

Integration Services2012: implementando solues de ETL - Parte 1

Em processos de ETL, os quais normalmente esto associados


produo de dados para a gerao de complexas anlises em
solues de BI (BOX 4);
Na exportao de dados sob a forma de arquivos, em situaes
que geralmente envolvem a integrao entre um sistema de origem e outras aplicaes. Exemplos disso a gerao de listas de
preo disponibilizadas por um fornecedor ou fabricante de um
conjunto de produtos, o envio de informaes para cobrana bancria utilizando o padro conhecido como CNAB, dentre outros
processos relacionados ao compartilhamento de dados.

de um arquivo CSV (BOX 6) contendo o catlogo de uma distribuidora de produtos alimentcios fictcia. O arquivo em questo
no possuir cabealho, sendo formado pelos seguintes campos
(estes j na sequncia esperada, devendo ainda estar separados
por ponto-e-vrgula):
Cdigo do produto;
Nome do produto;
Categoria;
Fornecedor;
Preo Unitrio.

BOX 4. Business Intelligence

BOX 5. Reporting Services

BI (sigla em ingls para Business Intelligence; termo tambm conhecido como Inteligncia
Empresarial) um conjunto de tcnicas que envolvem a coleta, o processamento e a gerao de
informaes a partir de dados gerados em operaes cotidianas de uma organizao. Este tipo de
procedimento busca, a partir de tais prticas, prover anlises que auxiliem profissionais de gesto
em atividades relacionadas tomada de decises.

O Reporting Services uma soluo da Microsoft para a criao e o gerenciamento de relatrios no


ambiente corporativo. Trata-se de uma ferramenta extremamente flexvel, que possibilita inclusive

Exemplos de solues utilizando o Integration Services


A fim de demonstrar como o SQL Server Integration Services
2012 pode ser utilizado, sero criadas quatro solues no Microsoft
Visual Studio 2012 Professional:
TesteIntegration01: solution em que constar um projeto do Integration Services para a exportao de informaes de produtos sob
a forma de arquivos .csv. Existiro ainda nesta soluo trs projetos
do tipo Console Application, sendo que os mesmos apresentam
diferentes maneiras de se executar um package do Integration
Services por meio de recursos da plataforma .NET;
TesteIntegration02: nesta soluo ser demonstrada a importao
de arquivos .csv, .xlsx e .txt a partir de aplicaes do Integration
Services. Ser criado para isto um projeto em que sero carregadas
informaes sobre notas fiscais que envolvam o pagamento de
servios contratados por uma empresa hipottica.
Antes de iniciar a implementao destas Solutions, ser necessrio instalar o pacote Microsoft SQL Server Data Tools - Business
Intelligence for Visual Studio 2012 (caso este procedimento
ainda no tenha sido realizado anteriormente). Essa extenso
responsvel por ativar dentro do Visual Studio 2012 templates
que permitem a construes de solues baseadas no Integration
Services, Analysis Services e Reporting Services (BOX 5).

Implementando o primeiro exemplo


Conforme j discutido na parte inicial deste artigo, arquivos
ainda representam um dos principais meios para o compartilhamento de informaes entre sistemas. Muitas organizaes
investem pesado na automao de processos que envolvam a
transferncia de informaes, construindo assim solues que
permitem a manipulao de grandes volumes de informaes
em formatos padronizados.
Neste primeiro exemplo estaremos implementando uma soluo
chamada TesteIntegration01, a qual ser responsvel pela gerao

38 .Net Magazine Edio 110

a exportao de relatrios para formatos como planilhas do Excel e documentos PDF. Muito embora
corresponda a mais um dos servios que compem o SQL Server, o Reporting Services tambm pode
ser empregado na produo de relatrios que acessem outras bases relacionais (como Oracle, por
exemplo), bancos multidimensionais do Analysis Services ou, at mesmo, fontes de dados como XML
e Web Services.
BOX 6. Arquivos CSV
CSV (sigla do ingls Comma-separated values) um padro para a representao de dados em
um formato tabular. Arquivos deste tipo possuem a extenso .csv e, em termos prticos, nada mais
so do que sequncias de texto separadas por um caracter especial (o mais comum que se utilize
vrgula ou ponto-e-vrgula em tais representaes). O uso de arquivos .csv para a integrao entre
diferentes sistema corresponde a um tipo de prtica bastante comum, sendo que o prprio pacote
Office (por meio do Excel) oferece suporte a este tipo de formato.

Nota
Na seo de Links desse artigo possvel encontrar o endereo para download da extenso
Microsoft SQL Server Data Tools - Business Intelligence for Visual Studio 2012.

No caso especfico dos campos Nome do Produto, Categoria


e Fornecedor, as informaes associadas aos mesmos sero
sequncias de texto com todos os caracteres em maisculo. J o
campo Preo Unitrio ser um valor numrico com duas casas
decimais (estas ltimas separadas por vrgula), ao passo que a coluna Cdigo do Produto corresponder a um nmero inteiro.
Eventuais clientes desta companhia receberiam tal catlogo,
com o preo de comercializao sugerido para cada item. A base
que fornecer essas informaes o banco de dados Northwind,
com que pode ser obtido a partir de um endereo listado na seo
de Links deste artigo.
A Solution TesteIntegration01 ser formada pelos seguintes
projetos:
TesteIntegration01.SSIS: aplicao baseada no Integration Services e na qual acontecer a gerao do arquivo CSV com os dados
do catlogo de produtos;
TesteIntegration01.ExecucaoLocalPackage: Console Application
em que ser demonstrada a execuo de um package localizado
em um determinado diretrio;

TesteIntegration01.ExecucaoRemotaPackage: outro projeto do


tipo Console Application, sendo que esta aplicao apresentar
como executar via .NET Framework um package previamente
instalado num servidor SQL Server;
TesteIntegration01.ExecucaoRemotaJob: neste ltimo projeto
(tambm uma Console Application) ser demonstrado como
acionar um Job do SQL Server que executa uma aplicao do
Integration Services.

de origem, alguma forma de processamento produzindo um tipo


especfico de informao e, finalmente, a transferncia disto para
um ponto de destino que pode ser um banco de dados relacional
ou, mesmo, um arquivo que faa uso de um padro especfico de
representao (XML, planilhas do Excel, CSV, texto com posies
delimitadas, etc.). Conjuntos de instrues definidos nesta seo
so executados atravs de tarefas acionadas dentro do fluxo principal (Control Flow) de um package;

O projeto TesteIntegration01.SSIS ser gerado a partir do


template Integration Services Project (Figura 1), o qual habilitado aps a instalao da extenso Microsoft SQL Server Data
Tools - Business Intelligence for Visual Studio 2012.
O prximo passo agora consistir na criao do package
GeracaoCSVProdutos.dtsx (Figura 2), removendo ainda o arquivo
Package.dtsx (que foi gerado automaticamente ao se executar a
etapa anterior).

Figura 3. O package GeracaoCSVProdutos.dtsx ainda no implementado

Figura 1. Criando o projeto TesteIntegration01.SSIS

Parameters: aqui so declarados itens de configurao (BOX 7)


que servem de base para a execuo de um package;
Event Handlers: permite a implementao de rotinas (Event
Handlers) para o tratamento de eventos que ocorram ao longo do
processamento de um package. possvel tambm a definio de
rotinas em resposta a eventos que associados a elementos especficos de um package. Quanto utilizao de estruturas desse tipo,
comum que Event Handlers sejam implementados em tarefas
que envolvam tarefas como logging e tratamento de erros;
Package Explorer: neste local possvel a visualizao e o acesso
a todos os elementos definidos dentro de um package;
Connection Managers: itens declarados nesta seo possibilitam a conexo de elementos de um package a repositrios de
dados como bases relacionais e/ou arquivos dos mais variados
tipos.
BOX 7. Parmetros no Integration Services 2012

Figura 2. Criando o package GeracaoCSVProdutos.dtsx


Neste momento j ser possvel iniciar a implementao da aplicao para a exportao de informaes sobre produtos. Conforme
possvel observar na Figura 3, o package GeracaoCSVProdutos.
dtsx conta com as seguintes sees:
Control Flow: corresponde ao centro nervoso de um pacote no
Integration Services. neste local em que acontece a orquestrao das
diferentes tarefas (tasks) definidas para um package, seguindo para
isto um fluxo de execuo que obedece a uma sequncia lgica;
Data Flow: o principal tipo de funcionalidade oferecido pelo
Integration Services consiste na extrao de dados de um local

As estruturas conhecidas como Parameters (parmetros) passaram a fazer parte do Integration


Services com o lanamento do SQL Server 2012. Em termos prticos, um parmetro nada mais
do que uma configurao formada por um identificador, alm de um valor previamente definido.
Importante destacar que tal valor no sofre alterao durante o processamento da aplicao que
se est considerando.
Tambm merece destaque o fato de que este recurso surgiu com o intuito de simplificar o
gerenciamento de configuraes para aplicaes do Integration Services, algo que em verses
anteriores era feito por meio do uso de arquivos no formato XML.
Todo parmetro criado com base em um tipo de dado especfico. Atualmente, esses itens podem
ser declarados com base nos tipos: Boolean, Byte, DateTime, Decimal, Double, Int16, Int32, Int64,
SByte, Single, String, UInt32 e UInt64.
Quanto ao escopo de execuo, parmetros podem ser definidos de forma global (acessveis,
portanto, a todos os packages de um projeto), ou ainda, dentro de um package especfico (sendo
utilizados neste ltimo caso apenas por elementos que constem nessa estrutura).

Edio 110 .Net Magazine

39

Integration Services2012: implementando solues de ETL - Parte 1

No caso do package GeracaoCSVProdutos.dtsx, estaremos


definindo um parmetro do tipo String chamado pCaminhoGeracaoArquivosCSV (Figura 4). Esta configurao indicar o
caminho no qual sero gerados os arquivos .csv contendo o catlogo de produtos (num primeiro momento, partiu-se da premissa
que existir o caminho C:\Devmedia\TesteVisualStudio\ na
mquina em que a aplicao de exemplo for executada).
A interao entre as diferentes tarefas definidas em um package possvel graas ao uso de variveis (BOX 8). Para o package GeracaoCSVProdutos.dtsx, estar sendo criada a varivel
vNomeArquivoCSV (Figura 5). Embora preenchida com o valor
C:\Devmedia\TesteVisualStudio\Produtos.csv (para efeitos de
configurao dentro do Visual Studio), esta referncia do tipo
String ter o seu valor gerado dinamicamente, armazenando o
nome completo para o arquivo de produtos que ser criado durante a execuo do pacote GeracaoCSVProdutos.dtsx. Alm disso,
possuir um escopo que a torna acessvel a todos os elementos
deste package.

Duas conexes tambm devero ser criadas a partir da seo


Connection Managers.
A primeira destas conexes (chamada connNorthwind) faz uso
do ADO.NET como mecanismo de acesso a dados, permitindo a
execuo de consultas base Northwind (Figura 6). justamente
este o repositrio de onde sero obtidas as informaes para a
gerao do arquivo com a listagem de produtos.
J a conexo connArquivoCSVProdutos ser empregada na gravao de novos arquivos .csv contendo o catlogo de produtos.

Figura 4. Criando o parmetro pCaminhoGeracaoArquivosCSV

Figura 5. Criando a varivel vNomeArquivoCSV

Figura 6. Configuraes da conexo connNorthwind

Nota

Nota

Dentro do Visual Studio, a janela para definio de variveis pode ser acessada atravs do menu
SSIS, opo Variables.

A conexo connNorthwind foi criada a partir da opo New ADO.NET Connection..., a qual est
disponvel atravs do menu de atalho da seo Connection Managers.

BOX 8. Variveis no Integration Services

Nota

Variveis so elementos que auxiliam na manipulao de dados e na comunicao entre as diferentes


tasks que compem um package do Integration Services.
Assim como acontece nas linguagens de programao convencionais, uma varivel possui um
identificador e armazena um valor baseado em um tipo de dado especfico. Para este tipo de
estrutura, o Integration Services disponibiliza os seguintes tipos de dados: Boolean, Byte, Char,
DateTime, DBNull, Decimal, Double, Int16, Int32, Int64, Object, SByte, Single, String, UInt32 e UInt64.
Diferentemente daquilo que acontece com parmetros, os valores associados variveis podem ser
modificados em tempo de execuo. Graas a esta caracterstica, variveis representam a alternativa
ideal para a manipulao de dados em cenrios com um comportamento mais dinmico, tais como
loopings sobre colees de valores, desvios condicionais e construes de cdigo .NET que envolvam
a produo de novos valores a partir de dados pr-existentes.
Variveis tambm possuem um escopo. Ao criar um novo item deste tipo, possvel definir que
tal elemento estar disponvel a todos os elementos de um package ou, at mesmo, apenas para
conjuntos de elementos especficos.

A conexo connArquivoCSVProdutos foi gerada atravs da opo New Flat File Connection..., que
tambm est localizada no menu de atalho da seo Connection Managers.

40 .Net Magazine Edio 110

Na Figura 7 esto algumas das configuraes necessrias para


a gerao do arquivo .csv. Esses ajustes foram efetuados dentro
da seo General na janela Flat File Connection Manager
Editor:
No campo Connection manager name foi informado o valor
connArquivoCSVProdutos, ao passo que em Description est
um comentrio que descreve a finalidade desta nova conexo;
O campo File name foi preenchido com um caminho que aponta para um novo arquivo .csv a ser criado durante o processamento
do package GeracaoCSVProdutos.dtsx (apenas para efeito de

configurao da conexo connArquivoCSVProdutos). Embora


com um contedo fixo, este valor ser gerado posteriormente de
forma dinmica (por meio da varivel vNomeArquivoCSV);
O item Locale foi configurado de maneira que a criao
do arquivo .csv acontea em conformidade com os padres de
formatao regionais adotados no Brasil;
J no campo Format foi marcada a opo Delimited, que indica
a gerao de um arquivo delimitado por um separador (caracterstica tpica do formato CSV);
O elemento Header row delimiter determina o conjunto de
caracteres empregado na quebra de linhas em um arquivo;
Por fim, a opo Column names in the first row desmarcada
far com que o arquivo .csv seja criado sem um cabealho.

Figura 8. Definindo o separador para as colunas na conexo connArquivoCSVProdutos

Figura 7. Configurando a conexo connArquivoCSVProdutos


Na seo Columns foi selecionada a opo Semicolon {;} para
o campo Column delimiter (Figura 8). Com essa configurao
determinamos que todos os valores do arquivo .csv estaro separados por ponto e vrgula.
Na Tabela 1 esto as configuraes para cada uma das colunas
que faro parte do arquivo .csv contendo o catlogo de produtos.
Estes itens devero ser preenchidos na seo Advanced da janela
Flat File Connection Manager Editor (Figura 9).
Name

DataType

OutputColumnWidth DataScale

CodProduto

four-byte signed integer


[DT_I4]

NomeProduto string [DT_STR]

40

Categoria

string [DT_STR]

15

Fornecedor

string [DT_STR]

40

PrecoUnitario decimal [DT_DECIMAL]

Tabela 1. Colunas a serem configuradas para a conexo connArquivoCSVProduto

Figura 9. Configurando as colunas para a conexo connArquivoCSVProdutos


Confirmadas as definies do arquivo .csv de produtos, ser
necessrio ainda um ltimo ajuste. Como a gerao do nome de tal
arquivo ocorre de forma automtica, a conexo connArquivoCSVProdutos precisar receber este valor (por meio da propriedade
ConnectionString), a fim de que o processo de gravao dos dados
acontea de maneira correta.
O Integration Services permite que os valores de expresses
baseadas em variveis e parmetros sejam atribudos ao contedo
de uma propriedade, com este processo acontecendo dinamicamente durante a execuo da aplicao. Essa caracterstica
possvel graas a uma propriedade chamada Expressions, a qual

Edio 110 .Net Magazine

41

Integration Services2012: implementando solues de ETL - Parte 1

pode conter uma coleo de expresses que vinculam os valores


correspondentes a outras propriedades de um componente.
Praticamente todos os controles disponveis para a implementao
de um package contam com a propriedade Expressions.
Na Figura 10 apresentada a janela a partir da qual acontece
o preenchimento da propriedade Expressions (nota-se que foi
selecionada a propriedade ConnectionString da conexo connArquivoCSVProdutos). Um assistente (no caso, a janela
Expression Builder) pode ser utilizado para a gerao de novas
expresses, combinando variveis, parmetros e funes para
manipulao de valores, conforme indicado na Figura 11.

Nota
Para acessar a propriedade Expressions de um controle, utilize a janela Properties do Visual Studio.

Figura 12. Expresso que preencher a propriedade ConnectionString

Figura 10. Preenchendo a propriedade Expressions para a conexo connArquivoCSVProdutos

Conforme mencionado anteriormente, o fluxo principal que


define um package formado por uma sucesso de tarefas (tasks).
Outros elementos conhecidos como containers permitem o agrupamento lgico de uma srie de tarefas, alm de disponibilizar
informaes para a realizao de aes especficas.
Na Figura 13 apresentada a janela Toolbox com alguns dos
controles que podem vir a ser empregados na construo do fluxo principal de um pacote. Outros tipos de tasks (agrupadas na
seo Other Tasks) tambm esto disponveis para uso, sendo
possvel se obter um maior detalhamento sobre os mesmos a partir
da documentao online do Integration Services.

Figura 11. A janela Expression Builder


J na Figura 12 est a expresso responsvel pelo preenchimento
automtico da propriedade ConnectionString da conexo connArquivoCSVProdutos (atravs da varivel vNomeArquivoCSV).
Concludo o processo de gerao das conexes, iniciaremos agora
a configurao das diferentes tarefas que faro parte do package
GeracaoCSVProdutos.dtsx. Este procedimento acontecer a partir
da seo Control Flow.

42 .Net Magazine Edio 110

Figura 13. Principais tasks e containers para a construo de um package

Quantos s tasks que podem ser empregadas em packages do


Integration Services, merecem destaque os seguintes controles:
Data Flow Task: permite a obteno de dados de uma fonte de
origem, o seu processamento e, consequentemente, a gravao das
informaes produzidas em um repositrio de destino;
Execute SQL Task: possibilita a execuo de instrues SQL e
stored procedures a partir de uma base de dados relacional;
Analysis Services Processing Task: realiza o processamento de
alguma estrutura (cubos, dimenses, modelos de data mining)
definida no Analysis Services;
Bulk Insert Task: efetua o carregamento de dados em uma
tabela empregando para isto o comando BULK INSERT do SQL
Server (BOX 9);
BOX 9. Bulk Copy
Bulk Copy um tipo de operao empregada na transferncia de grandes volumes de informaes
para uma base relacional. O comum que aes desse gnero envolvam a carga de arquivos no
formato texto para tabelas de um banco de dados especfico. O SQL Server oferece total suporte a
operaes de Bulk Copy, disponibilizando para isto o comando BULK INSERT; no caso do ADO.NET, este
mecanismo de acesso a dados disponibiliza a classe SqlBulkCopy (namespace namespace System.
Data.SqlClient) para a implementao deste tipo de funcionalidade em aplicaes .NET.

Data Profiling Task: permite a execuo de anlises, a fim


de identificar potenciais problemas relativos qualidade dos
dados;
Execute Package Task: torna possvel a execuo de outro package, a partir do pacote em que esta task for utilizada;
Execute Process Task: permite a execuo de programas externos
a um package, como acionar um utilitrio para compactao de
arquivos, por exemplo;
File System Task: possibilita a realizao de operaes envolvendo diretrios (criar, renomear ou excluir uma pasta) e arquivos
(mover, copiar ou, at mesmo, excluir um arquivo);
FTP Task: tarefa utilizada no envio e/ou recebimento de arquivos via FTP;
Script Task: graas a esta task possvel a codificao de scripts
em .NET para a realizao de uma ou mais aes especficas;
Send Mail Task: permite o envio de uma mensagem de e-mail,
fazendo uso para isto do protocolo SMTP;
Web Service Task: aciona um mtodo definido em um Web
Service;
XML Task: tarefa utilizada no processamento de documentos
XML.
Dos componentes citados, as tasks Data Flow Task, Execute SQL
Task e Script Task correspondem, basicamente, aos controles cuja
utilizao mais comum em solues baseadas no Integration
Services.
Dentre os containers disponibilizados pelo Integration Services,
podem ser mencionados os seguintes componentes:
For Loop Container: permite a repetio de um conjunto de
tasks dentro de um package. As sucessivas iteraes dentro

deste controle so controladas por expresses atribudas a uma


propriedade chamada EvalExpression;
Foreach Loop Container: assim como o controle For Loop
Container, este container permite a repetio de uma srie de
tarefas por meio de iteraes. A diferena est no fato de que o
componente Foreach Loop Container funciona de uma maneira
similar instruo foreach em .NET, efetuando iteraes sobre
um conjunto de registros retornados de uma base de dados ou,
at mesmo, em uma lista de arquivos localizados em um diretrio
especfico;
Sequence Container: permite o agrupamento lgico de um
conjunto de tarefas relacionadas.
Para o package GeracaoCSVProdutos.dtsx sero adicionadas
duas tasks, conforme listado na Tabela 2. Alterar a propriedade
Name destes controles com um valor sugestivo uma boa prtica:
eventuais erros durante a execuo do package GeracaoCSVProdutos.dtsx a partir do SQL Server produziro informaes em
log; levando tal falto em considerao, uma clara identificao
do ponto em que ocorreu um problema facilitar na posterior
resoluo do mesmo.
Na Figura 14 possvel observar o fluxo principal do pacote
GeracaoCSVProdutos.dtsx, com as tasks que faro parte do mesmo
j adicionadas.
Tipo da Task

Valor da propriedade Name

Script Task

Script Task - Gerar nome do arquivo CSV

Data Flow Task

Data Flow Task - Gerar arquivo CSV

Tabela 2. Tasks a serem adicionadas no package GeracaoCSVProdutos.dtsx

Figura 14. Fluxo principal do package GeracaoCSVProdutos.dtsx


O Script Task que foi adicionado ao package GeracaoCSVProdutos.dtsx ir receber o caminho associado ao parmetro
pCaminhoGeracaoArquivosCSV. A partir disso ser gerado
um novo nome para o arquivo .csv que conter o catlogo de

Edio 110 .Net Magazine

43

Integration Services2012: implementando solues de ETL - Parte 1

produtos, com este valor sendo finalmente associado varivel


vNomeArquivoCSV.
A Figura 15 apresenta o componente Script Task devidamente
configurado. Sobre os itens preenchidos na janela Script Task
Editor, possvel destacar:
ScriptLanguage: indica a linguagem que ser empregada para a
implementao do cdigo associado ao controle Script Task. Alm
de C# (que estaremos utilizando neste exemplo), este componente
aceita ainda o uso de instrues escritas em VB.NET;
EntryPoint: indica o mtodo em .NET que ser executado quando
a task em questo for acionada. Por default criada uma operao
de nome Main, sendo este o ponto em que sero executadas as
instrues definidas para um controle Script Task;
ReadOnlyVariables: variveis ou parmetros que sero utilizados como parmetros de leitura. Caso se tente atribuir um valor
a algum dos itens informados nesta configurao, um erro ser
gerado em tempo de execuo;
ReadWriteVariables: neste local normalmente so definidas
variveis nas quais tambm ser possvel a atribuio de valores.
Os itens aqui definidos normalmente armazenam o resultado das
aes desencadeadas dentro do mtodo Main.

Para a codificao das aes que faro parte do controle Script


Task, acione a opo Edit Script. Uma tela como a que consta
na Figura 16 aparecer ento.
O cdigo que constar num componente Script far parte de
uma classe chamada ScriptMain, a qual baseada no tipo bsico
VSTARTScriptObjectModelBase (namespace Microsoft.SqlServer.
Dts.Tasks.ScriptTask). Essa ltima estrutura faz parte de um
mecanismo do .NET Framework conhecido como Visual Studio
Tools for Applications ou, simplesmente, VSTA (BOX 10). Dentro
do tipo ScriptMain existir, por sua vez, um mtodo Main, sendo
este o local em que acontecer as aes definidas para o controle
Script Task adicionado a um package.

Figura 16. Editando o cdigo de um controle Script Task


BOX 10. Visual Studio Tools for Applications
O Visual Studio Tools for Applications (VSTA) um conjunto de ferramentas da plataforma .NET
que pode ser utilizado em solues dos mais variados tipos, de forma a permitir a customizao de
funcionalidades pr-existentes ou, at mesmo, possibilitar a estenso das capacidades oferecidas
por tais recursos. Surgido ainda com o Visual Studio 2005, justamente este o mecanismo que torna
possvel o uso de instrues em .NET dentro de solues do Integration Services.

Figura 15. Configurando o controle Script Task


Nota
recomendvel o uso de prefixos como p e v para identificar, respectivamente, parmetros e
variveis. Essa prtica ajuda a evitar equvocos durante a manipulao destes recursos em controles
do tipo Script Task.
Nota
Para se configurar uma task dentro do Visual Studio necessrio apenas clicar duas vezes com o
mouse sobre este controle. Uma janela ento aparecer, com os principais elementos que podero
ser preenchidos para este componente (como no caso do Script Task adicionado ao package
GeracaoCSVProdutos.dtsx).

44 .Net Magazine Edio 110

Na Listagem 1 est o cdigo esperado para o mtodo Main do


controle Script Task. Quanto implementao desta operao,
necessrio destacar:
O uso do objeto associado propriedade Dts (linhas 4, 6 e 10), o
qual representa uma instncia do tipo ScriptObjectModel (namespace Microsoft.SqlServer.Dts.Tasks.ScriptTask). Esta referncia
serve de base para a manipulao de variveis e parmetros,
com isso acontecendo atravs da propriedade Variables, alm de
indicar se a execuo do mtodo Main aconteceu com sucesso ou
no (por meio da propriedade TaskResult);
Na linha 3 o contedo definido para o parmetro pCaminhoGeracaoArquivosCSV acessado, de forma a se determinar o
diretrio em que ocorrer a gravao do arquivo .csv com o
catlogo de produtos;

J na linha 6 a varivel vNomeArquivoCSV est sendo preenchida com o nome completo (incluindo diretrio) do arquivo com
informaes de produtos;
Por fim, o valor de enumeration ScriptResults.Success atribudo propriedade TaskResult do objeto Dts, indicando assim que
a execuo do cdigo definido para o controle Script Task teve
sucesso (no caso de uma eventual falha, seria utilizado o valor
ScriptResults.Failure).
Listagem 1. Mtodo Main com as instrues para gerao de um novo nome de
arquivo
01 public void Main()
02 {
03 string nomeArquivoCSV =
04
Dts.Variables[pCaminhoGeracaoArquivosCSV].Value.ToString() +
05
Produtos_{0}.csv;
06 Dts.Variables[vNomeArquivoCSV].Value =
07
String.Format(nomeArquivoCSV,
08
DateTime.Now.ToString(yyyy-MM-dd_HHmmss));
09
10 Dts.TaskResult = (int)ScriptResults.Success;
11 }

Finalizada a configurao do componente Script Task, o ltimo


passo antes de se concluir a implementao do package GeracaoCSVProdutos.dtsx ser a definio do fluxo associado ao controle
Data Flow Task (dentro da seo Data Flow). Ser a partir da
sequncia de aes configuradas nesta tarefa que acontecer a
leitura dos dados de produtos armazenados na base Northwind
e, finalmente, a gravao do catlogo sob a forma de um arquivo
com a extenso .csv.
O fluxo de dados definido para uma tarefa do tipo Data Flow
Task costuma envolver:
Uma fonte de origem (Source), de onde sero obtidos dados que
podem estar sujeitos a alguma forma de processamento;
O processamento de tais informaes, com provveis transformaes (reformatao de valores, concatenao de dois ou mais
dados etc.);
Uma estrutura de destino (Destination) que receber os dados
j transformados. Bancos de dados relacionais e arquivos so
algumas das possibilidades para este caso especfico.
Para o exemplo que envolve a construo do package GeracaoCSVProdutos.dtsx, estaro sendo utilizados apenas controles para
a manipulao de dados na origem e gravao num repositrio
de destino. Na prxima edio abordaremos alguns dos controles
que podero ser utilizados na transformao de dados.
Na Figura 17 possvel observar alguns dos controles disponveis para a configurao de um Data Flow Task. J a Tabela 3
apresenta alguns desses elementos, assim como a tecnologia
empregada pelos mesmos no processamento de informaes.
Ser preciso adicionar ao fluxo de dados do controle Data Flow
Task os controles listados na Tabela 4, modificando ainda o valor
da propriedade Name para esses itens.

Figura 17. Alguns dos controles utilizados na definio de um Data Flow


Origem

Destino

Tecnologia empregada

ADO NET Source

ADO NET Destination Drivers ADO.NET

Excel Source

Excel Destination

Planilhas do Microsoft Excel

Flat File Source

Flat File Destination

Arquivos de texto (delimitados por


caracteres, posies fixas)

ODBC Source

ODBC Destination

Drivers ODBC

OLE DB Source

OLE DB Destination

Driver OLE DB

Raw File Source

Raw File Destination

Arquivos binrios

Tabela 3. Alguns dos controles disponveis para a implementao de um Data Flow


Tipo do Controle

Valor da propriedade Name

ADO NET Source

ADO NET Source - Northwind

Flat File Destination

Flat File Destination - Arquivo CSV

Tabela 4. Controles a serem adicionados para o componente Data Flow Task


Na Figura 18 est a representao para o fluxo de dados que
resultar na gerao de um novo arquivo .csv contendo o catlogo
de produtos.
J as definies esperadas para o controle ADO NET Source
so apresentadas na Figura 19. A configurao da fonte de dados
requer o preenchimento dos seguintes itens na seo Connection
Manager da janela ADO.NET Source Editor:
ADO.NET connection manager: conexo do tipo ADO.NET
empregada no acesso a uma base de dados relacional (para este
exemplo ser a conexo connNorthwind criada anteriormente);

Edio 110 .Net Magazine

45

Integration Services2012: implementando solues de ETL - Parte 1

Data access mode: indica se um comando SQL ser executado


para a obteno dos dados de origem (opo SQL Command)
ou ainda, se tais informaes viro de uma tabela ou view que
pertena base para a qual o controle ADO NET Source est
apontando (opo Table or view). Para o package GeracaoCSVProdutos.dtsx ser utilizada uma query (Listagem 2) que relaciona
as tabelas Products (produtos), Categories (categorias) e Suppliers
(fornecedores) do banco Northwind.
Na seo Columns da janela ADO.NET Source Editor possvel observar as colunas que estaro disponveis para a gerao
do arquivo .csv de produtos (Figura 20).

Figura 18. Fluxo do componente Data Flow Task

Listagem 2. Query para a obteno de informaes sobre o catlogo de produtos


01 SELECT
02 CdProduto = P.ProductID,
03 NmProduto = P.ProductName,
04 VlPrecoUnitario = P.UnitPrice,
05 DsCategoria = C.CategoryName,
06 NmFornecedor = S.CompanyName
07 FROM dbo.Products P
08 INNER JOIN dbo.Categories C ON
09 C.CategoryID = P.CategoryID
10 INNER JOIN dbo.Suppliers S ON
11 S.SupplierID = P.SupplierID
12 WHERE P.Discontinued = 0
13 ORDER BY P.ProductID

Figura 20. Colunas geradas a partir do controle ADO NET Source


Concluindo a implementao do package GeracaoCSVProdutos
.dtsx, estaremos configurando agora o controle Flat File Destination. Na seo Connection Manager da janela Flat File Destination Editor efetuar os seguintes ajustes (Figura 21):
Selecionar a conexo connArquivoCSVProdutos em Flat File
connection manager;
Manter a opo Overwrite data in the file desmarcada, uma
vez que a cada execuo do pacote GeracaoCSVProdutos.dtsx um
novo arquivo .csv ser gerado;
Opcionalmente um cabealho para o arquivo .csv poder ser
definido ao se preencher o elemento Header (o que no o caso
para o exemplo aqui abordado).

Figura 19. Configurando o controle ADO.NET Source

46 .Net Magazine Edio 110

Na seo Mappings da janela Flat File Destination Editor


(Figura 22) sero realizados os mapeamentos entre as colunas
da instruo SQL definida no componente ADO NET Source e
os campos correspondentes do arquivo .csv de destino (os quais
foram configurados na conexo connArquivoCSVProdutos).
Finalizada a construo do package GeracaoCSVProdutos.
dtsx, estaremos executando este arquivo para efeitos de testes a

partir do Visual Studio 2012 (da mesma maneira que uma aplicao .NET convencional). To logo o IDE tenha concludo este
procedimento, marcaes em verde aparecero em cada task da
seo Control Flow, indicando que a gerao do arquivo .csv teve
sucesso (Figura 23).
Na seo Execution Results (ainda dentro do Visual Studio)
ser ainda visualizar detalhes da execuo do pacote GeracaoCSVProdutos.dtsx (Figura 24). Eventuais erros estaro indicados
nesse local, servindo assim para que desenvolvedores possam
diagnosticar e corrigir problemas existentes em um package.
Um arquivo .csv dever constar ento no diretrio C:\Devmedia\
TesteVisualStudio\, como indicado na Figura 25.

Na Figura 26 possvel visualizar o contedo do arquivo .csv


dentro do Bloco de Notas do Windows. J a Figura 27 exibe os
dados deste arquivo a partir do Microsoft Excel.

Executando um package localmente


Packages do Integration Services podem ser acionados a partir
de solues .NET dos mais variados tipos. Isto possvel graas

Figura 23. Package GeracaoCSVProdutos.dtsx executado com sucesso

Figura 21. Configurando o controle Flat File Destination

Figura 24. Visualizando detalhes da execuo do package GeracaoCSVProdutos.dtsx

Figura 22. Mapeamentos das colunas empregadas na gerao do arquivo .csv

Figura 25. Arquivo .csv gerado aps a execuo do package GeracaoCSVProdutos.dtsx


Edio 110 .Net Magazine

47

Integration Services2012: implementando solues de ETL - Parte 1

aos recursos disponibilizados pela biblioteca Microsoft.SqlServer.ManagedDTS.dll, a qual permite que aplicaes Windows
Forms, Windows Service, ASP.NET e, at mesmo, Web Services
executem arquivos .dtsx sem maiores dificuldades.
A fim de demonstrar como este procedimento pode ser implementado em projetos .NET, estaremos criando uma Console Application chamada TesteIntegration01.ExecucaoLocalPackage.

Figura 26. Arquivo .csv sendo visualizado a partir do Bloco de Notas

Figura 27. Arquivo .csv sendo visualizado a partir do Microsoft Excel


Nota
A biblioteca Microsoft.SQLServer.ManagedDTS.dll pode ser encontrada no diretrio C:\Program Files
(x86)\Microsoft SQL Server\110\SDK\Assemblies\.

Listagem 3. Arquivo app.config do projeto TesteIntegration01.ExecucaoLocalPackage


01 <?xml version=1.0 encoding=utf-8 ?>
02 <configuration>
03 <appSettings>
04 <add key=CaminhoPackageGeracaoCSVProdutos
05
value=... />
06 <add key=CaminhoGeracaoArquivosCSV
07
value=C:\Devmedia\TesteAplicacaoDotNet\ />
08 </appSettings>
09 </configuration>

Na Listagem 4 est a definio da classe Program. Quanto


estrutura deste tipo possvel observar:
Inicialmente criada uma instncia do tipo Application (namespace Microsoft.SqlServer.Dts.Runtime), sendo que esta referncia
servir de base para o acesso a packages do Integration Services
(linha 16);
O mtodo LoadPackage acionado a partir do objeto associado
varivel de nome appSSIS (linha 17), devolvendo como resultado uma instncia da classe Package (namespace Microsoft.
SqlServer.Dts.Runtime). Esta operao recebe como parmetros o
caminho em que se encontra o package GeracaoCSVProdutos.dtsx
e, opcionalmente, uma referncia baseada na interface IDTSEvents
(namespace Microsoft.SqlServer.Dts.Runtime);
O parmetro pCaminhoGeracaoArquivosCSV do package
GeracaoCSVProdutos.dtsx est sendo preenchido atravs da
propriedade Parameters (linha 21), a qual parte integrante do
objeto representado pela varivel package. Esta ao substitui o
valor definido anteriormente no package pelo caminho indicado
no arquivo app.config;
A execuo do package GeracaoCSVProdutos.dtsx iniciada
ao se invocar o mtodo Execute pertencente instncia do tipo
Package (linha 28). O resultado disto ser um dos valores previstos
para o enumeration (namespace Microsoft.SqlServer.Dts.Runtime). Em caso de sucesso, a operao Execute retornar o valor
DTSExecResult.Success, ao passo que o valor DTSExecResult.
Failure corresponder a um erro durante o processamento.
Se a execuo da aplicao TesteIntegration01.ExecucaoLocalPackage ocorrer sem falhas (Figura 28), um arquivo .csv ser gerado
no diretrio especificado na seo appSettings do arquivo app.
config (Figura 29).

Efetuando o deploy de um projeto do Integration Services


Na Listagem 3 est o arquivo app.config com as configuraes
esperadas para este projeto:
No item CaminhoPackageGeracaoCSVProdutos foi definido o
caminho em que se encontra o pacote a ser executado (no caso o
package GeracaoCSVProdutos.dtsx definido na seo anterior);
J para o item CaminhoGeracaoArquivosCSV, informe o
diretrio em que sero criados os arquivos .csv de produtos
quando a aplicao aqui descrita for executada.

48 .Net Magazine Edio 110

Desenvolver solues para o Integration Services envolver,


quase que invariavelmente, a publicao de packages em um
servidor SQL Server. Dentre os motivos que contribuem para a
escolha por esse ambiente esto a possibilidade de se executar de
maneira programtica Jobs que acionaro um ou mais packages,
a prpria facilidade em se implementar esse tipo de alternativa (a
partir de uma interface grfica e sem a necessidade de construo
de aplicaes), alm um mecanismo de log que permite a anlise
de erros ocorridos durante o processamento de tais Jobs.

Listagem 4. Classe Program (projeto TesteIntegration01.ExecucaoLocalPackage)


01 using System;
02 using System.Collections.Generic;
03 using System.Linq;
04 using System.Text;
05 using System.Configuration;
06 using Microsoft.SqlServer.Dts.Runtime;
07
08 namespace TesteIntegration01.ExecucaoLocalPackage
09 {
10 class Program
11 {
12
static void Main(string[] args)
13
{
14
Console.WriteLine(
15
Carregando o package GeracaoCSVProdutos.dtsx...);
16
Application appSSIS = new Application();
17
Package package = appSSIS.LoadPackage(
18
ConfigurationManager
19
.AppSettings[CaminhoPackageGeracaoCSVProdutos],
20
null);

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
}
39 }
40 }

package.Parameters[pCaminhoGeracaoArquivosCSV].Value =
ConfigurationManager
.AppSettings[CaminhoGeracaoArquivosCSV];
Console.WriteLine(
Executando localmente o package +
GeracaoCSVProdutos.dtsx...);
DTSExecResult resultado = package.Execute();
Console.WriteLine(
Resultado da execuo do package +
GeracaoCSVProdutos.dtsx: +
resultado.ToString());
Console.Write(
Pressione qualquer tecla para +
encerrar esta aplicao...);
Console.ReadKey();

BOX 11. O banco de dados MSDB

Figura 28. Executando a aplicao TesteIntegration01.ExecucaoLocalPackage

Figura 29. Arquivo .csv gerado aps a execuo do projeto TesteIntegration01.ExecucaoLocalPackage


Antes do lanamento da verso 2012 do SQL Server, o deployment
de aplicaes do Integration Services costumava ser uma tarefa
rdua para desenvolvedores familiarizados com esta tecnologia:
O Visual Studio no dispunha de nenhuma funcionalidade que
permitisse de forma direta o deployment de arquivos .dtsx em
um servidor SQL Server;
Um arquivo de manifesto precisava ento ser criado atravs do
Visual Studio e executado posteriormente, promovendo com isto
a instalao dos packages num determinado servidor;
A nica forma de modificar as configuraes esperadas para
um ou mais packages era atravs do uso de documentos XML
criados especificamente para esse fim. Outra possibilidade
(bem mais trabalhosa) seria alterar manualmente os diferentes
elementos em cada pacote antes de se proceder com a publicao
dos mesmos. Diante desse cenrio, no difcil de imaginar que
todo este processo estava sujeito a falhas, sobretudo em solues
que envolvessem o uso de inmeros packages;
Os packages poderiam ser publicados no banco de dados MSDB
(BOX 11) ou ainda, em um diretrio acessvel para o servidor SQL
Server responsvel pela execuo dos mesmos.

A base MSDB um dos bancos de dados de sistema do SQL Server, sendo utilizada por este SGDB
em operaes que envolvam o backup/restore de outras bases, envio de e-mail, agendamento e
execuo de Jobs, armazenamento de packages do Integration Services (sobretudo em releases
anteriores verso 2012), dentre outras funcionalidades.

Este mtodo para a implantao de solues baseadas no Integration Services conhecido como Package Deployment Model
e, embora ainda seja possvel a utilizao desta alternativa, no
se recomenda mais que isso seja feito em conjunto com a verso
2012. Neste novo release do SQL Server foi disponibilizado um
modelo mais simplificado e flexvel para o deployment de aplicaes do Integration Services: trata-se do mecanismo conhecido
como Project Deployment Model.
Quanto ao funcionamento do modelo Project Deployment Model, possvel destacar:
O deployment de packages acontece agora a partir do Visual
Studio, atravs de uma funcionalidade que dispensa assim o uso
dos arquivos de manifesto requeridos pelo mtodo anterior;
Parmetros substituram os arquivos XML utilizados na manipulao de configuraes, procurando com isto facilitar o
gerenciamento das informaes necessrias ao funcionamento
de aplicaes do Integration Services;
Ser num repositrio chamado de catlogo que acontecer a publicao de projetos do Integration Services. Para cada instncia de
um servidor SQL Server poder ser criado somente um catlogo,
com este recurso fazendo uso do mecanismo conhecido como CLR
Integration (BOX 12) para a execuo de packages.
Nesta seo demonstremos como realizar o deploy de uma
aplicao do Integration Services a partir do Visual Studio. Alm
deste IDE, estaremos fazendo uso ainda do Microsoft SQL Server
Management Studio 2012.

Edio 110 .Net Magazine

49

Integration Services2012: implementando solues de ETL - Parte 1

BOX 12. CLR Integration


O recurso conhecido como CLR Integration foi introduzido ainda na verso 2005 do SQL Server,
permitindo a integrao de estruturas deste SGBD ao Common Language Runtime (CLR) do .NET
Framework. Este mecanismo permite, dentre outras coisas, que objetos tpicos de bases de dados
relacionais como stored procedures, functions e triggers sejam implementados em .NET.

Antes de proceder com a implantao de uma soluo do Integration Services, ser necessrio configurar o ambiente para a
execuo deste servio (caso isto ainda no tenha sido feito).
O primeiro passo consiste em habilitar o uso do Common Language Runtime da plataforma .NET. Na Listagem 5 apresentado
um script que ativa este mecanismo, utilizando para isto as rotinas
SP_CONFIGURE e RECONFIGURE.
Com a integrao junto ao CLR ativada, estaremos prosseguindo
agora com a criao do catlogo que armazenar os projetos do
Integration Services. Selecione dentro do SQL Server Management
Studio a opo Create Catalog..., que estar disponvel a partir
do menu de contexto para o item Integration Services Catalogs
(Figura 30).
Listagem 5. Habilitando o uso do CLR num servidor SQL Server
01 sp_configure clr enabled, 1
02 go
03 reconfigure
04 go

Figura 31. Criando o catlogo SSISDB


Importante ressaltar que um banco de dados (tambm chamado
SSISDB) ser gerado como resultado da criao de um catlogo
em uma instncia do SQL Server.
A fim de possibilitar uma melhor organizao dos diferentes
projetos que faro parte do catlogo SSISDB, pastas podero ser
criadas dentro deste repositrio. Quando utilizada (Figura 32), a
funcionalidade Create Folder... (acionada a partir do menu de
contexto do catlogo SSISDB) permite a separao de solues do
Integration Services em conformidade com algum critrio especfico. Para os exemplos abordados nesta srie de artigos, estaremos
criando uma pasta chamada Testes (Figura 33).

Figura 30. Acionando a opo para criao de um novo catlogo


Aparecer ento a janela Create Catalog (Figura 31) em
que constaro algumas opes referentes criao do catlogo
SSISDB:
Quando marcado, o item Enable automatic execution of
Integration Services stored procedure at SQL Server startup
determinar, logo aps a reinicializao do SGBD, a execuo
automtica de uma rotina responsvel por corrigir o status de
packages que estavam em processamento quando o servidor em
questo deixou de operar;
Uma senha que serve de base para a proteo da chave de criptografia empregada pelo catlogo SSISDB.

50 .Net Magazine Edio 110

Figura 32. Acionando a opo para a criao de pastas a partir do catlog SSISDB
Neste momento j estaremos com o ambiente devidamente
configurado para a publicao da aplicao TesteIntegration01.
SSIS, conforme pode ser observado na Figura 34.
Para iniciar o processo de publicao do projeto TesteIntegration01.SSIS, acione a opo Deploy a partir do menu de
contexto desta aplicao no Visual Studio (Figura 35). Ser exibida neste instante a janela Integration Services Deployment
Wizard (Figura 36).

Figura 33. Criando a pasta Testes para o catlogo SSISDB

Figura 36. A janela Integration Services Deployment Wizard

Figura 34. O catlogo SSISDB j configurado para a publicao de aplicaes

Figura 37. Selecionando o local em que o projeto TesteIntegration01.SSIS ser publicado

Figura 35. Acionando a opo para o deploy da aplicao TesteIntegration01.SSIS


Na seo Select Destination, informe o servidor e o caminho
configurado anteriormente para a publicao da aplicao TesteIntegration01.SSIS (Figura 37).
J na seo Review aparecero detalhes referentes ao projeto
que ser publicado, assim como o caminho em que este processo

acontecer (Figura 38). Acionar a opo Deploy, para com isto


concluir esse processo.
Caso no ocorram problemas, ser exibida uma confirmao de
que o projeto TesteIntegration01.SSIS foi publicado no catlogo
SSIDB abaixo da pasta Testes (Figura 39).
Retornando ao SQL Server Management Studio, ser possvel
observar o projeto TesteIntegration01.SSIS (incluindo nisto o package GeracaoCSVProdutos.dtsx) logo abaixo da pasta Testes
do catlogo SSISDB (Figura 40).

Edio 110 .Net Magazine

51

Integration Services2012: implementando solues de ETL - Parte 1

processo de implantao desta soluo tenha se encerrado. Uma


das formas mais comuns para a execuo de solues do Integration Services consiste na criao de Jobs em uma instncia do SQL
Server, com tais estruturas sendo acionadas de forma automtica
e periodicamente atravs do mecanismo conhecido como servio
SQL Server Agent (BOX 13).
BOX 13. SQL Server Agent
O SQL Server Agent mais um dos servios que fazem parte do SQL Server, fornecendo a estrutura
necessria para a criao e o agendamento da execuo de tarefas conhecidas como Jobs. Quanto
forma como os Jobs so definidos, este tipo de estrutura formado de um ou mais passos (steps),
com estes ltimos podendo executar uma instruo SQL, um stored procedure ou, at mesmo,
acionar um package do Integration Services.

Figura 38. Selecionando o local em que o projeto TesteIntegration01.SSIS ser publicado

Figura 40. Projeto TesteIntegration01.SSIS j publicado no servidor SQL Server

Figura 39. Publicao com sucesso do projeto TesteIntegration01.SSIS


Os valores dos parmetros e conexes utilizados pela aplicao
podem ser modificados acionando a opo Configure..., a partir
do menu de contexto da aplicao TesteIntegration01.SSIS. Altere
o valor do parmetro pCaminhoGeracaoArquivosCSV para C:\
Devmedia\TesteSQLServer\ (Figura 41); este caminho dever
existir fisicamente, a fim de que possamos executar com sucesso
os outros testes descritos mais adiante.

Criando um Job para a Execuo de um projeto do Integration


Services
A simples publicao da aplicao TesteIntegration01.SSIS
num servidor SQL Server no significa, necessariamente, que o

52 .Net Magazine Edio 110

Figura 41. Configurando a aplicao TesteIntegration01.SSIS a partir do servidor SQL Server


Nesta seo ser demonstrado de que maneira um Job pode ser
criado para a execuo diria do projeto TesteIntegration01.SSIS.
O primeiro passo para isto ser acessar (Figura 42), a partir do
elemento SQL Server Agent no utilitrio Management Studio, a
opo New Job... (acionando para isto o menu de contexto para
o item Jobs).
Dentro da janela New Job aconter a configurao de um
Job chamado Job TesteIntegration01.SSIS. Na seo General
sero preenchidas informaes para a identificao deste novo
Job (Figura 43).

Figura 42. Acionando a opo para a criao de um novo Job

Figura 44. Configurando os steps que faro parte de um Job

Figura 43. Criando o job TesteIntegration01.SSIS

Figura 45. Configurando o step que acionar o package GeracaoCSVProdutos.dtsx

Crie dentro da seo Steps (Figura 44) o passo que ir acionar o package GeracaoCSVProdutos.dtsx. Na janela New Job
Step (Figura 45), preencha as seguintes configuraes:
Step name: identificao de um passo que far parte de um Job.
Informe o valor Acionar package GeracaoCSVProdutos.dtsx;
Type: tipo de ao a ser executada. O valor SQL Server Integration Services Packages permite invocar um pacote .dtsx
(que pode ser ter sido previamente publicado num servidor
SQL Server ou ainda, estar localizado em algum diretrio do
servidor);
Seo Package: informar o servidor em que se encontra
instalado o package GeracaoCSVProdutos.dtsx, assim como o
caminho deste dentro do catlogo SSISDB.

J na seo Schedules (Figura 46), crie o agendamento para a


execuo do pacote GeracaoCSVProdutos.dtsx. A partir da janela
New Job Schedule (Figura 47), realize o preenchimento das
seguintes configuraes:
Name: texto que ir identificar o agendamento. Informe o valor
Agendamento - package GeracaoCSVProdutos.dtsx;
Schedule type: selecione a opo Recurring, indicando com
isto que o Job ser executado continuamente;
Frequency: selecione a opo Daily (execuo diria) para o item
Occurs e o valor 1 para Recurs every (intervalos de um dia);
Daily frequency: defina em Occurs every que a execuo
acontecer a cada 24 horas, sendo que isso ser feito entre 11:45:00
e 12:00:00;
Duration: certificar-se de que foi marcada a opo No end date.

Edio 110 .Net Magazine

53

Integration Services2012: implementando solues de ETL - Parte 1

criando para isto a Console Application TesteIntegration01.ExecucaoRemotaPackage.


Este projeto far uso das seguintes bibliotecas:
Microsoft.SqlServer.Management.IntegrationServices.dll;
Microsoft.SqlServer.ConnectionInfo.dll;
Microsoft.SqlServer.Management.Sdk.Sfc.dll;
Microsoft.SqlServer.Smo.dll.

Figura 46. Configurando o agendamento de um Job

Figura 48. Job j criado no SQL Server Agent

Figura 49. Arquivo .csv gerado aps a execuo do Job

Figura 47. Preenchendo as configuraes de agendamento de um Job


Na Figura 48 possvel visualizar o Job que acionar o package
GeracaoCSVProdutos.dtsx aps a criao do mesmo dentro do
SQL Server Agent. Aps a primeira execuo desta rotina, um
arquivo .csv ter sido gerado no diretrio C:\Devmedia\TesteSQLServer (Figura 49).
Todo job executado a partir do SQL Server Agent gera informaes de log que podero vir a ser consultadas posteriormente.
Na Figura 50 apresentando um exemplo disto, em que possvel
observar a execuo com sucesso desta rotina.

Executando um package remotamente


Packages publicados em um catlogo do Integration Services
tambm podem ser acessados por aplicaes .NET de forma
remota. Nesta seo apresentaremos de que forma isto feito,

54 .Net Magazine Edio 110

Figura 50. Consultando o log de um Job


A execuo remota de um package tem como pr-requisito a
realizao de uma conexo junto ao servidor em que essa estrutura
foi publicada. Por esse motivo, ser preciso incluir no arquivo app.
config uma Connection String que aponte para a base SSISDB

(gerada juntamente com o catlogo de mesmo nome). A Listagem 6


apresenta o contedo do arquivo app.config com as configuraes
esperadas para este projeto de testes.
J na Listagem 7 est a implementao da classe Program.
Quanto s instrues para se acessar remotamente um package
previamente publicado em um servidor, merece ser destacado:
As classes IntegrationServices, Catalog, CatalogFolder, ProjectInfo e PackageInfo esto sendo utilizadas ao longo do mtodo
Main, sendo que todas essas estruturas pertencem ao namespace
Microsoft.SqlServer.Management.IntegrationServices.
Uma instncia da classe IntegrationServices gerada (linha 17),
recebendo como parmetro uma referncia baseada no tipo
SqlConnection (namespace System.Data.SqlClient). Ser o objeto
associado varivel de nome integration que servir de base
para o acesso aos packages e projetos em uma determinada instncia do SQL Server;
Utilizando a referncia da classe IntegrationServices obtida
anteriormente, uma instncia da classe Catalog ser atribuda
varivel catalogo (linha 21);
O prximo passo agora ser a obteno de uma instncia da
classe CatalogFolder, a qual permitir o acesso a informaes da
pasta Testes dentro do catlogo SSISDB (linha 23);
A partir da varivel pasta ser retornada uma instncia do tipo
ProjectInfo (linha 25);
Por fim, atravs da instncia obtida no passo anterior ser associado um objeto do tipo PackageInfo varivel package. Ser
com esta ltima referncia que iniciaremos a execuo do package,
invocando para isto o mtodo Execute (linha 33);
A operao Execute (definida na classe PackageInfo) est recebendo dois parmetros. O primeiro deles um flag que indica
se o package ser processado como se estivesse num ambiente
de 32 bits (mesmo se o servidor SQL se basear numa arquitetura de 64 bits); j o segundo parmetro uma instncia do tipo
EnvironmentReference (namespace Microsoft.SqlServer.Management.IntegrationServices), sendo que a passagem de tal referncia
opcional.
Nota
Com exceo da biblioteca Microsoft.SqlServer.Management.IntegrationServices (normalmente
localizada em C:\Windows\assembly\GAC_MSIL\), todas as demais DLLs que contam com recursos do
SQL Server utilizados pelo projeto TesteIntegration01.ExecucaoRemotaPackage podem ser encontradas
a partir do diretrio c:\Program Files (x86)\Microsoft SQL Server\110\SDK\Assemblies\.

Caso a aplicao TesteIntegration01.ExecucaoRemotaPackage


seja executada sem falhas (Figura 51), um novo arquivo .csv constar no diretrio C:\Devmedia\TesteSQLServer\ (Figura 52).

Executando remotamente um package a partir de um Job


Como ltimo exemplo de execuo remota de um package, estaremos criando o projeto TesteIntegration01.ExecucaoRemotaJob.
Isso acontecer atravs de uma chamada stored procedure SP_
START_JOB, que faz parte do banco de dados de sistema MSDB.

Listagem 6. Arquivo app.config do projeto TesteIntegration01.ExecucaoRemotaPackage


01 <?xml version=1.0 encoding=utf-8 ?>
02 <configuration>
03 <connectionStrings>
04 <add name=SSISDB
05
connectionString=
06
Data Source=.;Initial Catalog=SSISDB;Integrated Security=SSPI;
07
providerName=System.Data.SqlClient />
08 </connectionStrings>
09 </configuration>
Listagem 7. Classe Program (projeto TesteIntegration01.ExecucaoRemotaPackage)
01 using System;
02 using System.Collections.Generic;
03 using System.Linq;
04 using System.Text;
05 using System.Configuration;
06 using System.Data.SqlClient;
07 using Microsoft.SqlServer.Management.IntegrationServices;
08
09 namespace TesteIntegration01.ExecucaoRemotaPackage
10 {
11 class Program
12 {
13
static void Main(string[] args)
14
{
15
Console.WriteLine(
16
Carregando o package GeracaoCSVProdutos.dtsx...);
17
IntegrationServices integration =
18
new IntegrationServices(new SqlConnection(
19
ConfigurationManager.ConnectionStrings[SSISDB]
20
.ConnectionString));
21
Catalog catalogo =
22
integration.Catalogs[SSISDB];
23
CatalogFolder pasta =
24
catalogo.Folders[Testes];
25
ProjectInfo projeto =
26
pasta.Projects[TesteIntegration01.SSIS];
27
PackageInfo package =
28
projeto.Packages[GeracaoCSVProdutos.dtsx];
29
30
Console.WriteLine(
31
Executando remotamente o package +
32
GeracaoCSVProdutos.dtsx...);
33
package.Execute(true, null);
34
35
Console.Write(
36
Pressione qualquer tecla para +
37
encerrar esta aplicao...);
38
Console.ReadKey();
39
}
40 }
41 }

Na Listagem 8 est o arquivo app.config para esta aplicao de


testes, j constando no mesmo a string de conexo para acesso
base MSDB.
J na Listagem 9 est a definio da classe Program. Quanto
forma como o mtodo Main foi implementado, possvel observar:
A partir da varivel conexao (instncia do tipo System.Data.
SqlClient.SqlConnection) estabelecida uma conexo com a base
de dados MSDB (linha 15);

Edio 110 .Net Magazine

55

Integration Services2012: implementando solues de ETL - Parte 1

A referncia cmd (objeto do tipo System.Data.SqlClient.SqlCommand) invocar o stored procedure SP_START_JOB atravs
de uma chamada ao mtodo ExecuteNonQuery (linha 34), iniciando assim a execuo da rotina Job TesteIntegration01.SSIS.
Se no ocorrerem falhas durante a execuo do projeto (Figura 53),
um novo arquivo .csv ter sido gerado no diretrio C:\Devmedia\
TesteSQLServer (Figura 54).

Figura 51. Executando a aplicao TesteIntegration01.ExecucaoRemotaPackage

Figura 52. Arquivo .csv gerado aps a execuo do projeto TesteIntegration01.ExecucaoRemotaPackage

Figura 53. Executando a aplicao TesteIntegration01.ExecucaoRemotaJob

Figura 54. Arquivo .csv gerado aps a execuo do projeto TesteIntegration01.ExecucaoRemotaJob


Listagem 8. Arquivo app.config do projeto TesteIntegration01.ExecucaoRemotaJob
01 <?xml version=1.0 encoding=utf-8 ?>
02 <configuration>
03 <connectionStrings>
04 <add name=MSDB
05
connectionString=
06
Data Source=.;Initial Catalog=msdb;Integrated Security=SSPI;
07
providerName=System.Data.SqlClient />
08 </connectionStrings>
09 </configuration>

56 .Net Magazine Edio 110

Listagem 9. Classe Program (projeto TesteIntegration01.ExecucaoRemotaJob)


01 using System;
02 using System.Collections.Generic;
03 using System.Linq;
04 using System.Text;
05 using System.Configuration;
06 using System.Data;
07 using System.Data.SqlClient;
08
09 namespace TesteIntegration01.ExecucaoRemotaJob
10 {
11 class Program
12 {
13
static void Main(string[] args)
14
{
15
using (SqlConnection conexao =
16
new SqlConnection(ConfigurationManager
17
.ConnectionStrings[MSDB]
18
.ConnectionString))
19
{
20
SqlCommand cmd = conexao.CreateCommand();
21
cmd.CommandText = SP_START_JOB;
22
cmd.CommandType = CommandType.StoredProcedure;
23
24
cmd.Parameters.Add(@JOB_NAME, SqlDbType.VarChar)
25
.Value = Job TesteIntegration01.SSIS;
26
27
Console.WriteLine(
28
Acessando a base de dados MSDB...);
29
conexao.Open();
30
31
Console.WriteLine(
32
Executando remotamente o Job que +
33
aciona o package GeracaoCSVProdutos.dtsx...);
34
cmd.ExecuteNonQuery();
35
36
conexao.Close();
37
}
38
39
Console.Write(
40
Pressione qualquer tecla para +
41
encerrar esta aplicao...);
42
Console.ReadKey();
43
}
44 }
45 }

Concluso
Este artigo procurou fornecer uma viso geral a respeito do Integration Services, enfatizando como tal servio pode ser empregado
na integrao entre diferentes sistemas. Por contar com um escopo
bastante abrangente no que se refere manipulao de informaes, esta ferramenta pode se revelar como um instrumento de
grande valia e flexibilidade nos mais variados contextos.
Dentre os cenrios mais comuns de uso do Integration Services, possvel destacar situaes nas quais o processamento
de um grande volume de informaes requer um bom nvel de
desempenho. importante ressaltar que esta nfase em questes
envolvendo performance uma preocupao central em grandes

organizaes, representando um fator crtico para o sucesso em


muitos ramos de negcio.
Embora parte integrante do SQL Server, o Integration Services
pode ser utilizado em conjunto com outros tipos de bancos relacionais (como Oracle, DB2, Postgre, Firebird), j que o mesmo
conta com suporte a mecanismos de acesso a dados como OLE DB,
ODBC e ADO.NET. Outras fontes como arquivos texto, planilhas
do Excel, documentos XML e Web Services tambm podem ser
utilizadas em projetos do Integration Services.

Autor
Renato Jos Groffe
renato.groffe@yahoo.com.br - http://www.devmedia.com.br/
renatogroffe
Atua como consultor em atividades voltadas ao desenvolvimento de softwares h mais de 10 anos. Bacharel em Sistemas de
Informao, com especializao em Engenharia de Software. Microsoft
Certified Technology Specialist (Web, WCF, Distributed Applications, ADO.NET, Windows
Forms), Microsoft Specialist (HTML5 with JavaScript and CSS3, Developing ASP.NET
MVC 4 Web Applications), Oracle Certified Associate (PL/SQL), Sun Certified (SCJP,
SCWCD), ITIL Foundation V2, Cobit 4.1 Foundation.

Links:
How to: Install Sample Databases
http://msdn.microsoft.com/en-us/library/vstudio/8b6y4c7s.aspx
Integration Services Programming Overview
http://technet.microsoft.com/en-us/library/ms403344.aspx
Microsoft SQL Server Data Tools - Business Intelligence for Visual Studio 2012
http://www.microsoft.com/en-us/download/details.aspx?id=36843
SQL Server Integration Services
http://technet.microsoft.com/en-us/library/ms141026.aspx
Whats New (Integration Services - SQL Server 2012)
http://technet.microsoft.com/en-us/library/bb522534.aspx

Voc gostou deste artigo?


D seu voto em www.devmedia.com.br/netmagazine/feedback
Ajude-nos a manter a qualidade da revista!

Edio 110 .Net Magazine

57

Criando uma aplicao para conexes remotas

Criando uma aplicao


para conexes remotas
Como criar uma aplicao cliente em C# que se
conecta a um servidor VNC remoto

utilizao de vrios computadores conectados em rede acabou atraindo diversos novos


servios que auxiliam o compartilhamento e
acesso a recursos. Um dos servios mais populares
representado pela categoria de softwares que permite
o compartilhamento da tela (screen sharing) e que possibilita o acesso e controle remoto da rea de trabalho
(desktop) de um computador.
As principais tecnologias para permitir o compartilhamento e acesso remoto interface grfica de um
sistema operacional trabalham com o conceito de cliente/
servidor, onde um computador servidor (o host) executa
um servio que permitir clientes (clients) remotos acessarem o desktop. O compartilhamento e o acesso remoto
so realizados atravs da transferncia da imagem (tela)
do host para o cliente e do envio das interaes do mouse
e teclado no cliente para o servidor. Dentre os softwares
existentes para trabalhar com estas tecnologias podemos
destacar o VNC, que a sigla utilizada para representar
as implementaes de cdigo livre que se baseiam no
uso do protocolo RFB.
A utilizao de ferramentas de compartilhamento de
desktop permite diversas aplicaes, como a possibilidade de suporte remoto e resoluo de problemas com
o acompanhamento do usurio, facilitar o processo de
deploy de componentes em servidores remotos, treinamento de usurios e monitoria de aes. Contudo,
tais usos da tecnologia de compartilhamento de tela
possuem implicaes relevantes para a privacidade e
segurana dos usurios.
Baseado nesse contexto, este artigo apresentar como
construir uma aplicao console em C# que acessa remotamente um servidor VNC com a biblioteca VNCSharp.
Esta aplicao pode ser utilizada para automatizar a
execuo de tarefas administrativas (aplicao de service
pack, atualizao de configuraes, etc), treinamento de

58 .Net Magazine Edio 110

Resumo DevMan
Porque esse artigo til:
A utilizao de servios de compartilhamento de tela e controle
remoto til em situaes onde preciso automatizar uma tarefa
que deve ser realizada diretamente na interface grfica do sistema
operacional. Esta automao pode ser realizada atravs do envio de
comandos (teclas) e eventos do mouse para diversos computadores
remotos que tiverem um servidor VNC instalado. Este artigo mostra
exemplos de como enviar caracteres e eventos do mouse para um
servidor VNC remoto atravs de uma aplicao cliente desenvolvida
em linguagem C#.

usurios, colaborao, captura de tela e outras. A partir do projeto


de exemplo descrito neste artigo o leitor poder integrar as bibliotecas de acesso a um servidor VNC e montar suas prprias solues
que envolvam o acesso a computadores remotos atravs de um
cliente VNC que permite o envio de teclas e eventos do mouse.

O VNC e tecnologias de compartilhamento de tela


As tecnologias para o compartilhamento de tela e o acesso
remoto j existem h um bom tempo. Contudo, apenas recentemente estas ferramentas comearam a serem utilizadas em larga
escala, principalmente devido ao aumento da largura de banda
da conexo entre computadores.
Possuir uma largura de banda adequada necessrio para a utilizao de tecnologias de compartilhamento de tela, uma vez que
necessrio transmitir frequentemente uma grande quantidade de
bytes associada tela do servidor remoto para os clientes. Apesar
de existirem tcnicas de compactao e reduo de informaes
necessrias para o compartilhamento de tela, ainda hoje esta
tecnologia requer uma conexo confivel, constante e adequada
entre o cliente e o servidor.
A definio de como a tela do servidor ser transmitida para os
clientes e como os eventos de mouse e teclado do cliente devem

ser transmitidos para o servidor detalhada no protocolo utilizado. Atualmente existem diversos protocolos empregados por
servidores de compartilhamento de tela, como o protocolo RDP
(Remote Desktop Connection), utilizado pelo servio Terminal
Services da Microsoft, e o protocolo RFB (Remote Framebuffer),
que empregado nos servidores de cdigo livre representados
pela sigla VNC (Virtual Network Connection). Este artigo se concentrar na utilizao do VNC devido facilidade de download,
instalao e execuo. Tambm se destaca a possibilidade de
criao de clientes VNC graas s bibliotecas de cdigo aberto
em C# existentes.
Antes de comearmos a detalhar como vamos criar uma aplicao cliente que acessa remotamente um servidor VNC, preciso
fazer a instalao do servidor e testar a conexo. Dentre as opes
gratuitas disponveis recomenda-se o RealVNC ou o TightVNC
(veja na seo Links). Estes dois softwares possuem pacotes para
download que contm tanto o servidor como ferramentas cliente
para as plataformas Windows, Mac OS e Linux.
Os leitores que desejarem executar os cdigos fontes apresentados neste artigo devem possuir um servidor VNC instalado
e configurado. Executar esta instalao simples e no requer
muitos passos, apesar de serem necessrios privilgios administrativos no computador e a eventual liberao de portas de
comunicao em um firewall. Uma vez que o servidor j esteja
instalado preciso saber qual o endereo IP (ou nome do host),
a porta utilizada (geralmente 5900) e definir uma senha para
controlar o acesso remoto. O protocolo VNC utiliza o tipo de
conexo TCP e, por isso, necessria uma conexo constante e
com uma boa qualidade para que o modo de interao remoto e
visualizao sejam adequados.
A partir do momento em que o servidor VNC est instalado
e com estas informaes em mos (endereo do host, porta e
senha), recomenda-se utilizar um segundo computador, ou seja,
um computador diferente daquele que possui o servidor VNC, e
testar a conexo remota com a ferramenta cliente disponibilizada
junto com o RealVNC ou o TightVNC. Uma vez que a conexo
esteja estabelecida, pode-se controlar remotamente o computador
que possui o servidor VNC instalado e interagir com o sistema
operacional como se o usurio estivesse fisicamente em frente
ao computador.
Um servidor VNC pode ser executado como um servio que
executado em background, isto , sem exigir interao com o
usurio. Desta maneira, quando o sistema operacional for iniciado o servio VNC iniciado junto e, a partir desde momento,
o servidor pode receber conexes remotas. Em geral, os servios
que trabalham desta forma possuem suas permisses limitadas
ao usurio do sistema operacional associado ao servio. Contudo,
um usurio remoto que se conecta no servidor pode realizar um
logon com qualquer usurio (fornecendo um login e senha do
sistema operacional) e obter o acesso desejado. Esta caracterstica
no uma falha de segurana, pois o que o servio VNC proporciona um acesso ao computador: se j houver algum usurio
logado, o servio VNC vai fornecer acesso ao computador como

se fosse o usurio. Se o computador estiver bloqueado ou pedindo


credenciais pra realizar o logon, o usurio remoto deve fornecer
o login e senha como se estive em frente ao computador.
importante destacar que o servio de compartilhamento de tela
proporcionado pelo VNC no requer um login. Contudo, opcionalmente possvel configurar apenas senha de acesso ao servidor
VNC. Uma vez que se tenha acessado o computador remoto,
geralmente necessrio fazer um login no sistema operacional
fornecendo as credenciais completas, ou seja, um usurio e senha
vlidos para o sistema operacional.
Quando um cliente se conecta remotamente a um servidor VNC,
ele assume o controle do mouse e do teclado, ou seja, os eventos do
teclado e do mouse so replicados para o servidor remoto. Porm,
isso no quer dizer que o usurio que est em frente ao mouse e
teclado do servidor remoto no possa utiliz-lo. O que acontece
que tanto os eventos de mouse/teclado remoto e local so aceitos
pelo sistema operacional. Deste modo, preciso coordenar como
ser a interao, uma vez que ambos os usurios (o remoto e o
local) podem controlar o computador.
Apesar desta situao de controle mtuo parecer estranha, existem diversas possibilidades para colaborao neste cenrio. H,
inclusive, ferramentas de udio e vdeo conferncia que exploram
esta possibilidade para permitir que, durante uma reunio, mais
de um usurio possa utilizar de forma sncrona uma aplicao de
desenho, por exemplo. Estes cenrios so comuns onde h uma
adoo de ferramentas de colaborao sncrona que so agregadas
aos canais de comunicao em tempo real com udio e vdeo.
O maior benefcio do compartilhamento de aplicativos que
um usurio remoto pode executar o software sem instalao
no seu computador, mesmo que o software no seja compatvel
com o seu sistema operacional ou que exija muito mais poder
de processamento do que o seu computador normalmente pode
possuir. Isso ocorre porque o usurio remoto no est executando
o software em seu computador, ele est apenas visualizando e
controlando o ambiente de trabalho (e, portanto, o software) do
computador host.
Apesar dos servidores e clientes VNC existentes possurem
algoritmos e tcnicas adequadas para reduzir e compactar a
quantidade de bytes necessrios para se utilizar remotamente um
computador como se ele estive local, a tecnologia e o protocolo
RFB no so adequados para a transmisso de vdeo e udio.
Sendo assim, a tecnologia recomendada para situaes onde
no h uma atualizao constante da tela e no h a necessidade
de transmisso de udio.
Contudo, certas empresas exploraram o conceito de controle
remoto e compartilhamento de tela para proporcionar servios
baseados em tecnologias armazenadas na nuvem (cloud computing). Um exemplo claro a empresa OnLive (ver seo Links)
que possui um servio onde possvel jogar diversos games sob
demanda diretamente no computador. O que a plataforma da
OnLive permite um servio de alta fidelidade e baixa latncia
para transferir a imagem do game, que est rodando em seus
servidores. A plataforma da OnLive tambm capta e envia para

Edio 110 .Net Magazine

59

Criando uma aplicao para conexes remotas

o servidor as interaes do mouse/teclado/controle/Kinect/


Wiimote ou qualquer outro dispositivo utilizado para interagir
como game. Em resumo, o servio proporciona a um usurio
jogar um game sem ter que comprar e instalar o console e o jogo.
H, inclusive, a possibilidade de se conectar nas redes Xbox
Live, PSN Network e Nintendo network para jogar com colegas,
comprar filmes, visualizar estatsticas e trofus e interagir com a
comunidade de jogadores.
Outro exemplo de empresa que se especializou na utilizao de
tecnologias para o compartilhamento de tela a Citrix. O foco na
utilizao de sistemas gerenciais do tipo ERP, evitando que seja necessrio instalar e manter softwares adicionais nos computadores
dos clientes. Alm de proporcionar o acesso remoto a servidores
que contm o software, evitando o processo de instalao, atualizao, manuteno e suporte, as tecnologias da Citrix tambm
possuem uma integrao com servidores virtuais, chegando ao
ponto de permitir a virtualizao e o acesso remoto completo do
desktop do usurio que pode acessar o software de qualquer PC,
Mac, Linux, Tablet ou smartphone.

Conhecendo as alternativas
O desenvolvedor da plataforma .NET que trabalha com C#
possui algumas alternativas para criar sua prpria aplicao
que age como cliente VNC. Tanto o RealVNC como o TightVNC
possuem verses com cdigo livre, porm elas so baseadas na
linguagem de programao C/C++. Os projetos mais populares
no .NET que disponibilizam classes e outros recursos para
acessar um servidor VNC em C# so o VNC-Client for .NET, o
.NET VNC Viewer e o VNCSharp.
O projeto VNC-Client for .NET contm apenas um exemplo de
como criar uma aplicao que se conecta a um servidor VNC
remoto. Ele faz uso do arquivo binrio das bibliotecas NzipLib
e DirectX e possui uma documentao simples das classes e
mtodos. Contudo, este projeto no foi criado na forma de uma
biblioteca autocontida que possa ser utilizada em qualquer
tipo de aplicao .NET (console, Windows Forms, WPF, ASP
.NET), o que requer do desenvolvedor um esforo grande para
trabalhar com seus mtodos e classes.
O projeto .NET VNC Viewer disponibilizado como uma
aplicao cliente criada a partir do tipo de projeto Windows
Forms. Apesar de ser completo, este projeto no disponibiliza
uma biblioteca e nem um controle. Alm disso, h no documentao do projeto e ele disponibilizado como um conjunto
de classes que deve ser compilado diretamente no console,
ou seja, no h uma soluo ou projeto do Visual Studio. Este
projeto no possui dependncias externas e nos testes realizados apresentou boa performance de atualizao da tela do
computador remoto.
Por fim, o projeto VNCSharp segue o modelo de licena GPL e
tambm apresentou boa performance de atualizao da tela do
computador remoto. Este projeto disponibilizado como uma
biblioteca .NET (assembly) que contm classes e um controle
do tipo Windows Forms. Apesar do projeto no estar mais em

60 .Net Magazine Edio 110

desenvolvimento, no possuir uma boa documentao e no


precisar de dependncias externas, o cdigo do projeto bem
comentado. Este projeto conta ainda com um exemplo simples
que mostra como utilizar a biblioteca e o controle em uma
aplicao do tipo Windows Forms.
Devido s caractersticas dos projetos descritos e facilidade
de uso, este artigo se concentrar na utilizao da biblioteca
VNCSharp para montar um exemplo de aplicao console em
C# que se conecta a um servidor VNC remoto e envia um conjunto de letras como se elas tivessem sido digitadas pelo usurio
no teclado. O exemplo mostra tambm como enviar eventos do
mouse para mov-lo remotamente ou simular um clique.
O exemplo apresentado pode ser modificado para realizar
tarefas de manuteno automaticamente em diversos computadores de usurios finais, mesmo realizar um treinamento
remoto ou compartilhar uma aplicao existente entre vrios
usurios em uma aplicao de udio/vdeo conferncia.

Download, instalao e exemplo do VNCSharp


O projeto VNCSharp disponibiliza seus recursos em diferentes
arquivos. Neste artigo utilizou-se a verso 1.0 e o leitor pode
fazer o download do arquivo vncsharp-1.0-bin.zip, que contm a
biblioteca compilada no assembly VncSharp.dll, ou o download do
arquivo vncsharp-1.0-src.zip, que contm uma soluo do Visual
Studio com os cdigos fontes deste projeto. H tambm o projeto
de exemplo no formato Windows Form compactado no arquivo
vncsharpexample-csharp-1.0-src.zip. Veremos como compilar o
projeto de exemplo e iniciar conexes remotas para testar a biblioteca e o componente Windows Form disponibilizados.
Aps o download e extrao dos arquivos contidos em
vncsharpexample-csharp-1.0-src.zip, abra a soluo disponibilizada no arquivo VncSharpExampleCS.sln no Visual Studio
(a partir da verso 2005) e compile o projeto. O leitor deve
notar atravs da lista de referncias (References) que a nica
dependncia externa deste projeto o assembly VncSharp.dll
que contm as classes, componentes e outros recursos organizados no namespace VncSharp.
O projeto de exemplo contm um Form chamado VncSharpExampleForm, que composto de menus e de um controle
especial da classe VncSharp.RemoteDesktop chamado rd. Este
controle est dentro do assembly VncSharp.dll e ele responsvel pela apresentao da tela e captura/envio de eventos do
mouse e teclado. Existem outros detalhes importantes deste
exemplo, porm fica a cargo do leitor explorar o projeto para
compreend-lo melhor.
Aps compilar e executar este projeto, podemos clicar no menu
File e escolher a opo Connect. Em seguida devemos informar
o endereo IP ou nome do servidor VNC e a senha. Por padro,
este cliente assume que o servidor est utilizando a porta 5900,
mas caso seja empregada uma porta diferente, basta indicar no
nome do servidor o nmero da porta precedido do caractere :
(dois pontos), como 10.0.0.100:5901 para indicar que o computador
10.0.0.100 possui um servidor VNC na porta 5901.

A Figura 1 mostra a conexo remota com um servidor executando o Windows XP (note que o cone do VNC no canto esquerdo
da barra de tarefas do Windows mudou de cor para indicar a
conexo), enquanto a Figura 2 mostra uma conexo remota com
um computador executando o Mac OS Lion, que possui um servidor VNC nativo, isto , disponibilizado junto com o sistema
operacional. J a Figura 3 mostra um exemplo de conexo com um
dispositivo celular rodando o sistema operacional Android 4.0.4
(Ice Cream Sandwich) com um servidor VNC. Qualquer sistema
operacional que possua um servidor VNC que siga o padro do
protocolo RFB pode receber uma conexo do VncSharp, inclusive
sistemas operacionais das plataformas mveis (iOS, Android e
Windows 8).
Uma vez que o teste de conexo tenha sido realizado com sucesso, preciso utilizar a opo Disconnect do menu File para
finalizar a conexo e liberar os recursos utilizados do lado do
cliente.

Figura 3. Cliente VncSharpExampleForm conectado a um servidor VNC no Android 4.0.4 (Ice


Cream Sandwich)

Enviando caracteres

Figura 1. Cliente VncSharpExampleForm conectado a um servidor VNC no Windows XP

Figura 2. Cliente VncSharpExampleForm conectado a um servidor VNC no Mac OS Lion

Para auxiliar o leitor a compreender como trabalhar com a biblioteca do projeto VNCSharp, este artigo apresentar um projeto
do tipo Console Application escrito em C# que utiliza apenas as
classes bsicas do VNCSharp. O objetivo mostrar como possvel
abrir uma conexo com um servidor VNC remoto, enviar uma
sequncia de caracteres como se fosse algo digitado pelo usurio
e fechar a conexo. Apesar de este exemplo ser simples, ele ilustra
bem como possvel utilizar o C# para se conectar a um servidor
VNC independente da plataforma e sistema operacional na qual
este servidor esteja sendo executado.
Apesar do exemplo apresentado neste artigo utilizar o tipo de
projeto Console Application, as classes do VNCSharp podem
ser utilizadas em qualquer tipo de aplicao .NET. H, inclusive,
a possibilidade de criar um cliente VNC inteiro em HTML5 e
ASP.NET para que o usurio possa acessar remotamente outros
computadores diretamente pelo browser sem a necessidade de
instalao de nenhum software adicional.
Um cliente VNC basicamente faz trs tarefas principais: ele controla a conexo (abrir/fechar), recebe a atualizao de telas e envia
teclas ou eventos do mouse. Tambm possvel realizar tarefas
mais complexas, como copiar o contedo do que foi colocado na
rea de transferncia do servidor remoto com o comando cpia
(ou Control+C) e colar (Control+V) este contedo no computador
que executa o cliente. Porm, como foi explicado na primeira
sesso deste artigo, veremos um exemplo que detalhar como

Edio 110 .Net Magazine

61

Criando uma aplicao para conexes remotas

abrir a conexo, enviar caracteres, enviar eventos do mouse e


fechar a conexo. O leitor que se interessar por recursos avanados proporcionados pela tecnologia VNC pode analisar o cdigo
fonte do projeto VNCSharp, pois ele possui diversas classes que
implementam o protocolo RFB, interagem com os dados enviados
e recebidos, compactam e descompactam os dados e permitem a
utilizao de recursos avanados.
Vamos comear o exemplo abrindo o Visual Studio e criando um
novo projeto do tipo Console Application chamado ConsoleVNC.
Em seguida preciso fazer a referncia ao assembly VncSharp
.dll que disponibilizado no arquivo vncsharp-1.0-bin.zip do
projeto VNCSharp.
Para fazer a referncia corretamente preciso clicar com o
boto direito do mouse sobre o item References na janela Solution Explorer e escolher a opo Add References. Em seguida
escolha a aba Browser e navegue para a pasta onde o arquivo
VncSharp.dll est armazenado, selecione o arquivo e clique
no boto OK. Agora que a referncia est completa e podemos
comear a utilizar as classes do VNCSharp. O cdigo fonte
comentado deste exemplo apresentado na Listagem 1 que
contm apenas o mtodo Main().

Para este exemplo utilizaremos um objeto da classe VncClient


chamado v. O primeiro passo abrir a conexo e faremos isso com
o mtodo Connect(), que recebe o endereo do servidor, o nmero
da tela (screen) e a porta. Neste exemplo utilizaremos o endereo
10.0.0.100 e a porta 5900. O valor numrico da tela deve ser 0, uma
vez que no vamos trabalhar com mltiplas telas neste exemplo.
Um servidor VNC pode ser configurado para permitir conexes
de usurio sem que haja a necessidade de senha. Contudo, tal opo no recomendada por motivos de segurana. Na Listagem 1
o mtodo Connect() retorna um valor booleano indicando se
necessrio ou no fornecer uma senha para se conectar neste
servidor. Caso seja necessrio, a varivel needPassword receber
o valor verdadeiro (true) e devemos chamar o mtodo Authenticate(). Caso no seja necessrio fornecer uma senha, podemos
chamar o mtodo Initialize(). Para fornecer a senha chamamos
o mtodo Authenticate() passando como parmetro a senha, que
no exemplo da Listagem 1 abc123. Caso o retorno de Authenticate() seja verdadeiro, prosseguimos com conexo e chamamos
o mtodo Initialize().
O ltimo mtodo necessrio para abrir corretamente a conexo
o mtodo StartUpdates(), pois ele sinaliza para o servidor que

Listagem 1. Exemplo de conexo com o projeto VncSharp


01 using System;
02 using VncSharp;
03 using System.Windows;
04 using System.Drawing;
05 using System.Threading;
06
07 namespace ConsoleVNC
08 {
09 class ConsoleVNC
10 {
11
// Esta varivel representa o cliente VNC
12
static VncClient v = new VncClient();
13
14
static void Main(string[] args)
15
{
16
// Armzena se precisa ou no enviar a senha
17
bool needPassword;
18
19
try
20
{
21
// Abre a conexo como servidor 10.0.0.100
22
// na porta 5900 e na tela 0
23
needPassword = v.Connect(10.0.0.100, 0, 5900);
24
if (needPassword)
25
{
26
// Envia a senha abc123
27
if (v.Authenticate(abc123))
28
{
29
// Realiza as inicializaes necessrias
30
v.Initialize();
31
}
32
else
33
{
34
// Problema: informar usurio e finalizar
35
Console.WriteLine(Autentication problem!);
36
return;
37
}
38
}

62 .Net Magazine Edio 110

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

60
61
62
63
64
65
66
67
68
69
}
70 }
71 }

else
// Realiza as inicializaes necessrias
v.Initialize();
// Indicando o mtodo que vai receber o
// evento de desconexo
v.ConnectionLost +=
new EventHandler(ConsoleVNC.ClientConnectionLost);
// Comea a receber as atualizaes de tela
v.StartUpdates();
}
catch (Exception e)
{
// Problemas na conexo: informar usurio e finalizar
Console.WriteLine(Connection error: + e.Message);
return;
}
// Mostra informaes do host
Console.WriteLine(Connection OK!);
Console.WriteLine(Host Name: + v.HostName);
Console.WriteLine(Screen Size: +
v.Framebuffer.Width.ToString() + x
+ v.Framebuffer.Height.ToString() );
// Envia a frase Hello World with VNC para o host
ConsoleVNC.SendString(Hello World with VNC);
// Disconecta e libera os recursos
v.Disconnect();
Console.WriteLine(Disconnected!
Presse any key to terminate);
Console.ReadLine();

estamos prontos para receber as atualizaes de tela. Neste exemplo no iremos trabalhar com a atualizao de tela, pois apenas
vamos enviar um conjunto de caracteres para o servidor VNC.
Um ponto importante que toda a sequncia de conexo est
protegida por um bloco try/catch e as devidas mensagens de erro
so apresentadas, caso ocorra algum problema.
Aps a conexo entre o cliente e o servidor ser estabelecida,
possvel que, por algum motivo, o servidor encerre esta conexo.
Por exemplo: o computador que contm o servio VNC foi reinicializado. Devido a esta possibilidade a biblioteca VNCSharp possui
um evento que ser disparado no cliente caso o servidor encerre a
conexo. Para indicar um mtodo que ser chamado nesta situao
devemos preencher a propriedade ConnectionLost com um objeto
da classe EventHandler, que permite o acesso a um mtodo que
tratar este evento. No cdigo da Listagem 2 o mtodo esttico
ClientConectionLost() utilizado como evento para a propriedade
ConnectionLost do objeto v, que da classe VncClient.

um valor numrico do tipo UInt32. Caso seja necessrio enviar


teclas especiais como Enter, Tab, SHIFT ou ALT, preciso enviar
um cdigo numrico do tipo UInt32 especial para cada tecla. Este
cdigo definido no protocolo RFB, porm a Tabela 1 apresenta
algumas das teclas especiais mais utilizadas e tambm o respectivo valor no tipo de dados UInt32 representados por um valor
hexadecimal.
Listagem 3. Mtodo para envio de caracteres com o VncSharp
01 static void SendString(String s)
02 {
03 // Envia um caracter por vez
04 foreach (Char c in s.ToCharArray())
05 {
06
// preciso converter o caracter para UInt32
07
// O segundo parmetro verdadeiro para simular que o
08
// usurio pressionou as teclas
09
v.WriteKeyboardEvent((UInt32) c, true);
10 }
11 }

Listagem 2. Mtodo para tratar desconexo do servidor


01 // Evento gerado caso o servidor desconecte o cliente
02 static void ClientConnectionLost(object sender, EventArgs e)
03 {
04 // Liberando os recursos da conexo do cliente
05 ConsoleVNC.v.Disconnect();
06 }

O mtodo ClientConectionLost() segue a assinatura de um evento, ou seja, ele retorna void e possui dois parmetros: um objeto
da classe Object e um objeto da classe EventArgs. A utilizao
do evento ocorre quando o servidor finaliza a conexo e ela ser
simples, pois somente vamos chamar o mtodo Disconnect() da
classe VncClient para liberar os recursos alocados. Contudo, o
leitor pode codificar outras funcionalidades neste evento, como
notificar o usurio de alguma forma na interface grfica que o
servidor finalizou a conexo.
Uma vez que o primeiro passo esteja completo, ou seja, abrir
a conexo, podem mostrar algumas caractersticas do host.
A propriedade HostName da classe VncClient retorna o nome do
host e as propriedades Framebuffer.Width e Framebuffer.Height
retornam valores numricos com a largura e altura da tela do host,
respectivamente. O exemplo mostra estes valores para o usurio
e segue seu fluxo para enviar uma frase pelo VNC.
O envio da frase Hello World with VNC realizado atravs do
mtodo SendString(), que mostrado na Listagem 3. Este mtodo
basicamente recebe uma String como parmetro e faz um loop
para pegar cada caractere individual deste String, uma vez que
esta operao necessria, pois o mtodo WriteKeyboardEvent()
da classe VncCliente requer a converso de cada caractere enviado
para UInt32. Tambm necessrio passar o segundo parmetro
de WriteKeyboardEvent() como verdadeiro para simular que o
usurio realmente digitou algo.
No exemplo do cdigo apresentado na Listagem 3 um texto foi
enviado por meio da converso de cada um dos caracteres para

Tecla

Valor numrico
(UInt32)

Tecla

Valor numrico (UInt32)

Tab

0x0000FF09

F1

0x0000FFBE

Enter

0x0000FF0D

F2

0x0000FFBF

Esc

0x0000FF1B

F3

0x0000FFC0

Home

0x0000FF50

F4

0x0000FFC1

Seta para esquerda

0x0000FF51

F5

0x0000FFC2

Seta para cima

0x0000FF52

F6

0x0000FFC3

Seta para direita

0x0000FF53

F7

0x0000FFC4

Seta para baixo

0x0000FF54

F8

0x0000FFC5

PageUp

0x0000FF55

F9

0x0000FFC6

PageDown

0x0000FF56

F10

0x0000FFC7

End

0x0000FF57

F11

0x0000FFC8

Insert

0x0000FF63

F12

0x0000FFC9

Shift

0x0000FFE1

Alt

0x0000FFE9

Ctrl

0x0000FFE3

Delete

0x0000FFFF

Tabela 1. Teclas especiais e seus respectivos valores UInt32


O envio de teclas deve ser realizado de forma individual, ou seja,
uma tecla por vez. preciso lembrar que certas teclas iniciam e
finalizam um modo, por exemplo, a tecla Shift que inicia/termina
o modo de letras maisculas.
Por fim, o ltimo passo do programa de exemplo chamar o
mtodo Disconnect() da classe VncClient para finalizar a conexo e liberar os recursos. Para testar o exemplo preciso instalar
corretamente um servidor VNC e abrir algum tipo de aplicao
que aceite caracteres, como o editor Notepad do Windows.
Se tudo estiver configurado corretamente (servidor VNC, firewall,

Edio 110 .Net Magazine

63

Criando uma aplicao para conexes remotas

senha, etc.), ao rodar a aplicao o usurio remoto ver a frase


Hello World with VNC sendo escrita na aplicao que estiver
com foco do cursor do mouse.

Enviando eventos do mouse


Agora que j vimos como se conectar a um servidor VNC
remoto e enviar um conjunto de teclas como se fosse o usurio
digitando algo no teclado, veremos como enviar eventos do
mouse. Este tipo de funcionalidade muito til quando precisamos acessar algum cone ou elemento visual da interface do
usurio que requer o posicionamento e o clique do mouse.
Um cenrio comum para este tipo de situao no suporte
a usurios. Vamos supor que um usurio est com dificuldade para acessar uma opo no menu de uma aplicao.
O atendente de suporte que recebeu uma ligao deste usurio pode acionar um comando da sua interface e posicionar
automaticamente o cursor do mouse do usurio sem que o
atendente de suporte tenha acesso remoto completo ao sistema operacional do usurio. Neste cenrio a possibilidade
do atendente de suporte ter acesso a arquivos e contedos
da mquina do usurio reduzida, evitando uma possvel
violao da privacidade.
Antes de enviar os eventos do mouse preciso levar em considerao que a resoluo do computador remoto (o host com o
servidor VNC) pode ser diferente da resoluo do computador
com o cliente VNC. Portanto, preciso fazer um mapeamento e
converso de coordenadas locais para as coordenadas remotas
do ponteiro para que o uso do mouse parea natural e adequado.
O controle disponibilizado pelo VncSharp implementa um
algoritmo que faz este tipo de mapeamento de coordenadas de
tela, porm veremos um exemplo simples de movimentao do
cursor em um conjunto de coordenadas da tela pr-definido.
Para enviar eventos do mouse utilizando a classe VncClient
preciso utilizar o mtodo WritePointerEvent(), que requer dois
parmetros: um valor numrico para indicar qual boto do mouse
foi pressionado e um objeto da classe System.Drawing.Point com
as coordenadas de onde o cursor do mouse ser posicionado.
No primeiro exemplo veremos como enviar um comando
para simular a movimentao do mouse. Para isso vamos
criar um novo mtodo chamado SendMouseMove(), que vai
enviar comandos de movimentao do mouse para seguir o
formato de um quadrado com 100 pixels de lado.
O quadrado ter seus vrticies nos pontos (100,100), (200,100),
(200,200) e (100,200) da interface do usurio e ser desenhado ponto
a ponto. A movimentao do cursor ser feita atravs de quatro
loops que utilizam o contador do loop para variar as coordenadas
de um objeto da classe System.Drawing.Point, que ser enviado
como segundo parmetro do mtodo WritePointerEvent(). Para
visualizarmos o caminho do cursor do mouse utilizaremos um
intervalo de 10 milisegundos entre cada movimentao do cursor
atravs da chamada do mtodo Thread.Sleep().
O primeiro parmetro do mtodo WritePointerEvent() requer
um valor numrico para indicar qual o boto do mouse que

64 .Net Magazine Edio 110

est sendo pressionado. Neste primeiro exemplo vamos apenas


movimentar o curso do mouse e, por isso, passaremos o valor 0
como primeiro parmetro para o mtodo WritePointerEvent().
A Listagem 4 mostra o contedo completo do mtodo SendMouse-Move() que pode ser chamado logo aps o mtodo
SendString() da Listagem 1.
Listagem 4. Mtodo SendMouseMove() que envia comandos para movimentar o
cursor do mouse
01 static void SendMouseMove()
02 {
03 // Topo do quadrado
04 for (int i = 100; i <= 200; i++)
05 {
06
Thread.Sleep(10);
07
v.WritePointerEvent(0, new System.Drawing.Point(i, 100));
08 }
09 // Lado direito do quadrado
10 for (int i = 100; i <= 200; i++)
11 {
12
Thread.Sleep(10);
13
v.WritePointerEvent(0, new System.Drawing.Point(200, i));
14 }
15 // Base do quadrado
16 for (int i = 200; i >= 100; i--)
17 {
18
Thread.Sleep(10);
19
v.WritePointerEvent(0, new System.Drawing.Point(i, 200));
20 }
21
22 // Lado esquerdo do quadrado
23 for (int i = 200; i >= 100; i--)
24 {
25
Thread.Sleep(10);
26
v.WritePointerEvent(0, new System.Drawing.Point(100, i));
27 }
28 }

O prximo exemplo que veremos envia o clique do mouse


remotamente. Para enviar o clique do mouse tambm utilizaremos o mtodo WritePointEnvent() da classe VncClient,
porm desta vez precisamos indicar no primeiro parmetro
qual boto do mouse ser pressionado. A Tabela 2 mostra a
correspondncia de valores nmeros para o valor do primeiro
parmetro do mtoro WritePointEvent() e os respectivos botes do mouse. Tambm so mostrados na Tabela 2 os valores
correspondentes movimentao da roda do mouse (scroll)
para frente e para trs.
Valor do parmetro

Boto do mouse

Nenhum boto pressionado

Esquerdo

Meio

Direito

Roda do mouse movimentada para frente

16

Roda do mouse movimentada para trs

Tabela 2. Valores numricos do primeiro parmetro de WritePointEvent() e botes do mouse

possvel simular a situao onde mais de um boto foi pressionando adicionando os valores numricos. Por exemplo, se desejarmos indicar que os botes direito e esquerdo foram pressionados
juntos utilizaremos o valor 5, pois 1+4 = 5.
Devemos tomar cuidado com um ltimo detalhe antes de enviar
um evento de clique do mouse com o mtodo WritePointEvent():
nos sistemas operacionais que seguem o modelo de interface
WIMP (BOX 1) um clique do mouse geralmente representado
por dois eventos: MouseDown e MouseUp. Isto quer dizer que
precisamos fazer duas chamadas aos mtodos WritePointEvent()
para simular um clique do mouse, sendo que a primeira delas deve
indicar qual foi o boto utilizado e a segunda chamada indica o
valor 0 (ausncia de boto).
BOX 1. Interfaces WIMP
WIMP um acrnimo usado para descrever todos os elementos de sistemas operacionais que
definem o modo como interagimos com os computadores cuja GUI (Graphical User Interface
Interface Grfica de usurio) seja baseada em janelas.W significa Windows (janelas), I significa Icons
(cones), M significa Menus e P significa Pointers (ponteiros).
Em 1973 a Xerox desenvolveu o primeiro sistema operacional com um paradigma WIMP para o Xerox
Alto. Desde aquela poca at recentemente as GUI baseadas em WIMP foram as lderes da interao
entre humanos e computadores. Sistemas operacionais como o Windows, Mac OS, OS/2 e o Linux
adotaram os conceitos WIMP em suas interfaces, o que facilitou a interao para os usurios que
utilizam mouse e teclado.
Com as novas tecnologias e recursos para desenvolvimento de pginas Web, muitos dos conceitos
WIMP vem sendo desafiados, como a ausncia de menus tradicionais. Alm disso, os sistema
operacionais mveis como iOS, Android e Windows 8 abandonaram muitos dos conceitos WIMP ao
adotarem interfaces baseadas em toques e gestos realizados diretamente no dispositivo sensvel a
toque que apresenta as informaes.

Se entre a primeira chamada (equivalente ao MouseDown) e a


segunda chamada (equivalente ao MouseUp) no houver uma
diferena nas coordenadas, ou seja, o valor do segundo parmetro de WritePointEvent() for igual, temos o evento do clique do
mouse. Porm, caso haja uma diferena de coordenadas entre
a primeira chamada de WritePointEvent() e a segunda temos a
representao do clicar, arrastar e soltar, tambm conhecido como
drag-and-drop. Por fim, se desejarmos simular o evento de clique
duplo basta fazer duas vezes as duas chamadas necessrias para
um clique normal.
Para mostrar como simular o envio de um evento de clique do
mouse pelo VNC, a Listagem 5 mostra o mtodo SendMouseClick(), que recebe como parmetro um valor numrico correspondente ao boto do mouse como apresentado na Tabela 2.
O contedo deste mtodo simples: ele cria uma varivel chamada
mask para indicar qual o boto do mouse que est sendo acionado e simula um clique no centro da tela, utilizando o mtodo
WritePonterEvent. Para testar este exemplo leitor deve realizar a
chamada de SendMouseClick() duas vezes, sendo que na primeira
vez deve-se indicar o valor do boto do mouse (1, 2 ou 4) e na
segunda vez deve-se indicar o valor 0 para que um clique seja
enviado para o servidor VNC remoto.

Listagem 5. Mtodo SendMouseClick() que envia comandos para simular o clique


de um boto do mouse no centro da tela.
01 static void SendMouseClick(byte botao)
02 {
03 // Mandando o cursor do mouse para o centro da tela
04
05 byte mask;
06
07 // 1 = boto da esquerda
08 // 2 = boto do centro
09 // 4 = boto da direita
10 mask = botao;
11
12 v.WritePointerEvent(
13
mask,
14
new System.Drawing.Point
(v.Framebuffer.Width/2,v.Framebuffer.Height/2 )
15 );
16 }

Concluso
A utilizao de tecnologias de compartilhamento de tela e controle remoto representa uma oportunidade para a realizao de
tarefas que necessita do acesso completo local a um computador.
Apesar e ser possvel realizar diversas operaes com ferramentas de acesso remoto ao shell, tais como ferramentas de SSH ou
mesmo servidores de FTP/SFTP, o acesso direto ao desktop de um
computador pode fornecer diversas oportunidades para automao de tarefas, treinamento de usurio, resoluo de problemas
de suporte, deploy de aplicaes, verificao de configuraes e
outras.
As principais ferramentas de compartilhamento de telas livres,
agrupadas sob a sigla VNC, permitem o acesso remoto completo
de um servidor, porm elas representam potenciais problemas de
segurana e violao de privacidade. Por exemplo, atravs do acesso por VNC um usurio com ms intenes pode acessar arquivos
pessoais de usurios ou mesmo observar a digitao de senhas
e outras informaes sigilosas. Neste contexto, permitir o acesso
remoto por meio do VNC se torna uma atitude arriscada.
Contudo, possvel criar uma aplicao na plataforma .NET que
encapsula o acesso remoto a um servidor VNC. Esta aplicao
pode se conectar a um host remoto e enviar determinadas teclas
ou eventos do mouse e realizar certas tarefas sem nem ao menos
mostrar para quem iniciou este cliente VNC a tela do desktop
remoto. Desta maneira evitam-se possveis problemas de violao
de privacidade.
Apesar da tecnologia envolvida nos servidores VNC ser bsica,
ou seja, permite apenas o envio de teclas e eventos do mouse e
recebe do host a atualizao de telas, existem vrias possibilidades
para incluir novas funcionalidades. Criptografia das informaes, ferramentas de chat com texto e VoIP, envio/transferncia
de arquivos e acesso por meio da Web so apenas algumas das
funcionalidades adicionais que no so contempladas pelo protocolo RFB e que podem ser agregadas em uma soluo que utilize
tecnologias de compartilhamento de tela.

Edio 110 .Net Magazine

65

Criando uma aplicao para conexes remotas

Outro cenrio de uso para esta tecnologia envolve o treinamento. Em uma situao onde no h recursos para treinamento
adequados (projetores, sala de treinamento, etc) possvel treinar
usurios de forma automatizada diretamente nas suas interfaces, sem a necessidade de locomoo do usurio. Este tipo de
treinamento com demonstraes fornece a sensao de presena
remota e o usurio que est sendo treinado pode acompanhar as
aes sendo realizadas como se o instrutor estivesse trabalhando
junto com ele.
Outra forma para utilizar o compartilhamento de contedo ou
apresentao so seminrios Web ou webinars. Em um webinar
um apresentador envia um convite por e-mail a um grupo de participantes que inclui um link e um cdigo de acesso. Quando os
participantes clicarem no link e digitarem seus cdigos de acesso
eles esto registrados na apresentao virtual. Neste cenrio s
pode haver um apresentador de cada vez que pode compartilhar
seu desktop, suas apresentaes com programas como o PowerPoint, ou partes de outras aplicaes e software no computador
host. Com o software de webinar, que baseado em tecnologias
de compartilhamento de tela, cada apresentador pode compartilhar o seu prprio ambiente de trabalho e arquivos. Talvez o
exemplo mais claro deste tipo de tecnologia seja representado
pelos servios da empresa WebEx (parte do grupo da Cisco) que
fornece aplicativos de demanda, reunio online, web conferncia
e aplicaes de vdeo conferncia.
Com a utilizao de um servidor VNC tambm possvel criar
um servio de monitorao constante do desktop de um computador remoto. Tal ferramenta pode ser til para revisar aes
realizadas ou medir o tempo gasto em determinada aplicao.
Por exemplo: um gerente de projeto deseja saber quanto tempo
um programador passou como a interface do Visual Studio aberto
e quanto tempo ele passou navegando na internet. Ao invs de
programar um servio especfico para este tipo de monitorao,
possvel instalar um servidor VNC no computador do desenvolvedor e criar um cliente VNC em C# que periodicamente l a tela
do desenvolvedor e grava a tela em uma sequncia de imagens
ou em um banco de dados. Posteriormente o gerente de projeto
pode revisar as imagens e verificar exatamente quanto tempo o
desenvolvedor gastou na interface do Visual Studio ou no navegador. Alm disso, o gerente de projeto tambm pode identificar
como o programador utilizou o IDE ou mesmo qual tipo de site
foi visitado pelo programador. Novamente, este uso da tecnologia
VNC possui implicaes no campo da privacidade e segurana

66 .Net Magazine Edio 110

que devem ser consideradas com cautela por quem emprega este
tipo de tecnologia para fins de monitoria.
O leitor que desejar automatizar tarefas remotas que exigem
acesso direto ao servidor em diversas mquinas pode se beneficiar
do contedo apresentado neste artigo, uma vez que ele mostrou
como possvel desenvolver uma aplicao .NET na linguagem
C# que age como um cliente de um servidor VNC atravs do uso
das classes fornecidas pelo projeto VNCSharp.

Autor
Mauro Pichiliani
mauro@pichiliani.com.br http://pichiliani.com.br
bacharel em Cincia da Computao, mestre e doutorando
pelo ITA (Instituto Tecnolgico de Aeronutica) e MCP, MCDBA e
MCTS. Trabalha h mais de 10 anos utilizando diversos bancos de dados
SQL e NoSQL. colunista de SQL Server do web site iMasters (http://www.
imasters.com.br) e mantenedor do DatabaseCast (@databasecast), o podcast brasileiro
sobre banco de dados.
Links:
Projeto VNC-Client for .NET
http://sourceforge.net/projects/dnvnccl/
Projeto.NET VNC Viewer
http://sourceforge.net/projects/dotnetvnc/
Projeto VNCSharp
http://cdot.senecac.on.ca/projects/vncsharp
Servidor e cliente VNC gratuito RealVNC para Windows, Mac OS e Linux
https://www.realvnc.com
Servidor e cliente VNC gratuito TightVNC para Windows, Mac OS e Linux
http://www.tightvnc.com/
OnLive Games
http://games.onlive.com/

Voc gostou deste artigo?


D seu voto em www.devmedia.com.br/netmagazine/feedback
Ajude-nos a manter a qualidade da revista!

Edio 110 .Net Magazine

67

Criando uma aplicao para conexes remotas

68 .Net Magazine Edio 110

Você também pode gostar