Persistência de dados em aplicações Silverlight


Grande parte das aplicações Web, independentemente de qual tecnologia ela foi criada, tem a necessidade de manter informações por um determinado tempo. Essas informações, na maioria das vezes, refletem alguma configuração definida pelo cliente, que customiza alguma seção do aplicativo, e quer manter isso em algum local para não precisar refazê-la mais tarde.

Quando estamos falando em uma aplicação desenvolvida em ASP.NET, você utiliza algumas funcionalidades definidas pela tecnologia, tais como Session, Caching, Profile, ViewState ou Cookies, para atingir esse objetivo. A escolha entre qual utilizar, vai depender do escopo, performance e nível de segurança. Esses detalhes devem ser cuidadosamente analisados, tentando equilibrar cada um dos pontos mencionados.

Aplicações construídas em Silverlight também tem a mesma necessidade, precisando, de alguma forma, armazenar informações para serem utilizadas posteriormente. Como sabemos, o Silverlight possui uma versão do .NET Framework exclusiva, trazendo várias APIs para o gerenciamento de estado. Como o aplicativo desenvolvido em Silverlight está rodando no navegador, você não tem acesso à variáveis de sessão, Caching ou Profile, já que estão acessíveis apenas pelo ASP.NET e do lado do servidor. Devido a isso, a Microsoft disponibilizou no Silverlight o Isolated Storage. Esse recurso não é exclusidade do Silverlight, e já está disponível no .NET Framework desde a sua primeira versão, e foi reescrito para o Silverlight, ganhando alguns novos conceitos.

Com o Isolated Storage podemos montar uma estrutura de arquivos para a aplicação, armazenando qualquer tipo de informação, desde um simples arquivo texto até um arquivo mais complexo (como a serialização de um objeto em formato binário/Xml). Do ponto de vista do desenvolvedor, temos uma estrutura para armazenamento das informações bem próximo ao que é o sistema de arquivos. O Isolated Storage é como os cookies (armazenar do lado do cliente), mas ao invés de armazenar somente chave/valor (strings), é um sistema de arquivos virtual, dando muito mais flexibilidade e segurança.

Apesar de uma aplicação Silverlight também ser acessada e executada através de um navegador, ela diferente bastante de uma aplicação Web tradicional. Ao contrário dessas aplicações tradicionais, que são executadas no servidor e apenas o HTML correspondente é enviado ao cliente, aplicações Silverlight são consideradas parcialmente confiáveis, e rodam dentro do navegador em um ambiente conhecido como “sandboxing”, que protegem o computador do cliente de aplicações maliciosas, evitando que aplicações Silverlight acessem recursos da máquina, compromentendo-a.

Antes de trabalharmos com o Isolated Storage, precisamos conhecer como funciona o nível de isolamento que ele fornece. O isolamento permitirá definirmos o escopo de acesso de uma determinada informação. O Silverlight possui dois níveis de isolamento: usuário + aplicação ou usuário + site. O primeiro deles irá isolar as informações pelo usuário dentro da aplicação (XAP), estando acessíveis somente a partir da mesma. Já a segunda opção, irá isolar as informações pelo usuário dentro do site, e todas as aplicações Silverlight que estão acessíveis a partir do mesmo site (domínio), irão compartilhar a informação de acordo com o usuário. É importante ficar claro que cada usuário tem dois locais de armazenamento, sendo um deles exclusivo para uma determinada aplicação, enquanto o outro pode ser acessado de qualquer aplicação, desde que esteja dentro daquele mesmo site.

O local de armazenamento e leitura dos arquivos estão condicionados ao usuário que está acessando a aplicação. Isso quer dizer que o Silverlight somente poderá acessar (para leitura ou gravação) o diretório local, que estará localizado debaixo do perfil do usuário atual. Esse caminho poderá variar de acordo com o sistema operacional, onde no Windows Vista está em C:Users<Usuario>AppDataLocaLowMicrosoftSilverlightis e no Windows XP em C:Docuemnts and Settings<Usuario>Local SettingsApplication DataMicrosoftSilverlightis. É importante dizer que você não precisa se preocupar com o endereço, pois ao utilizar o Isolated Storage, ele se encarregará de salvar ou ler as informações do local correto, não permitindo que uma aplicação maliciosa acesse, de forma arbitrária, o sistema de arquivos da máquina cliente, comprometendo a segurança.

Depois da parte teórica, vamos analisar a API que temos disponível para manipular o Isolated Storage. Basicamente temos quatro classes a nossa disposição, estando todas elas debaixo do namespace System.IO.IsolatedStorage, mas separadas em dois assemblies diferentes, sendo o mscorlib.dll e o System.Windows.dll.

A primeira classe que temos é a IsolatedStorageFile. A finalidade desta classe é representar uma das areas disponíveis no Isolated Storage para um determinado usuário, abstraindo o sistema de arquivos virtual que ele nos fornece. Essa classe não pode ser instanciada diretamente; ao invés disso, ela possui dois métodos estáticos chamados GetUserStoreForApplication e GetUserStoreForSite, quais retornam instâncias da mesma, com as respectivas áreas de armazenamento. A partir da instância desta classe, podemos criar, excluir ou enumerar diretórios e arquivos. Para efetuar essas tarefas, essa classe fornece métodos autoexplicativos, tais como: CreateDirectory, DeleteDirectory, GetFilesNames, GetDirectoryNames, DeleteFile e CreateFile.

Os métodos para recuperar arquivos ou diretórios pode, opcionalmente, receber uma string, representando um critério de busca, especificando um subdiretório, ou até mesmo utilizar o caracter “*”, para refinar ainda mais a busca. O método CreateFile cria o arquivo desejado e retorna uma instância da classe IsolatedStorageFileStream, representando o arquivo recém-criado, para que você consiga gravar ou ler as informações do mesmo. O exemplo abaixo ilustra como proceder para criar e ler um arquivo dentro do repositório de uma aplicação específica:

//Criando o Arquivo
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
    using (IsolatedStorageFileStream stream = store.CreateFile(“Teste.txt”))
        using (StreamWriter sw = new StreamWriter(stream))
            sw.WriteLine(“Teste”);

//Lendo o Arquivo
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
    using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(“Teste.txt”, FileMode.Open, store))
        using (StreamReader sr = new StreamReader(stream))
            MessageBox.Show(sr.ReadToEnd());

Observação: Os exemplos acima não estão contemplando o tratamento de erros. Todas as operações que se faz com o Isolated Storage, você deve envolver em um bloco try/catch, monitorando por possíveis exceções do tipo IsolatedStorageException. Um cenário onde ela pode ser lançada, é quando o usuário desabilita o acesso ao Isolated Storage ou atinge a cota máxima.

Cotas

Imagine que uma determinada aplicação possui um código malicioso, que cria arquivos sem nenhum controle. Em breve, não haverá mais espaço disponível no disco do cliente, que foi todo tomado pela aplicação. Felizmente o Isolated Storage disponibiliza o conceito de cotas. As cotas são um recurso bastante interessante, garantindo que a quantidade de informações geradas pela aplicação não ultrapasse um limite imposto pelo Silverlight. O Silverlight utiliza o conceito de grupos para gerenciar as cotas. Com isso, aplicações oriundas de um mesmo site, compartilham a mesma cota.

Por padrão temos 1MB de espaço disponível para cada grupo. Com uma aplicação Silverlight rodando no navegador, ao clicar com o botão direito, você tem a opção Silverlight Configuration. Ao abrir a janela, haverá uma aba chamada Application Storage. Lá temos a relação dos sites que estão fazendo uso deste recurso, exibindo o tamanho atual e o máximo permitido. Essa tela de configuração ainda permite você gerenciar o Isolated Storage, como excluí-los ou até mesmo desabilitá-lo. A imagem abaixo exibe essas configurações:

A partir da instância da classe IsolatedStorageFile temos acesso à alguns membros, que permitem manipular as cotas. O primeiro deles é a propriedade AvailableFreeSpace, que como o próprio nome diz, retorna a quantidade de espaço disponível para aquela “store”. Ainda temos a propriedade Quota, que representa a quantidade máxima permitida para aquela “store”.

A idéia do Isolated Storage é armazenar poucas informações, e justamente por isso, que 1MB é um valor razoável. Mas e se precisarmos de um tamanho maior para armazenar as informações que estão sendo geradas pelas aplicações? É neste momento que entra em cena o método IncreateQuotaTo. Este método recebe como parâmetro a nova cota, retornando um valor boleano indicando se a alteração foi ou não realizada com sucesso. Isso se deve ao fato de que somente podemos aumentar a capacidade de armazenamento do Isolated Storage, com o consentimento do usuário. Ao chamar esse método, uma mensagem aparece na aplicação (como mostrado na figura abaixo), informando o usuário se ele permite ou não esse crescimento.

O código abaixo ilustra como podemos proceder para efetuar o aumento da capacidade do Isolated Storage para 10MB, utilizando os membros que vimos acima:

int space = 1024 * 1024 * 10;

using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
    if (store.AvailableFreeSpace < space)
        if (store.IncreaseQuotaTo(space))
            MessageBox.Show(“Cota aumentada com sucesso.”);

Persistindo Objetos

Em algumas situações podemos querer armazenar instâncias de classes que a aplicação manipula, para mais tarde recuperá-las e dar prosseguimento ao que usuário estava fazendo, evitando que ele refaça essas tarefas. Para atingir esse objetivo, basta serializarmos o objeto em formato binário ou Xml com os formatadores que já conhecemos, em conjunto com o Stream gerado pelo Isolated Storage.

Como isso será uma tarefa comum, a Microsoft facilitou a vida dos desenvolvedores, criando uma classe chamada de IsolatedStorageSettings (a única que está contida no Assembly System.Windows.dll). Essa classe nada mais é do que um dicionário de dados, onde a chave é do tipo string e o valor do tipo object, ou seja, podemos armazenar a instância de qualquer objeto do .NET (desde que ele seja serializável).

Essa classe não pode ser instanciada diretamente pela aplicação. Ao invés disso, você captura as instâncias predefinidas a partir de duas propriedades estáticas que ela mesma fornece: ApplicationSettings e SiteSettings. Escolher qual delas usar, irá depender do nível de compartilhamento das informações que você desejar, assim como já vimos acima.

Para manipular esse dicionário, podemos utilizar os conhecidos métodos Add e o indexer, que dado um chave retorna o respectivo valor. Se informar uma chave inexistente para o indexer, uma exceção será disparada. Para evitar isso, essa mesma classe fornece um método chamado TryGetValue, que dado a chave e um parâmetro de saída representando o valor correspondente, retorna um valor boleano indicando se foi ou não possível recuperar o valor. Esse procedimento é mostrado através do código a seguir:

IsolatedStorageSettings store = IsolatedStorageSettings.ApplicationSettings;
store.Add(“Cliente”, new Cliente() { Email = “ia@israelaece.com”, Nome = “Israel Aece” });

Cliente cliente = null;

if (store.TryGetValue<Cliente>(“Cliente”, out cliente))
    MessageBox.Show(cliente.Nome);

Conclusão: Vimos no decorrer deste artigo os benefícios e facilidades que temos ao trabalhar com ele, mas devemos levar em consideração que essas informações ficam armazenadas no disco, e alguém pode encontrar os arquivos gerados e manipulá-los, comprometendo a aplicação. Justamente por isso, nunca armazene informações sensíveis dentro dele, ou de qualquer arquivo no disco, a menos que esteja devidamente protegido.

PersistenciaDeDadosEmSL.zip (63.76 kb)

Anúncios

Um comentário sobre “Persistência de dados em aplicações Silverlight

  1. Muito bem explicado, parabéns.
    Estava em dúvida se usava Cookies ou IsolatedStorage, mas esse post me ajudou a decidir sobre Storage.

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s