Neste artigo veremos

O que é o .NET RIA Service; principais funcionalidades; como utilizá-lo no projeto ASP.NET; como utilizá-lo no projeto Silverlight.

Qual a finalidade?

Aprender como utilizar o recente Framework lançado pela Microsoft para construir aplicações em Silverlight e como tirar proveito de suas funcionalidades.

Quais situações utilizam esses recursos?

Qualquer sistema hoje em dia pode ser desenvolvimento com tecnologia Silverlight.

Resumo do DevMan

A Microsoft tem colocado em status de emergente diversas tecnologias. É até muito difícil acompanhar tudo que está em desenvolvimento ou estourando por ai. O que veremos nesse artigo de perto é mais uma tecnologia Microsoft que com certeza trará grande produtividade.

O que veremos aqui é uma visão geral sobre o Framework .NET RIA Service lançado pela Microsoft, e aprender a utilizá-lo no desenvolvimento de aplicações Silverlight.

Recentemente a Microsoft anunciou o desenvolvimento de um Framework com o codinome Alexandria para o desenvolvimento de aplicações em Silverlight. O primeiro release deste Framework foi lançado oficialmente com o nome .NET RIA Service em uma sessão do MIX09 e está disponível para download. O link para download encontra-se no final do artigo. Por conveniência, durante o artigo, vou abreviar o nome para somente RIAService.

Este Framework torna muito natural a comunicação entre a aplicação Silverlight e a lógica de negócio presente do lado do Server. Veja neste artigo como utilizar as funcionalidades deste Framework em uma aplicação Silverlight, e também como encapsular a lógica de negócio com o novo DomainService e o Entity Framework para acesso ao banco de dados.

Nota: Em aplicações Web, o termo client é usado para referenciar o que acontece do lado do usuário, o Silverlight roda no browser na máquina do usuário, portanto a aplicação Silverlight roda no lado client. O termo server é usado para referenciar com quem o client irá se comunicar. Por exemplo, uma aplicação ASP.NET atendendo as requisições que o Silverlight faz.

Funcionalidades do Ria Service

Segundo a visão de Nikhil Kothari, arquiteto de programação da Microsoft:

O RIAService simplifica o padrão de aplicações tradicionais com n-camadas, unindo as plataformas ASP.NET e Silverlight; fornece um padrão para escrever lógica de aplicação que roda em uma camada central entre o client e o Server, controla o acesso aos dados para consulta, mudanças e demais operações. Também fornece suporte para tarefas comuns como visualização de dados, autenticação e papéis de usuário, integrando os componentes Silverlight no client com ASP.NET na camada central”.

A idéia da Microsoft é simplificar e agregar produtividade no desenvolvimento de aplicações com Silverlight, a Figura 1 mostra a anatomia de uma aplicação Web clássica.

Figura 1. Aplicação web clássica

Ainda na visão de Nikhil:

A aplicação web se comunica com um ou mais banco de dados e serviços no back-end, que contem um modelo de dados e uma camada de acesso a dados, lógica de aplicação que diz o que pode ser feito utilizando a aplicação e finalmente alguma lógica de apresentação, e normalmente uma parte da aplicação em HTML para apresentar no browser. Maior parte da aplicação fica no servidor; acessando diferentes funcionalidades como um simples método de chamadas, o que simplifica as coisas”.

Com o RIAService, mais da lógica de apresentação vai para o client, o que facilita no desenvolvimento, pois com a lógica de apresentação do lado do client, você tem mais recursos para melhorar ainda mais a experiência com o usuário e ganhar com produtividade ao mesmo tempo. No entanto este modelo agrega mais trabalho para o desenvolvedor; na hora de definir o que será compartilhado entre o server e o client. A Figura 2 mostra a anatomia de uma aplicação Silverlight com RIAService.

Figura 2. Aplicação web com RIAService

A camada de apresentação se conecta com o Server através de uma rede, e nós normalmente adicionamos referência a um serviço em um endereço que estará aguardando pelas requisições do client. Com a arquitetura do RIAService esta comunicação fica muito simples, as chamadas são feitas como se o client e o server fossem a mesma coisa, para o desenvolvedor fica transparente a existência da rede como meio de comunicação entre o client e o resto da aplicação, esta é a intenção. Esta característica é a aposta para obter produtividade no desenvolvimento em Silverlight.

Para quem já está acostumado a programar com ASP.NET, vai achar muito semelhante à maneira de programar, pois a idéia de DataSource como o ObjectDataSource do ASP.NET está presente no Silverlight 3. Para utilizar o Framework RIAService no projeto Silverlight não foi criado nenhum template especial, continua sendo o template Silverlight Application do Visual Studio, no entanto algumas mudanças foram feitas. Uma nova pasta foi criada para manter do lado do client os arquivos que são compartilhados com o server, esta pasta tem o nome de Generated Code, para visualizá-la você precisa habilitar a opção para mostrar todos os arquivos do projeto. Vamos poder ver isso mais adiante quando começarmos a criar o projeto.

DomainDataSource: Este controle é uma das novidades do RIAService, ele utiliza um DataContext gerado pelo Server e torna muito simples a chamada de métodos do lado do client. Funciona como o ObjectDataSource do ASP.NET.

Autenticação e papéis: Os serviços de autenticações do ASP.NET agora são implementados no Silverlight, de modo que para usá-los você não vai precisar adicionar nenhuma referência para nenhum serviço. A Figura 3 mostra como funciona a comunicação do Silverlight com RIAService.

Figura 3. Comunicação do Silverlight com RIAService

Como o foco deste artigo não é sobre SQL nem sobre banco de dados. Para acompanhar os exemplos deste artigo vamos utilizar o banco AdventureWorks da Microsoft que pode ser baixado no link www.codeplex.com/MSFTDBProdSamples.

Criando o projeto

Para iniciar nosso projeto é claro que teremos que criar um ambiente de desenvolvimento onde serão necessários os aplicativos Microsoft Visual Studio 2008, Silverlight 3 Tools for Visual Studio e .net RIA Services March 2009 Preview. Com a versão Express do Visual Studio 2008 já é possível testar nossa aplicação exemplo, portanto acesse o link www.microsoft.com/exPress/download/ e faça seu download e instalação.

O segundo requisito, o Silverlight 3 Tools for Visual Studio, pode ser obtido no endereço www.microsoft.com/downloads/details.aspx?FamilyId=11dc7151-dbd6-4e39-878f-5081863cbb5d&displaylang=en.

O terceiro e último item de nossa lista de requisitos é o RIA Services March 2009 Preview que pode ser baixado e instalado pelo link www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=76bb3a07-3846-4564-b0c3-27972bcaabce. Evidentemente que não entrarei em detalhes de sua instalação, pois não é o foco desse artigo. O interessante é que todos eles são gratuitos.

Vamos ao exemplo então. Com o Visual Studio 2008 aberto selecione File> New Project. Em seguida escolha o template Silverlight Application e coloque o nome de SLAdventureWorks. Na janela seguinte, no campo New Web Project name digite o nome HostAdventureWorks, marque as opções Host the silverlight in a new Web site e Link to ASP.NET Server project. Esta segunda opção deve ser marcada para que possamos utilizar as funcionalidades do RIAService. Em caso de dúvidas, consulte a Figura 4.

Figura 4. Habilitando RIAService no projeto Host do Silverlight

Repare na pasta References do projeto Silverlight e do projeto ASP.NET, as referências que você vai utilizar enquanto estiver criando sua aplicação foram adicionadas automaticamente. A referência para o RIAService é o assembly System.Web.Ria que possui uma versão para o client e outra para o Server.

Outra referência relacionada ao RIAService é o assembly System.Web.DomainServices que permite você usar a classe DomainService. Quando marcamos a opção Link to ASP.NET Server projects nós conectamos o projeto Silverlight ao projeto ASP.NET, e eles agora irão compartilhar partes de código, veremos que classes serão compartilhadas mais adiante.

Selecione o projeto Silverlight e clique em Show All Files, você verá a pasta Generated_Code. Nesta pasta irá o código gerado pelo Server e compartilhado com o client conforme Figura 5. Esta pasta não precisa ser incluída no seu repositório de código (CVS, SVN, etc.. ).

Figura 5. Pasta Generated_Code

Criando ADO.NET Entity Data Model

Para fazer o mapeamento com o banco de dados vamos criar um ADO.NET Entity Data Model. Clique com botão do direito do mouse no projeto HostAdventureWorks e clique Add New Item. Na janela seguinte no campo ADO.Net Entity Data Model , digite o nome AdventureWorksDataModel e pressione Ok. Veja Figura 6.

Figura 6. Criando o ADO.Net Entity Data Model

O Visual Studio irá exibir um Wizard para configurar seu DataModel, selecione Generate from database e clique Next. Na próxima janela configure a conexão com o banco de dados e clique Next. Por último o Wizard apresenta uma janela com os objetos do banco de dados, para o exemplo do nosso artigo escolha a tabela Product.

Agora faça um build no projeto HostAdventureWorks para gerar as classes do seu DataModel. Veja na Figura 7, como ficou o projeto após incluir o DataModel.

Figura 7. Projeto após adicionar o DataModel

Adicionando a classe DomainService

A classe DomainService irá expor os métodos para que o Silverlight possa utilizá-los. Esta classe será compartilhada com o client, e poderá ser vista dentro da pasta Generated_Code. Para criar o DomainService, clique com o botão direito do mouse sobre o projeto HostAdventureWorks, selecione Add New Item. Escolha o tipo Domain Service Class e digite o nome AdventureWorksDataService. Veja Figura 8.

Figura 8. Adicionando a classe DomainService

O Visual Studio irá exibir uma janela para configurar o serviço. Nesta janela você tem a opção de associar o serviço à um DataModel, é o que vamos fazer. Escolha AdventureWorksEntities. Em seguida marque as entidades deste DataModel ( no nosso caso somente a entidade Product ) e também marque a opção Enable Editing. Por último marque a opção Generate associated classes for metadata e clique ok.

Dentro da classe AdventureWorksDataService o Visual Studio gerou os métodos de CRUD da tabela Product do DataModel automaticamente. A lógica aplicada nesta classe pode ser modificada para atender alguma regra de negócio especifica.

Entendendo o arquivo Metadata

Se você analisar a estrutura do projeto, o Visual Studio gerou um arquivo com extensão metadata com o nome AdventureWorksDataService.metadata.cs. Este arquivo contém informações sobre as entidades que seu serviço utiliza. Neste arquivo você pode marcar alguma propriedade para que seja usada do lado do client. Portanto você não precisa ficar replicando suas entidades de negócio que estão agora no Server para o lado do client, basta criar e expor quais propriedades você vai utilizar no client.

Além de dizer quais propriedades você vai expor, nesta classe você também configura a regra de cada uma delas: se uma propriedade é requerida, qual critério para validação, etc. Vamos ver como configurar estas regras mais adiante.

Adicionando o DomainDataSource no Silverlight

Até agora nós vimos todas as mudanças do RIAService no Server da aplicação Silverlight, vamos ver agora como tirar proveito desta novidade quando estiver desenvolvendo o client, ou seja, a aplicação Silverlight de fato.

Faça um Rebuild na solution, o Visual Studio irá atualizar a pasta Generated_Code do projeto SLAdventureWorks. Vamos utilizar a classe gerada pelo Visual Studio para comunicar a aplicação Silverlight com o Server e conseqüentemente o banco de dados.

O arquivo na pasta Generated_Code com nome de HostAdventureWorks define a classe AdventureWorksDataContext com os métodos para gerenciar a entidade Product que escolhemos quando definimos o DomainDataService no Server. A diferença e que a classe AdventureWorksDataContext está no lado do cliente, e pode ser instanciada em qualquer lugar da sua aplicação Silverlight e fazer uma chamada ao servidor, muito fácil, simples e rápido. Você pode fazer isto via código C# ou definir via XAML. Vamos ver como fica acessando via XAML veja na Listagem 1.

Listagem 1. Configurando o DomainDataSource via XAML


  <UserControl x:Class="SLAdventureWorks.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:service="clr-namespace:System.Windows.Controls;assembly=System.Windows.Ria.Controls"
      xmlns:myApp="clr-namespace:HostAdventureWorks">
      <Grid x:Name="LayoutRoot" Background="White">            
          <service:DomainDataSource x:Name="AdventureWorksDataSource" LoadMethodName="LoadProduct">
              <service:DomainDataSource.DomainContext>
                  <myApp:AdventureWorksDataContext />
              </service:DomainDataSource.DomainContext>
          </service:DomainDataSource>        
      </Grid>
  </UserControl>

De uma olhada neste XAML, o primeiro passo é incluir o assembly System.Windows.Ria.Controls e o namespace HostAdventureWorks. Feito isso voce já pode colocar o DomainDataSource, neste caso demos o nome de AdventureWorksDataSource que fica dentro do namespace service. Depois de colocar o DomainDataSource, você deve configuar o AdventureWorksDataContext que fica no namespace myApp como DomainContext. No exemplo eu já configurei também a propriedade LoadMothodName com o nome do metódo que carrega os produtos no nosso AdventureWorksDataContext.

Pronto, somente isso para fazer com que nossa aplicação Silverlight se conecte com o servidor e carregue os dados pelo nosso DomainService.

Listando os produtos no Silverlight

Para comprovar, vamos adicionar um DataGrid na interface e popular com as informacoes. Veja a Listagem 2 como fica o trecho de código com o DataGrid.

Listagem 2. DataGrid para exibir os dados


  <UserControl x:Class="SLAdventureWorks.MainPage"
      …
      xmlns:data="clr-namespace:System.Windows.Controls;assembly=
  System.Windows.Controls.Data"
      …
      >
      <Grid x:Name="LayoutRoot" Background="White">        
          …
          <data:DataGrid x:Name="AdventureGrid" HorizontalAlignment="Stretch"
                         AutoGenerateColumns="false" 
                         ItemsSource="{Binding ElementName=AdventureWorksDataSource, Path=Data}">            
              <data:DataGrid.Columns>
                  <data:DataGridTextColumn Header="Id" Binding="{Binding ProductID}" />
                  <data:DataGridTextColumn Header="Nome" Binding="{Binding Name}"/>
                  <data:DataGridTextColumn Header="Ultima Modificação" Binding="{Binding ModifiedDate}" />                
              </data:DataGrid.Columns>                        
          </data:DataGrid>    
  </Grid>
  </UserControl>

Para incluir o DataGrid, é necessário incluir o assembly System.Windows.Controls.Data. Depois configurar a propriedade ItemsSource com um Binding direto para o nosso DomainDataSource. Deste modo o grid irá apresentar os dados que o método do DataSource reupera, no momento em que ele for carregado. Você pode ou não definir as colunas do DataGrid, se você não defini-las e a propriedade AutoGenerateColumns do grid estiver True, ele irá criar as colunas automaticamente. A Figura 9 mostra o DataGrid populado com os dados de Produto retornado pelo Server.

Figura 9. Listando os produtos no DataGrid

Nota do DevMan

O Binding com ElementName é uma novidade do Silverlight 3, com ele você tem a possibilidade de fazer binding entre componentes, coisa que até a versão dois não era possível. Para fazer o Binding entre os componentes basta dizer o nome do componente que você vai ligar na propriedade ElementName e colocar na propriedade Path o nome da propriedade do componente que você vai utilizar.

Exibindo detalhes do produto em um DataForm

O DataForm é um controle muito flexível para apresentar dados de uma única entidade. Este controle possui alguns métodos para apresentar, atualizar e navegar pelos dados. Quando combinado com outros controles, o DataForm fornece um método simples de se conectar ao DataContext, alem disso, possui uma interface muito simples e que pode ser completamente customizada.

Vamos usá-lo para apresentar detalhes do produto que está selecionado no DataGrid. Veja na Listagem 3 o trecho da declaração do DataForm no XAML.

Listagem 3. Adicionando um DataForm para mostrar detalhes do Produto


  <UserControl x:Class="SLAdventureWorks.MainPage"
      …
      xmlns:df="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm"   
      HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
      <Grid x:Name="LayoutRoot" Background="White" >
    …
          <df:DataForm Header="Detalhes do Produto" Grid.Column="1" AutoGenerateFields="False"
                       HorizontalAlignment="Stretch" Orientation="Horizontal"
                       ItemsSource="{Binding ElementName=AdventureWorksDataSource, Path=Data}" 
                       >            
              <df:DataForm.Fields>
                  <df:DataFormFieldGroup>
                      <df:DataFormTextField Binding="{Binding ProductID}" IsReadOnly="True" FieldLabelContent="Id"/>
                      <df:DataFormTextField Binding="{Binding Name}" FieldLabelContent="Nome"/>
                      <df:DataFormTextField Binding="{Binding Size}" FieldLabelContent="Tamanho"/>                    
                      <df:DataFormCheckBoxField Binding="{Binding MakeFlag}" FieldLabelContent="Flag"/>                    
                      <df:DataFormSeparator />
                      <df:DataFormDateField Binding="{Binding ModifiedDate}" FieldLabelContent="Ultima Modificação"/>
                  </df:DataFormFieldGroup>                
              </df:DataForm.Fields>
          </df:DataForm>        
      </Grid>
  </UserControl>

Para incluir o controle DataForm é preciso adicionar o assembly System.Windows.Controls.Data.DataForm, este assembly possui outros componentes interessantes como por exemplo o DataPager para fazer paginação. Como no DataGrid você pode ou não definir quais campos você quer apresentar, você pode configurar a propriedade AutoGenerateFields para que o DataForm se cuide de criar os campos, para simplificar o formulário vamos incluir apenas alguns campos no formulário. Você só precisa configurar a propriedade ItemsSource com o DataSource que você deseja apresentar e pronto.

Grande parte do trabalho que tínhamos que programar antes, o componente já nos fornece, tais como, validação dos campos, binding para apresentação dos dados, navegação pelos dados e as operações de CRUD. Veja na Figura 10 o DataForm exibindo os dados de detalhes do produto.

Figura 10. DataForm com detalhes do produto

Nota DevMan

Quando estiver utilizando o DataGrid ou o DataForm no modo de geração automática de colunas e campos conforme o DataSource, ou seja, com as propriedades AutoGenerateColumn e AutoGenerateFields com valor True, o Silverlight cria o layout destes componentes somente quando o DataSource é populado. Para que isso não ocorra você precisará configurar as colunas do DataGrid e os campos do DataForm.

Validando o formulário através do arquivo metadata

Você deve se lembrar do arquivo AdventureWorksDomainService.metadata.cs, este arquivo foi gerado junto com o DomainService, dentro deste arquivo está definido a classe ProductMetadata, dentro desta classe nós podemos adicionar alguns atributos de lógica de aplicação que serão utilizados pelo Silverlight. Veja na Listagem 4 as regras definidas para as propriedades ProductID e Name.

Listagem 4. Atributos para validação dos dados


  internal sealed class ProductMetadata
  {
   
  // Metadata classes are not meant to be instantiated.
        private ProductMetadata()
        {
        }
   
        [Display(Name = "Id", Description = "Id do Produto")]
        [Required(ErrorMessage="Campo Id é Obrigatório")]
        [StringLength(3)]
        public int ProductID;
   
        [Display(Name="Nome",Description="Nome do Produto")]
        [Required(ErrorMessage = "Campo Nome é Obrigatório")]
        [StringLength(20)]
        public string Name;
   
        public string ProductNumber;
        public bool MakeFlag;
  ...
  ...
  }

Você pode definir através de atributos que tipo de validação o seu DataForm do Silverlight irá fazer. Existem muitos outros atributos, vale a pena estudar as possibilidades do que você pode fazer. Esta classe ProductMetadata é utilizada para agregar informações para a classe de Produto original, o código desta classe é compartilhado entre client e o server. Para testar estas alterações salve este arquivo, build a solution novamente e rode a aplicação. Veja Figura 11 o DataForm apresentando feedback de erro de validação.

Figura 11. Validação automática pelo DataForm

Conclusão

O .NET RIA Service como vimos é uma poderosa ferramenta para se utilizar quando estiver desenvolvendo aplicações Silverlight, com ele você também pode facilmente adicionar paginação, filtros de busca, etc. A idéia é que a equipe de desenvolvimento possa se dedicar mais em atender as regras de negócios e não precise ficar programando esse tipo de coisa que existe na maioria dos projetos. Para mais referências sobre esses métodos, aconselho a leitura e acompanhamento dos links a seguir:

Links

Brad Adams
http://blogs.msdn.com/brada

Tim Heuer
http://timheuer.com/blog/

Nikhil Kothari
http://www.nikhilk.net/