Consumindo Serviços ASMX com Xamarin Forms

Disponível também em inglês

Quando eu comecei a trabalhar com Xamarin Forms uma das primeiras coisas que eu precisei fazer foi consumir serviços. Quando a gente usa o Xamarin Forms para consumir API RestFull é bem fácil. Mas, serviços ASMX você vai precisar implementar algumas coisas para as diferentes plataformas iOS e Android.

Primeiramente, eu criei um projeto cross-plataform Xamarin Forms portable no Visual Studio 2015. Para esse artigo eu não uso nenhuma biblioteca de terceiros para consumir os serviços. Eu gosto de criar as minhas próprias implementações para aprender.

Blz, vamos começar!

 
Consumindo Serviços ASMX com Xamarin Forms
 

O que a gente precisa?

1 – Uma interface para o serviço que contenha todos os métodos que a gente precisa. Essa interface ficará no projeto portable.
2 – A referência ao serviço em si. Precisa ser referenciado em ambos os projetos Xamarin.iOS e Xamarin.Droid projects.
3 – Uma classe que implementa a interface criada anteriormente. Essa classe será um wrapper para o serviço ASMX. Precisam ser criadas duas classes em cada uma das plataformas both Xamarin.Droid e Xamarin.iOS. Então, sim, você precisará criar duas classes.
4 – Adiconar uma dependency injection para essa interface em ambos os projetos Xamarin.Droid e Xamarin.iOS projects.
5 – Uma propriedade estática no projeto portable para consumir o serviço. Essa propriedade será injetada pelo Xamarin Forms.

Blz, pare! Como essas coisas irão funcionar? Vamos ver a implementação no projeto Droid…

Vamos dizer que você tem uma view e você precisa exibir todos os clientes que são retornados através do serviço ASMX. No serviço tem um método que recebe como parâmetro um critério de filtro e retorna essa lista de clientes.

Primeiro, referencie o serviço ASMX no projeto Xamarin.Droid.

Segundo, criei a interface “ICustomerSoapService” e um método GetAllCustomers.

public interface ICustomer
{
        string Name {get;set;}
        string Id {get;set;}
}

public interface ICustomerSoapService
{
        Task<List<ICustomer>> GetAllCustomers(string criteria = null);
}

Certo, agora crie uma classe “CustomerSoapService” no projeto Xamarin.Droid e implemente a interface “ICustomerSoapService”

[assembly: Dependency(typeof(FSL.XF2.Droid.CustomerSoapService))]

namespace FSL.XF2.Droid
{
    public sealed class CustomerSoapService : ICustomerSoapService
    {
        CustomersWs.Customers service;

        public CustomerSoapService()
        {
            service = new CustomersWs.Customers()
            {
                Url = "http://localhost/FSL.WS/Customers.asmx"
            };
        }

        public async Task<List<ICustomer>> GetAllCustomers(string criteria = null)
        {
            return await Task.Run(() =>
            {
                var result = service.GetAllCustomers();

                return new List<ICustomer>(result);
            });
        }
    }
}

O código acima “CustomersWs” é a referência ao web service.

No projeto portable, cria a propriedade para ser injetada via dependency injection.

public partial class App : Application
{
        private static ICustomerSoapService _customerSoapService;
        public static ICustomerSoapService CustomerSoapService
        {
            get
            {
                if (_customerSoapService== null)
                {
                    _customerSoapService = DependencyService.Get<ICustomerSoapService>();
                }

                return _customerSoapService;
            }
        }
}

A propriedade acima usa o conceito de Lazy Loading, ou seja, o Xamarin Forms somente injetará a instancia da interface se a propriedade for usada.

Finalmente para chamar o método na view use da seguinte forma:

var customers = await App.CustomerSoapService.GetAllCustomers();

Download full source code:
FSL.ConsummingAsmxServicesInXamarinForms

Bom é isso. Esperto que tenha ajudado.

Abaixo encontrará alguns links úteis.

Consumindo Serviços ASMX com Xamarin Forms

ASMX : Perguntas, sugestões ou críticas são bem vindas. Boa sorte!

Faça download completo do código fonte no github.
Sobre o Autor:
Trabalha como arquiteto de soluções e desenvolvedor, tem mais de 16 anos de experiência em desenvolvimento de software em diversas plataformas sendo mais de 14 anos somente para o mercado de seguros.
  • Herick Faro

    Parabéns Fábio pelo artigo. Salvo engano, este foi o primeiro sobre o tem a SOAP em Xamarin em português e detalhado. Como faço para invocar os item da minha List de Customer em uma ListView? Detalhando: Como posso fazer o cast da variável customers e resgatar o Id e o Name da cada customers?

    var customers = await App.CustomerSoapService.GetAllCustomers();

    Obrigado e aguardo retorno.

    • E aí @herickfaro:disqus! Obrigado pela pergunta.

      No meu repositório do github tem uma partial class com o mesmo nome da classe que está no Reference.cs do serviço ASMX:

      namespace FSL.XF2.Droid.CustomersWs
      {
      public partial class Customer : ICustomer
      {
      }
      }

      O CAST é feito automaticamente.

      A sua listview tem que receber um objeto List.
      Se você tiver uma model diferente na listview, basta implementar essa interface na sua model.

      Agora se você quiser pegar o item ao clicar na listview você faz da seguinte forma:

      private async void ListaView_ItemTapped(object sender, ItemTappedEventArgs e)
      {
      var customer = e.Item as ICustomer;
      }

      Na variável customer terá as propriedades que você quer. É isso que você queria saber?

      Depois que fechar o entendimento vou colocar essa explanação no artigo.

      • Herick Faro

        Obrigado pela resposta! Mas acredito que devo detalhar ainda mais minha dúvida:
        No projeto PCL/Portable, como eu faço para recuperar a List em uma ListView?
        Como eu posso recuperar da variável customers já que ela é do tipo assíncrona?

        Minha tentativa:
        List Items = new List();
        var customers = await App.CustomerSoapService.GetAllCustomers();
        listview1.ItemsSource = customers;

        Como fazer o método assíncrono para carregar a ListView?

        Obrigado!

        • Herick, seguinte, acabei de atualizar o repositório do github.

          Para popular o listview:

          protected override async void OnAppearing()
          {
          base.OnAppearing();

          lvCustomers.BeginRefresh();

          var customers = await App.CustomerSoapService.GetAllCustomers();

          lvCustomers.ItemsSource = customers;
          lvCustomers.EndRefresh();
          }

          Para capturar a lista inteira ou um item:

          private async void lvCustomers_ItemTapped(object sender, ItemTappedEventArgs e)
          {
          var customer = e.Item as ICustomer;

          var allCustomers = lvCustomers.ItemsSource as List;
          }

          A variável customers já não é mais ASYNC por causa do AWAIT que tem antes.

          Ajuda?

          • Herick Faro

            Olá Fabio! Ajuda sim! Ficou mais claro!
            Porém, no OnAppearing() quando eu realizo o debug percebi que acontece algo que ele não passa do var customers = await App.CustomerSoapService.GetAllCustomers(); e as demais variáveis não são atribuídas depois desta linha.
            Será que está faltando algum BindingContext?

          • Herick Faro

            Fabio! Descobri a falha. A Url estava apontando para, acredito, o seu IP. Alterei, mas creio que seja algo do firewall ou outra configuração do IIS Express. Estou tentando aqui.
            Url = “http://10.0.2.2/FSL.WS/Customers.asmx”

            Obrigado!

          • Herick, quando abre do simulador mobile é essa url mesmo, basta vc criar um diretorio virtual no IIS para esse servico asms com o nome de FSL.WS. Eu ja ia fazer isso amanha de manha publicando no meu site. Blz?

          • Herick, quando abre do simulador mobile é essa URL mesmo, basta vc criar um diretório virtual no IIS para esse serviço ASMX com o nome de FSL.WS. Eu já ia fazer isso amanha de manha publicando no meu site. Blz?

          • @herickfaro:disqus conseguiu? abs

          • Herick Faro

            @fabio_silva_lima:disqus, Bom dia!
            Perdoe-me pela demora no retorno. Somente hoje consegui, depois de várias tentativas. Executei o MS VS 2015 como administrador e conseguir carregar a lista de custormers na ListView, sem qualquer mudança de IP. Sinceramente, não entendi realmente o que aconteceu (acredito que foi algum configuração de firewall ou semelhante).

            Agradeço a atenção! Parabéns mais uma vez pelo artigo!

            Abs,
            Herick