Este artigo foi traduzido por máquina.

Pontos de dados

Agregado de dados E armazenamento isolado no Silverlight

John Papa

Download do código disponível na Galeria de código do MSDN
Procure o código on-line

Conteúdo

Obtendo concluída
Solicitações de Web HTTP e Threading
Adicionar um feed
Análise de feeds
Solicitações entre domínios para feeds
Armazenamento isolado básico
Organizar o armazenamento isolado
Wrap-Up

O Silverlight é ideal para a criação de um aplicativo de leitor de notícias distribuído. Ele pode ler RSS e AtomPub agregados formatos, se comunicar com serviços da Web por meio de solicitações HTTP e lidar com as diretivas de domínio cruzado. Depois que os dados distribuídos foi recebidos, ele pode ser lido em uma estrutura de classe, analisado com o LINQ e apresentados ao usuário via ligação de dados baseada em XAML.

Nesta coluna, demonstrarei como utilizar esses recursos exclusivos para criar um leitor de notícias distribuído. Eu também mostrará como depurar problemas com comunicações de serviço da Web do Silverlight e como armazenar dados localmente usando isolado armazenamento. Todos os exemplos estão disponíveis no download do código do MSDN.

Obtendo concluída

Distribuição de alimentação fornece acesso aos formatos de RSS e AtomPub por meio de serviços da Web. Cada feed é acessado por um URI que retorna o XML contendo os itens alimentação usando os formatos de RSS ou AtomPub. O aplicativo de exemplo fornecido com esta coluna demonstra técnicas que ler dados distribuídos usando solicitações de serviço da Web em um aplicativo do Silverlight. Antes de mergulhar em detalhes, pode ser útil se eu Mostrar da versão concluída do aplicativo. Em seguida, abordarei a lógica e vários outros aspectos do código do aplicativo.

A Figura 1 mostra o aplicativo de Silverlight leitura desses dois feeds distribuídos:

 http://pipes.yahooapis.com/pipes/pipe.run?_id=957­
    d9624940693fb9f9644d7b12fb0e9&_render=rss 
http://pipes.yahooapis.com/pipes/pipe.run?_id=057559bac7aad6640b­
    c17529f3421db0&_render=rss 

fig01.gif

Figura 1 O SilverlightSyndicationApplication

Uma solicitação da Web é feita para coletar os dados de alimentação quando o usuário clica no botão Adicionar. URI a alimentação é armazenado localmente no computador cliente, e o título do serviço alimentação é exibido no controle Data­Grid superior.

Armazenar o feed URI no computador cliente permite que o aplicativo Silverlight obter os dados alimentação para os feeds quando o aplicativo é iniciado. Quando os dados de feeds são reunidos, os itens são colocados em uma lista de objetos e, em seguida, analisado usando LINQ. Os resultados, em seguida, são ligados ao controle Data­Grid inferior em ordem classificada.

Solicitações de Web HTTP e Threading

Consumir feeds agregados de aplicativos do Silverlight começa com poder fazer solicitações da Web. Tanto o Web­Client as classes HttpWebRequest podem tornar Web HTTP solicitações de aplicativos do Silverlight. A primeira etapa do processo é decidir que técnica usar para fazer solicitações de Web HTTP. Na maioria dos casos, a classe de WebClient é tudo o que é necessária, pois é mais simples usar (ele também chama o HttpWebRequest nos bastidores). HttpWebRequest permite mais personalização das solicitações.

Este trecho de código demonstra como fazer uma solicitação por meio do WebClient:

//feedUri is of type Uri 
WebClient request = new WebClient();
request.DownloadStringCompleted += AddFeedCompleted;
request.DownloadStringAsync(feedUri);

O código a seguir, por outro lado, mostra como fazer uma chamada semelhante usando HttpWebRequest:

//feedUri is of type Uri 
WebRequest request = HttpWebRequest.Create(feedUri);
request.BeginGetResponse(new AsyncCallback(ReadCallback), request);

A classe de WebClient é mais fácil de usar porque ele encapsula algumas das funcionalidades da classe HttpWeb­Request.

Desde que todas as solicitações de Web HTTP do Silverlight são feitas de forma assíncrona por meio de WebClient e HttpWebRequest, é importante compreender como processar os dados quando as chamadas de retornam. Quando HttpWebRequest faz suas chamadas assíncronas e sua conclusão, o manipulador de evento concluído não certamente estar operando no thread da interface do usuário. Se os dados foram recuperados e deve ser exibido em um elemento de interface do usuário, a chamada para o elemento de interface do usuário deve ser feita usando uma técnica que transfere o controle novamente para o segmento de interface do usuário do thread em segundo plano. Isso pode ser feito com o Dispatcher ou através da classe SynchronizationContext. O código a seguir mostra como fazer uma chamada utilizando o segmento de interface do usuário com BeginInvoke método a classe Dispatcher:

Deployment.Current.Dispatcher.BeginInvoke(() =>
     {
         MyDataGrid.DataContext = productList;
     });

Este exemplo de código usa a variável productList (que foi preenchida os dados retornados de uma chamada de serviço da Web) e define-lo como DataContext de um elemento de interface do usuário. Nesse caso, um DataGrid agora será ser ligado à lista de produtos. O Dispatcher não é necessário, no entanto, se a chamada foi feita através da classe do WebClient. Nesse caso, o código pode simplesmente definir a lista de produtos diretamente ao DataContext do elemento da interface do usuário.

Para usar a classe SynchronizationContext, uma instância da classe Synchronization­Context deve ser criada em um local onde o thread da interface do usuário é costumam estar disponíveis. O construtor e o manipulador de eventos de carga são bons locais para criar a instância de um Synchronization­Context. Este exemplo de código mostra o campo de _syncContext sendo inicializado no construtor de classe:

public Page() {
_syncContext = SynchronizationContext.Current;
}

E este código mostra da instância de SynchronizationContext usando o método Post para fazer a chamada ao método LoadProducts. Ele se certifica que o método LoadProducts tenha acesso ao segmento de interface do usuário:

if (_syncContext != null) {
  _syncContext.Post(delegate(object state){ LoadProducts(products); } 
  ,null);
}

Além de ser mais fácil de usar, solicitações de WebClient sempre voltar no thread da interface do usuário. Isso significa que nenhum resultado da solicitação o WebClient pode ser facilmente vinculado a elementos da interface do usuário sem ter que envolver o Dispatcher (ou, opcionalmente, a classe Synchronization­Context em vez do dispatcher). De leitura de dados distribuídos, a classe de WebClient é adequada e será usada para aplicativo de exemplo desta coluna.

Adicionar um feed

No aplicativo de exemplo, quando o usuário insere um endereço de alimentação e clica no botão Adicionar, o código mostrado na Figura 2 é executado. Primeiro o código tenta criar um URI do endereço, usando o método Uri.TryCreate se possível. Se ele pode criar um URI, o URI é retornado para o feedUri variável local. Caso contrário, feedUri permanece nulos e o código é encerrado.

A Figura 2 Adicionando um feed

private void btnAdd_Click(object sender, RoutedEventArgs e)
{
    Uri feedUri;
    Uri.TryCreate(txtAddress.Text, UriKind.Absolute, out feedUri);
    if (feedUri == null)
        return;

    LoadFeed(feedUri);
}

public void LoadFeed(Uri feedUri)
{
    WebClient request = new WebClient();
    request.DownloadStringCompleted += AddFeedCompleted;
    request.DownloadStringAsync(feedUri);
}

Depois que um URI válido é criado, o método LoadFeed é executado, fazendo a solicitação HTTP para coletar os dados alimentação usando a classe Web­Client. A instância de WebClient é criada e um manipulador de eventos é atribuído ao evento DownloadStringCompleted. Quando o método DownloadStringAsync é executado e está pronto para retornar os dados, ele precisa saber o manipulador de eventos para ir para. É por isso que o manipulador de eventos (no caso, AddFeedCompleted) deve ser atribuído antes que o evento assíncrono seja executado.

Uma vez que a solicitação seja concluída, o manipulador de eventos AddFeedCompleted executará (veja a Figura 3 ). O parâmetro DownloadStringCompleted­EventArgs contém uma propriedade Result e uma propriedade de erro, que são importantes para verificar após cada solicitação da Web. A propriedade e.Error será nula se não tenha havido erros durante a solicitação. A propriedade e.Result contém os resultados da solicitação da Web. Para o aplicativo de exemplo, e.Result irá conter o XML que representa os dados de alimentação.

A Figura 3 AddFeedCompleted

private void AddFeedCompleted(object sender, 
    DownloadStringCompletedEventArgs e)
{
    if (e.Error != null)
        return;
    string xml = e.Result;
    if (xml.Length == 0)
        return;
    StringReader stringReader = new StringReader(xml);
    XmlReader reader = XmlReader.Create(stringReader);
    SyndicationFeed feed = SyndicationFeed.Load(reader);
    if (_feeds.Where(f => f.Title.Text == feed.Title.Text).ToList().Count > 0)
        return;
    _feeds.Add(feed); // This also saves the feeds to isolated storage
    ReBindAggregatedItems();
    txtAddress.Text = string.Empty;
}

Depois que os dados de feeds são reunidos, ele pode ser lido na classe System.Ser­vice­Model.SyndicationFeed usando método de carga a classe SyndicationFeed do. Observe que ao recuperar dados de alimentação e usá-lo em uma forma de somente leitura, usando LINQ para XML para recuperar o feed e carregá-lo em um objeto personalizado talvez uma opção melhor que SyndicationFeed. SyndicationFeed tem mais recursos, mas se eles não estão sendo usado pode não ser vale a pena o tamanho adicional ao XAP — SyndicationFeed adiciona 150KB sobre o XAP enquanto LINQ para XML adiciona sobre 40KB. Com a capacidade adicional do SyndicationFeed você também tem alguns custos de tamanho.

SyndicationFeed é uma classe especial que sabe como representar dados feeds (RSS e AtomPub) como um objeto. Ele tem propriedades que descrevem a alimentação, como título e descrição, bem como uma propriedade de itens que contém um IEnumerable <syndicationitem>. Cada instância de classe SyndicationItem representa um item de alimentação para a alimentação. Por exemplo, os feeds são representados por instâncias da classe SyndicationFeed, e suas coleções de itens contêm as postagens individuais de feeds.

Depois que a classe SyndicationFeed é carregada com o feed e seus itens, o código mostrado na Figura 3 verifica se o mesmo feed já foram coletado. Nesse caso, o código sai imediatamente. Caso contrário, o feed é adicionado para o local ObservableCollection <Syndication­Feed> chamado _feeds. Por meio do método ReBindAggregatedItems, os alimentação itens de todos os feeds carregados são, em seguida, filtrados, classificados e vinculados ao DataGrid inferior. Desde que a classe WebClient fez a solicitação da Web de HTTP, o manipulador de eventos AddFeedCompleted terá acesso ao segmento de interface do usuário. Esse é o motivo pelo qual o código dentro do método ReBind­Ag­gregatedItems pode ligar os dados para o elemento da interface do usuário de DataGrid sem a ajuda do dispatcher.

Análise de feeds

Quando o método ReBindAggregatedItems é executado, os dados de feeds são armazenados em uma coleção de instâncias de SyndicatedFeed e seus respectivos conjuntos de SyndicatedItem instâncias. LINQ é ideal para consultar os dados de feeds porque está agora em uma estrutura de objeto. Os dados não precisam ser carregado em SyndicatedFeed objetos. Em vez dele poderia ter foi mantido em seu formato XML nativo (como RSS ou AtomPub), e ele pode ter sido analisado usando um XmlReader ou LINQ para XML. No entanto, a classe SyndicatedFeed facilita a gerenciar e LINQ ainda pode ser usado para consultar os dados.

A exibição de itens feeds para vários feeds requer que os itens do feeds são todos mashed juntos. A consulta LINQ mostrada na Figura 4 demonstra como capturar todos os itens alimentação (instâncias Syndication­Item) para todos os feeds (instâncias SyndicationFeed) e classificá-los por sua data de publicação.

A Figura 4 consultar feeds com o LINQ

private void ReBindAggregatedItems()
{
    //Read the feed items and bind them to the lower list
    var query = from f in _feeds
                from i in f.Items
                orderby i.PublishDate descending
                select new SyndicationItemExtra
                        { FeedTitle = f.Title.Text, Item = i };

    var items = query.ToList();
    feedItemsGridLayout.DataContext = items;
}

Observe na Figura 4 que a consulta retorna uma lista das classes SyndicationItemExtra. A classe SyndicationItemExtra é uma classe personalizada que tenha a propriedade de FeedTitle do tipo seqüência de caracteres e uma propriedade de item do tipo SyndicationItem. O aplicativo exibe os itens de alimentação em DataGrid, e a maior parte dos dados para que isso pode ser encontradas na classe SyndicationItem.

No entanto, como o aplicativo mashes juntos itens de vários feeds, exibir o título do feed para cada item de alimentação faz claro qual feed cada item provém. O título para o feed não é acessível a partir da classe SyndicationItem, para que o aplicativo usa uma classe personalizada chamada SyndicationItemExtra, que armazenará o SyndicationItem e o título a alimentação.

Os itens de alimentação, em seguida, são vinculados ao feedItemsGridLayout do painel de grade no aplicativo do Silverlight. O painel de grade contém o DataGrid, bem como outros elementos de interface do usuário (tais como o número de itens exibidos em um TextBlock) envolvidas nas operações de ligação de dados para exibir informações sobre os itens do feeds.

Solicitações entre domínios para feeds

Solicitações para reunir feeds são que solicitações de Web HTTP que geralmente fazer solicitações para um domínio da Web diferente. Qualquer solicitação da Web do Silverlight que se comunica com um domínio diferente do que hospeda o aplicativo de Silverlight deve cumprir a diretiva de domínio cruzado o domínio remoto. O diagrama na Figura 5 demonstra essa situação.

fig05.gif

A Figura 5 entre domínios chamada para um feed

Para obter mais informações sobre diretivas de domínio cruzado, consulte meuColuna de pontos de dados de 2008 de setembro. Coluna aborde os formatos de arquivo e como as diretivas funcionam.

Quando uma solicitação da Web de HTTP é feita entre domínios, o Silverlight preempts a solicitação, primeiro solicitando o arquivo de diretiva entre domínios do servidor Web remoto. O Silverlight primeiro procura para o arquivo clientaccesspolicy.xml (o arquivo de diretiva de domínio cruzado do Silverlight), e se não for encontrado, ele, em seguida, procura o arquivo crossdomain.xml (o arquivo de diretiva de domínio cruzado flash). Se nenhum arquivo for encontrado, a solicitação falhará e um erro é lançado. Este erro pode ser detectado no manipulador de eventos DownloadStringCompleted e apresentado ao usuário, se desejar.

Por exemplo, se o http://johnpapa URI. NET/feed/default.aspx é inserido no aplicativo de exemplo, o Silverlight primeiro irá procurar por um dos arquivos diretiva de domínio cruzado na johnpapa. rede raiz do servidor Web. Se nenhum dos arquivos for encontrado, um erro será retornado para o aplicativo, no ponto que o aplicativo pode notificar o usuário se desejar. a Figura 6 mostra a FireBug plug-in, que é controle todas as solicitações do navegador. Ela mostra o navegador procurando os arquivos de diretiva de domínio cruzado, não encontrá-los e retornar sem na verdade, fazendo a solicitação para o RSS feed.

fig06.gif

A Figura 6 depuração entre domínios feed chamadas

FireBug é uma excelente ferramenta para assistir a solicitações HTTP no Firefox, e Web Development Helper é uma ferramenta excelente ao usar o Internet Explorer. Outra opção é Fiddler2, que é um aplicativo autônomo que pode assistir a todo o tráfego na seu computador.

Uma solução para esse problema é peça ao administrador da Web para a alimentação para colocar um arquivo de clientaccesspolicy.xml na raiz do servidor Web. Isso pode não ser realista, desde que você provavelmente não controlar o servidor Web remoto nem você sabe quem faz. Outra opção é ver se a alimentação usa um serviço intermediário, como pipes do Yahoo. Por exemplo, o principal de alimentação no johnpapa. NET pode ser recuperada por meio de pipes ele usando o http://pipes.yahooapis.com/pipes/pipe.run?\_id=057559bac7aad6640bc17529f­3421db0&\_render=r URI. Como não há um arquivo de diretiva de domínio cruzado localizado em http://pipes.yahooapis.com/clientaccesspolicy.xml que permite acesso aberto, isso é uma boa alternativa.

Uma terceira opção é usar um serviço, como Popfly ou FeedBurner para agregar os feeds, efetivamente retransmissão-los através de um serviço que também possui uma diretiva de domínio cruzado aberta. Por fim, uma quarta opção seria escrever seu próprio serviço da Web personalizado que coleta os feeds e, em seguida, transmite-los para o aplicativo do Silverlight. Usem um serviço, como Popfly ou ele pipes oferece as soluções mais simples.

Armazenamento isolado básico

O aplicativo de exemplo que permite ao usuário adicionar vários feeds e exibir todos os itens para cada um desses feeds. Se um usuário insere 10 feeds e decide que ele precisa fechar o aplicativo e vêm volta posteriormente para lê-las, ele provavelmente esperaria que os feeds poderiam ser lembrados pelo aplicativo. Caso contrário, ele teria de digitar o URI para cada feed sempre que o aplicativo é aberto. Como desses feeds não são específicos a um usuário, elas podem ser armazenadas no servidor usando alguns token para identificar o usuário que inseriu-los ou no computador do usuário.

O Silverlight permite que os dados ser armazenado para uma área protegida do computador do usuário usando as classes no namespace System.IO.IsolatedStorage. Armazenamento isolado do Silverlight é como os cookies no steroids: ele permite que você armazenar valores escalares simples ou até mesmo armazenar gráficos de objetos complexos serializados no computador cliente. A maneira mais simples para salvar em armazenamento isolado é criar uma entrada de ApplicationSettings e colocar os dados, conforme mostrado aqui:

private void SaveFeedsToStorage_UsingSettings()
{
    string data = GetFeedsFromStorage_UsingSettings() + FEED_DELIMITER + 
        txtAddress.Text;
    if (IsolatedStorageSettings.ApplicationSettings.Contains(FEED_DATA))
        IsolatedStorageSettings.ApplicationSettings[FEED_DATA] = data;
    else
        IsolatedStorageSettings.ApplicationSettings.Add(FEED_DATA, data);
}

<syndicationfeed>Isso pode ser chamado toda vez que um SyndicationFeed é adicionada ou removida da instância Ob­serv­ableCollection < SyndicationFeed > campo chamada _feeds. Desde que o ObservableCollection expõe um evento CollectionChanged, um manipulador pode ser atribuído ao evento que executa o salvamento, conforme mostrado aqui:

_feeds.CollectionChanged += ((sender, e) => { 
                               SaveFeedsToStorage_UsingSettings(); });

Quando o método SaveFeedsToStorage_UsingSettings é executado, ele chama primeiro o método de GetFeedsFromStorage_UsingSettings, que captura os endereços de todos os feeds do armazenamento isolado e os coloca em uma única seqüência de caracteres delimitada por um caractere especial.

Quando o aplicativo é iniciado pela primeira vez, o método de LoadFeedsFromStorage_UsingSettings recupera os feeds do armazenamento isolado:

private void LoadFeedsFromStorage_UsingSettings()
{
    string data = LoadFeedsFromStorage_UsingSettings();
    string[] feedList = data.Split(new string[1] { FEED_DELIMITER }, 
      StringSplitOptions.RemoveEmptyEntries);
    foreach (var address in feedList)
        LoadFeed(new Uri(address));
}

O código primeiro lê a lista de endereços URI para cada feed do armazenamento isolado. Em seguida, ele itera através os endereços e carrega cada indivíduo feed um de cada vez, usando o método LoadFeed.

Organizar o armazenamento isolado

Esse recurso permite que o aplicativo Lembre-se os endereços de alimentação para o usuário e carregá-los quando o usuário executa o aplicativo. Remessa URI endereços em uma seqüência delimitada por é simples, mas nem elegante extensos. Por exemplo, se você quiser armazenar mais do que apenas um único valor escalar, isso poderia obter complicado de usar essa técnica.

Outra maneira de armazenar dados no armazenamento isolado é usar as classes Isolated­StorageFile e IsolatedStorageFileStream, que permitem a você armazenar estruturas de dados mais complexas, incluindo serializado objetos, por usuário. Os dados ainda podem ser segmentados em diferentes arquivos e pastas em armazenamento isolado. Isso é ideal para organizar os dados que serão salvas no armazenamento isolado. Por exemplo, uma pasta pode ser criada para todas as listas estáticas dos dados, e um arquivo separado para cada lista pode ser criado. Portanto, em uma pasta no armazenamento isolado, pode existir um arquivo para prefixos de nome, outro para sexo e outra do governo informa.

O aplicativo de exemplo poderia criar um arquivo no armazenamento isolado para conter a lista de endereços de URI. Os dados devem primeiro ser serializado e, em seguida, enviadas para o arquivo no armazenamento isolado (conforme mostrado na Figura 7 ). Primeiro, uma instância da classe IsolatedStorageFile para o usuário atual é criada usando o método GetUserStoreForApplication. Em seguida, um fluxo de arquivos é criado para o aplicativo pode escrever o endereço de URI. Os dados, em seguida, são serializados e gravados a instância Isolated­StorageFileStream. O exemplo para este aplicativo serializa uma seqüência de caracteres, mas qualquer objeto pode ser serializado pode ser gravado bem armazenamento isolado.

Salvar a Figura 7 serializado dados para um arquivo de armazenamento isolado

private void SaveFeedsToStorage_UsingFile() {
    using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
        List<string> data = GetFeedsFromStorage_UsingFile();
        if (data == null)
            if (txtAddress.Text.Length == 0)
                return;
            else
                data = new List<string>();
         using (var isoStoreFileStream =
                new IsolatedStorageFileStream(FEED_FILENAME,
                   FileMode.Create, isoStore)) {
            data.Add(txtAddress.Text);
            byte[] bytes = Serialize(data);
            isoStoreFileStream.Write(bytes, 0, bytes.Length);
        }
    }
}

Lendo os dados serializados check-out de um arquivo de armazenamento isolado é um pouco mais envolvida que o exemplo anterior. a Figura 8 mostra que primeiro você deve obter uma instância da classe IsolatedStorageFile para o usuário e, em seguida, verificar se o arquivo existe antes de lê-lo. Se o arquivo existir, o arquivo é aberto para acesso de leitura, que permite que os dados ser lido por meio de um fluxo de tipo IsolatedStorageFileStream. Os dados é lidos no fluxo, juntar e, em seguida, desserializados para que ele possa ser usado para carregar os feeds distribuídos.

A Figura 8 Leituras serializado dados a partir de um arquivo de armazenamento isolado

private List<string> GetFeedsFromStorage_UsingFile() {
    byte[] feedBytes;
    var ms = new MemoryStream();
    using (var isoStore = 
      solatedStorageFile.GetUserStoreForApplication())
    {
        if (!isoStore.FileExists(FEED_FILENAME)) return null;
        using (var stream = isoStore.OpenFile(FEED_FILENAME, 
          FileMode.Open, FileAccess.Read))  {
            while (true) {
                byte[] tempBytes = new byte[1024];
                int read = stream.Read(tempBytes, 0, tempBytes.Length);
                if (read <= 0) {
                    //feedBytes = ms.ToArray();
                    break;
                }
                ms.Write(tempBytes, 0, read);
            }
        }
        feedBytes = ms.ToArray();
        List<string> feedList = Deserialize(typeof(List<string>), 
            feedBytes) as List<string>;
        return feedList;
    }
}

private void LoadFeedsFromStorage_UsingFile() {
    var feedList = GetFeedsFromStorage_UsingFile();
    foreach (var address in feedList) {
        Uri feedUri;
        Uri.TryCreate(address, UriKind.Absolute, out feedUri);
        if (feedUri != null)
            LoadFeed(feedUri);
    }
}

Para estruturas de dados mais simples, usando serializado objetos e arquivos no armazenamento isolado não podem ser necessários.No entanto, quando o armazenamento isolado é usado para vários tipos de armazenamento local, ele pode ajudar a organizar os dados e fornecem acesso fácil a ler e gravar nela.Armazenamento isolado deve ser usado organizadamente para armazenar dados que devem ser armazenada em cache localmente.

Observe também que os usuários podem, em última análise, desmarcar o armazenamento a qualquer momento, pois eles têm controle total sobre suas configurações.Isso significa que dados armazenados no armazenamento isolado não devem ser considerados garantido armazenamento persistente.Outro bom exemplo é armazenar uma lista dos EUAEstados no armazenamento isolado portanto, uma Web solicitação (e o impacto de banco de dados) não precisa ser feitas sempre que uma caixa de combinação precisa ser preenchido com uma lista dos EUAinforma.

Wrap-Up

O aplicativo de exemplo demonstra como é fácil carregar alimentações RSS e AtomPub em um aplicativo do Silverlight.O Silverlight torna possível fazer com que da Web solicitação, aceitar seus resultados, lidar com chamadas de diretiva de domínio cruzado, carregar dados de alimentação em classes SyndicationFeed, consultá-los com o LINQ, ligá-los a elementos da interface do usuário e armazenar dados de alimentação no armazenamento isolado.

Tanto no mês passado este mês, Hanu Kommalapati abordadas criando um aplicativo linha de negócios com o Silverlight, que você pode ler sobre em seu artigo"O Silverlight: criar aplicativos de empresa de linha de negócios com o Silverlight, parte 1"e"O Silverlight: criar aplicativos de empresa de linha de negócios com o Silverlight, parte 2."

Envie suas dúvidas e comentários para John ammdata@Microsoft.com.

John Papa(johnpapa.NET) é consultor sênior de comASPSOFTe um fã de beisebol que gasta noites de verão raiz pelos Yankees com sua família.John, um MVP C# e o orador da INETA, é autor de vários livros e agora está trabalhando em sua última, denominada Data-Driven Services with Silverlight 2.Ele geralmente fala em conferências, como DevConnections e VSLive.