Xamarin Forms -  Consumindo um serviço REST

 Vamos recordar como consumir um serviço REST no Xamarin Forms.

Vamos iniciar com um resumo sobre REST...

O que é REST ?

Representational State Transfer (REST) ​​é um estilo de arquitetura para a construção de serviços na web. As solicitações REST são feitas em HTTP usando os mesmos verbos HTTP que os navegadores da Web usam para recuperar páginas da Web e enviar dados para os servidores. Os verbos são:

GET - esta operação é usada para recuperar dados do serviço da web.
POST - esta operação é usada para criar um novo item de dados no serviço web.
PUT - esta operação é usada para atualizar um item de dados no serviço da web.
PATCH - esta operação é usada para atualizar um item de dados no serviço da Web, descrevendo um conjunto de instruções sobre como o item deve ser modificado.
DELETE - esta operação é usada para apagar um item de dados no serviço web.

As APIs de serviço da Web que aderem ao REST são chamadas de APIs RESTful e são definidas usando:

1- Uma URI base.
2- Métodos HTTP, como GET, POST, PUT, PATCH ou DELETE.
3- Um tipo de mídia para os dados, como JavaScript Object Notation (JSON).


A simplicidade do REST ajudou a torná-lo o principal método para acessar serviços da Web em aplicativos móveis.

 

Para consumir uma serviço RESTful primeiro você tem que ter o serviço disponível, geralmente através de uma URI. Esse serviço pode ter sido criado por você mesmo ou por terceiros.

 

Neste artigo eu não vou mostrar como criar um serviço REST então vamos consumir um serviço RestFul de terceiros, e, neste caso temos centenas de opções.

 

Vou usar o serviço disponbilizado neste link:  http://jsonplaceholder.typicode.com/posts  que retorna dados no formato json conforme mostra a figura abaixo obtida via navegador Chrome:

   

Assim já temos um serviço Restful pronto e agora vamos consumir esse serviço em uma aplicação Xamarin Forms que iremos criar no VS 2017 Community.

Recursos usados:

Criando o projeto e instalando as dependências

Abra o  VS 2017 Community e clique em New Project e a seguir escolha Cross Platform -> Mobile App (Xamarin.Forms) e informe o nome XF_Restful:

A seguir selecione a Plataforma, eu marquei somente Android, e escolha a estratégia de compartilhamento que será .NET Standard.

Clique no botão OK. (Eu estou criando apenas o projeto Android mas fique a vontade para criar os demais projetos)

Pronto nosso projeto já esta criado. (Atualmente(01/2019) a versão mais atual estável é a 3.5.0.129452)

Vamos agora incluir as referências a biblioteca Newntonsoft.Json que iremos usar para acessar o serviço REST e tratar os dados no formato Json.

No menu Tools clique em Nuget Package Manager e a seguir em Manage Nuget Packages for Solution;

Selecione a guia Browse e digite NewtonSoft. Localize a biblioteca e instale-a no projeto:

Nota: Na guia Updates(6) você pode atualizar a versão do Xamarin Forms e dos pacotes para Android.

Definindo o modelo de domínio

O serviço REST que vamos consumir expõe dados de Posts e possuem o formato: userId, Id, title e body

Dos dados expostos vamos exibir apenas o title, então precisamos definir uma classe contendo propriedades que mapeam para os dados que vamos exibir.

Vamos criar uma pasta Model no projeto e nesta pasta criar a classe Post com o código abaixo:

using Newtonsoft.Json;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace XF_Restful.Model
{
    public class Post : INotifyPropertyChanged
    {
        public int Id { get; set; }

        private string _title;
        //Mapeia o elemento title do serviço rest para o modelo
        [JsonProperty("title")]
        public string Title
        {
            get => _title;
            set
            {
                _title = value;
                //Notifica a sua View ou ViewModel que o valor que a propriedade
                //no modelo mudou e a view precisa ser atualizada

                OnPropertyChanged();
            }
        }

        //Método OnPropertyChanged()
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

    }
}

A classe Post representa os dados que vamos exibir (como vamos exibir apenas o title definimos apenas as propriedades id e title) e implementa a interface INotifyPropertyChanged que vai notificar a View de qualquer alteração que for feita no Model.

Definindo o código da MainPage

Agora vamos definir a interface com o usuário e vamos fazer isso no arquivo MainPage.xaml.

Vou usar uma interface bem simples usando um ListView e 3 botões com eventos que serão disparados para realizar as operações de Incluir, Atualizar e Deletar dados. (Uma abordagem mais robusta seria usar MVVM como eu já mostrei em outros artigos)

Abra o arquivo MainPage.xaml e inclua as seguintes views usando um layout StackLayout:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XF_Restful"
             x:Class="XF_Restful.MainPage"
             Title="Meus Posts" >

    <StackLayout>

        <ListView x:Name="lvwDados">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextCell Text="{Binding Title}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

        <StackLayout Orientation="Horizontal">
            <Button x:Name="btnAdd"
                BackgroundColor="Khaki"
                Clicked="OnAdd"
                Text="Incluir" />
            <Button  x:Name="btnUpdate"
                BackgroundColor="MediumPurple"
                Clicked="OnUpdate"
                HorizontalOptions="CenterAndExpand"
                Text="Atualizar" />
            <Button  x:Name="btnDelete"
                BackgroundColor="Crimson"
                Clicked="OnDelete"
                Text="Deletar" />
        </StackLayout>

    </StackLayout>

</ContentPage>

Perceba que definimos no ListView um TextCell usando o Binding com a propriedade Title do modelo Post.

Em cada botão de comando definimos os eventos OnAdd, OnUpdate e OnDelete que iremos usar para definir o código que vai realizar a inclusão, alteração e exclusão dos dados obtidos do serviço REST.

Definindo o código para acessar o serviço REST

Pois bem, como fazer para acessar o serviço REST e realizar as tarefas para incluir, alterar e excluir dados ?

Para obter informações em um serviço REST temos que usar uma requisição GET, para incluir usamos um POST, para alterar dados usamos PUT e para deletar dados usamos DELETE

Vamos realizar essas tarefas usando a classe HttpClient.

A classe HttpClient é a classe principal usada para enviar e receber mensagens HTTP através de HttpRequestMessage e HttpResponseMessage.  Se você já utilizou anteriormente as classes WebClient e HttpWebRequest vai notar que a classe HttpClient possui diferenças importantes a saber:

  1. Uma instância HttpClient é usada para configurar extensões, definir headers padrão, cancelar requests e mais;

  2. Você pode emitir tantos pedidos quantos quiser através de uma única instância HttpClient;

  3. HttpClients não estão vinculados a um determinado servidor HTTP ou host; você pode enviar qualquer solicitação HTTP usando a mesma instância HttpClient;

  4. Você pode derivar de HttpClient para criar clientes especializados para determinados sites ou padrões;

  5. A classe HttpClient usa o novo padrão orientada a tarefa (Task) para lidar com solicitações assíncronas, possibilitando assim, gerenciar e coordenar de forma mais fácil solicitações pendentes;

Para manter o exemplo bem simples vamos definir o código para realizar essas tarefas usando a classe HttpClient no arquivo MainPage.xaml.cs (Uma abordagem mais robusta seria criar um serviço para fazer isso).

Então vamos fazer isso passo a passo...

Abra o arquivo MainPage.xaml.cs e no início do arquivo vamos definir primeiro os namespaces usados

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net.Http;
using Xamarin.Forms;
using XF_Restful.Model;

A seguir vamos definir 3 itens importantes:

  1. A url que indica onde esta o serviço que vamos consumir;
  2. A instância de HttpClient que vamos usar para realizar as tarefas;
  3. Definir um ObservableCollection<Post> para poder sincronizar a atualização do modelo com a View;

        //Esta é a url publica que oferece o serviço
        private const string Url = "http://jsonplaceholder.typicode.com/posts";
        //Cria uma instância de HttpClient (Microsoft.Net.Http)
        private readonly HttpClient _client = new HttpClient();
        //Definimos uma coleção do tipo ObservableCollection que é coleção de dados dinâmica
        //e que permite atualizar o estado da UI em temporeal quando os dados forem alterados

        private ObservableCollection<Post> _posts;

 

1 - Acessando informações do serviço REST (GET)

Para acessar informações e exibir no ListView vamos usar o evento OnAppearing() da página que ocorre quando ela aparece.(Isso ocorre quando você navega para a página ou retorna a ela)


       
protected override async void OnAppearing()
        {
            // Envia uma requisição GET para a url especificada e retorna
            // o Response (Body) como uma string em uma operação assíncrona

            string content = await _client.GetStringAsync(Url);
            // Deserializa ou converte a string JSON em uma coleção de Post
            List<Post> posts = JsonConvert.DeserializeObject<List<Post>>(content);
            // Convertendo a Lista para uma ObservalbleCollection de Post
            _posts = new ObservableCollection<Post>(posts);
            //Atribui a ObservableCollection ao Listview lvwDados
            lvwDados.ItemsSource = _posts;
            base.OnAppearing();
        }

Executando o projeto neste momento teremos o seguinte resultado:

Para poder exibir o título "Meus Posts" abra o arquivo App.xaml.cs e altere o código do construtor da classe conforme a seguir:

public App()
{
      InitializeComponent();
      MainPage = new NavigationPage( new MainPage());
}

Vemos ao lado os dados disponibilizados pelo serviço REST sendo exibidos em nossa aplicação Xamarin Forms.

O método GetStringAsync(url) obtém os dados.

2 - Incluindo informações (POST)

Para incluir informações temos que criar um novo Post e enviar uma requisição POST.

        /// <summary>
        /// Evento Click do botão Incluir.
        /// Envia uma requisição POST incluindo um objeto Post no servidor e na coleção
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>

        private async void OnAdd(object sender, EventArgs e)
        {
            // Cria uma instância de Post atribuindo um TimeStamp à propriedade Title
            Post post = new Post { Title = $"Title: Timestamp {DateTime.UtcNow.Ticks}" };
            // Serializa ou converte o Post criado em uma string JSON
            string content = JsonConvert.SerializeObject(post);
            // Envia uma requisição POST para a Uri especificada em uma operação assíncrona
            // e com a codificação correta(utf8) e com o content type(application/json).

            await _client.PostAsync(Url, new StringContent(content, Encoding.UTF8, "application/json"));
            // Atualiza a UI inserindo um elemento na coleção
            _posts.Insert(0, post);
        }

Clicando 3 vezes botão Incluir teremos o seguinte resultado:

Vemos as informações com o TimeStamp sendo incluidas no ListView para os 3 objetos Post criados

Usamos o método PostAsync() passando a Url, e o conteúdo a ser incluindo com a codificdação utf8 e o content adequado.

3 - Alterando informações (PUT)

Para alterar informações devemos enviar uma requisição PUT e post que desejamos alterar. Estamos obtendo o segundo post da coleção e alterando.

        /// <summary>
        /// Evento Click do botão Atualizar
        /// Envia uma requisição PUT para atualizar o segundo objeto Post
        /// no servidor e na coleção
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>

        private async void OnUpdate(object sender, EventArgs e)
        {
            // Atribui o segundo objeto Post da Coleção para uma nova instância de Post
            Post post = _posts[1];
            // Anexa a string [atualizado] ao valor atual da propriedade Title
            post.Title += " [atualizado]";
            // Serializa ou converte o post criado em uma string JSON
            string content = JsonConvert.SerializeObject(post);
            // Envia uma requisição PUT para a uri definida como uma operação assincrona
            await _client.PutAsync(Url + "/" + post.Id, new StringContent(content, Encoding.UTF8, "application/json"));
        }
 

Clicando no botão Atualizar iremos obter o seguinte resultado:

Estamos usando o método PutAsync() passando a Url e o Id do Post mais o contéudo codificado com utf8 e com content adequado.

4 - Excluindo informações (DELETE)

Para excluir informações devemos enviar uma requisição DELETE e o post que desejamos excluir. Estamos excluindo o primeiro post da coleção.

         /// <summary>
        /// Evento Click do botão Deletar
        /// Envia uma requisição DELETE removendo o primeiro objeto post
        /// no servidor e na coleção
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>

        private async void OnDelete(object sender, EventArgs e)
        {
            // Atribui o primeiro objeto Post da Coleção para uma nova instância de Post
            Post post = _posts[0];
            // Envia uma requisição DELETE para a Uri de forma assíncrona
            await _client.DeleteAsync(Url + "/" + post.Id);
            // Remove a primeira ocorrencia do objeto especificado na coleção Post
            _posts.Remove(post);
        }
 

Abaixo temos o resultado obtido ao clicar no botão Deletar:

Usamos o método DeleteAsync() passando a Url e o id do post a ser excluído.

Vimos assim como é simples consumir um serviço REST no Xamarin Forms.

Pegue o código do projeto compartilhado aqui :     XF_Restful.zip  (sem as referências)

"E, quanto fizerdes por palavras ou por obras, fazei tudo em nome do Senhor Jesus, dando por ele graças a Deus Pai."
Colossenses 3:17

Referências:


José Carlos Macoratti