Share via


Consumir um Serviço Web ASP.NET (ASMX)

O ASMX fornece a capacidade de criar serviços Web que enviam mensagens usando o protocolo SOAP (Simple Object Access Protocol). O SOAP é um protocolo independente de plataforma e linguagem para criar e acessar serviços Web. Os consumidores de um serviço ASMX não precisam saber nada sobre a plataforma, o modelo de objeto ou a linguagem de programação usada para implementar o serviço. Eles só precisam entender como enviar e receber mensagens SOAP. Este artigo demonstra como consumir um serviço ASMX SOAP de um Xamarin.Forms aplicativo.

Uma mensagem SOAP é um documento XML que contém os seguintes elementos:

  • Um elemento raiz chamado Envelope que identifica o documento XML como uma mensagem SOAP.
  • Um elemento Header opcional que contém informações específicas do aplicativo, como dados de autenticação. Se o elemento Header estiver presente, ele deverá ser o primeiro elemento filho do elemento Envelope .
  • Um elemento Body necessário que contém a mensagem SOAP destinada ao destinatário.
  • Um elemento Fault opcional usado para indicar mensagens de erro. Se o elemento Fault estiver presente, ele deverá ser um elemento filho do elemento Body .

O SOAP pode operar em muitos protocolos de transporte, incluindo HTTP, SMTP, TCP e UDP. No entanto, um serviço ASMX só pode operar por HTTP. A plataforma Xamarin oferece suporte a implementações SOAP 1.1 padrão sobre HTTP, e isso inclui suporte para muitas das configurações de serviço ASMX padrão.

Este exemplo inclui os aplicativos móveis executados em dispositivos físicos ou emulados e um serviço ASMX que fornece métodos para obter, adicionar, editar e excluir dados. Quando os aplicativos móveis são executados, eles se conectam ao serviço ASMX hospedado localmente, conforme mostrado na captura de tela a seguir:

Aplicativo de exemplo

Observação

No iOS 9 e superior, o App Transport Security (ATS) impõe conexões seguras entre recursos da Internet (como o servidor back-end do aplicativo) e o aplicativo, evitando assim a divulgação acidental de informações confidenciais. Como o ATS está habilitado por padrão em aplicativos criados para iOS 9, todas as conexões estarão sujeitas aos requisitos de segurança do ATS. Se as conexões não atenderem a esses requisitos, elas falharão com uma exceção. O ATS pode ser desativado se não for possível usar o protocolo e a HTTPS comunicação segura para recursos da Internet. Isso pode ser feito atualizando o arquivo Info.plist do aplicativo. Para obter mais informações, consulte Segurança de transporte de aplicativo.

Consumir o serviço Web

O serviço ASMX fornece as seguintes operações:

Operação Descrição Parâmetros
GetTodoItems Obter uma lista de itens pendentes
CreateTodoItem Criar um novo item de tarefa pendente Um TodoItem serializado XML
EditTodoItem Atualizar um item pendente Um TodoItem serializado XML
DeleteTodoItem Excluir um item pendente Um TodoItem serializado XML

Para obter mais informações sobre o modelo de dados usado no aplicativo, consulte Modelando os dados.

Criar o proxy TodoService

Uma classe proxy, chamada TodoService, estende SoapHttpClientProtocol e fornece métodos para comunicação com o serviço ASMX por HTTP. O proxy é gerado adicionando uma referência da Web a cada projeto específico da plataforma no Visual Studio 2019 ou Visual Studio 2017. A referência da Web gera métodos e eventos para cada ação definida no documento WSDL (Web Services Description Language) do serviço.

Por exemplo, a GetTodoItems ação de serviço resulta em um GetTodoItemsAsync método e um GetTodoItemsCompleted evento no proxy. O método gerado tem um tipo de retorno void e invoca a GetTodoItems ação na classe pai SoapHttpClientProtocol . Quando o método invocado recebe uma resposta do serviço, ele dispara o GetTodoItemsCompleted evento e fornece os dados de resposta dentro da propriedade do Result evento.

Criar a implementação ISoapService

Para permitir que o projeto compartilhado entre plataformas funcione com o serviço, o exemplo define a ISoapService interface, que segue o modelo de programação assíncrona de tarefa em C#. Cada plataforma implementa o para expor o proxy específico da ISoapService plataforma. O exemplo usa TaskCompletionSource objetos para expor o proxy como uma interface assíncrona de tarefa. Detalhes sobre o uso TaskCompletionSource são encontrados nas implementações de cada tipo de ação nas seções abaixo.

O exemplo SoapService:

  1. Instancia o TodoService como uma instância de nível de classe
  2. Cria uma coleção chamada Items para armazenar TodoItem objetos
  3. Especifica um ponto de extremidade personalizado para a propriedade opcional Url no TodoService
public class SoapService : ISoapService
{
    ASMXService.TodoService todoService;
    public List<TodoItem> Items { get; private set; } = new List<TodoItem>();

    public SoapService ()
    {
        todoService = new ASMXService.TodoService ();
        todoService.Url = Constants.SoapUrl;
        ...
    }
}

Criar objetos de transferência de dados

O aplicativo de exemplo usa a TodoItem classe para modelar dados. Para armazenar um TodoItem item no serviço Web, ele deve primeiro ser convertido para o tipo gerado TodoItem pelo proxy. Isso é realizado pelo ToASMXServiceTodoItem método, conforme mostrado no exemplo de código a seguir:

ASMXService.TodoItem ToASMXServiceTodoItem (TodoItem item)
{
    return new ASMXService.TodoItem {
        ID = item.ID,
        Name = item.Name,
        Notes = item.Notes,
        Done = item.Done
    };
}

Esse método cria uma nova ASMService.TodoItem instância e define cada propriedade para a propriedade idêntica da TodoItem instância.

Da mesma forma, quando os dados são recuperados do serviço Web, eles devem ser convertidos do tipo gerado TodoItem pelo proxy em uma TodoItem instância. Isso é realizado com o FromASMXServiceTodoItem método, conforme mostrado no exemplo de código a seguir:

static TodoItem FromASMXServiceTodoItem (ASMXService.TodoItem item)
{
    return new TodoItem {
        ID = item.ID,
        Name = item.Name,
        Notes = item.Notes,
        Done = item.Done
    };
}

Esse método recupera os dados do tipo de proxy gerado TodoItem e os define na instância recém-criada TodoItem .

Recuperar dados

A ISoapService interface espera que o RefreshDataAsync método retorne um Task com a coleção de itens. No entanto, o TodoService.GetTodoItemsAsync método retorna void. Para satisfazer o padrão de interface, você deve chamar GetTodoItemsAsync, aguardar o acionamento do GetTodoItemsCompleted evento e preencher a coleção. Isso permite que você retorne uma coleção válida para a interface do usuário.

O exemplo abaixo cria um novo TaskCompletionSource, inicia a chamada assíncrona RefreshDataAsync no método e aguarda o Task fornecido pelo TaskCompletionSource. Quando o TodoService_GetTodoItemsCompleted manipulador de eventos é invocado, ele preenche a Items coleção e atualiza o TaskCompletionSource:

public class SoapService : ISoapService
{
    TaskCompletionSource<bool> getRequestComplete = null;
    ...

    public SoapService()
    {
        ...
        todoService.GetTodoItemsCompleted += TodoService_GetTodoItemsCompleted;
    }

    public async Task<List<TodoItem>> RefreshDataAsync()
    {
        getRequestComplete = new TaskCompletionSource<bool>();
        todoService.GetTodoItemsAsync();
        await getRequestComplete.Task;
        return Items;
    }

    private void TodoService_GetTodoItemsCompleted(object sender, ASMXService.GetTodoItemsCompletedEventArgs e)
    {
        try
        {
            getRequestComplete = getRequestComplete ?? new TaskCompletionSource<bool>();

            Items = new List<TodoItem>();
            foreach (var item in e.Result)
            {
                Items.Add(FromASMXServiceTodoItem(item));
            }
            getRequestComplete?.TrySetResult(true);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(@"\t\tERROR {0}", ex.Message);
        }
    }

    ...
}

Para obter mais informações, consulte Modelo de programação assíncrona e TPL e Programação assíncrona tradicional do .NET Framework.

Criar ou editar dados

Ao criar ou editar dados, você deve implementar o ISoapService.SaveTodoItemAsync método. Esse método detecta se o TodoItem é um item novo ou atualizado e chama o método apropriado no todoService objeto. Os CreateTodoItemCompleted manipuladores de eventos e EditTodoItemCompleted também devem ser implementados para que você saiba quando o todoService recebeu uma resposta do serviço ASMX (eles podem ser combinados em um único manipulador porque executam a mesma operação). O exemplo a seguir demonstra a interface e as implementações do manipulador de eventos, bem como o TaskCompletionSource objeto usado para operar de forma assíncrona:

public class SoapService : ISoapService
{
    TaskCompletionSource<bool> saveRequestComplete = null;
    ...

    public SoapService()
    {
        ...
        todoService.CreateTodoItemCompleted += TodoService_SaveTodoItemCompleted;
        todoService.EditTodoItemCompleted += TodoService_SaveTodoItemCompleted;
    }

    public async Task SaveTodoItemAsync (TodoItem item, bool isNewItem = false)
    {
        try
        {
            var todoItem = ToASMXServiceTodoItem(item);
            saveRequestComplete = new TaskCompletionSource<bool>();
            if (isNewItem)
            {
                todoService.CreateTodoItemAsync(todoItem);
            }
            else
            {
                todoService.EditTodoItemAsync(todoItem);
            }
            await saveRequestComplete.Task;
        }
        catch (SoapException se)
        {
            Debug.WriteLine("\t\t{0}", se.Message);
        }
        catch (Exception ex)
        {
            Debug.WriteLine("\t\tERROR {0}", ex.Message);
        }
    }

    private void TodoService_SaveTodoItemCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
    {
        saveRequestComplete?.TrySetResult(true);
    }

    ...
}

Excluir os dados

A exclusão de dados requer uma implementação semelhante. Defina um TaskCompletionSource, implemente um manipulador de eventos e o ISoapService.DeleteTodoItemAsync método:

public class SoapService : ISoapService
{
    TaskCompletionSource<bool> deleteRequestComplete = null;
    ...

    public SoapService()
    {
        ...
        todoService.DeleteTodoItemCompleted += TodoService_DeleteTodoItemCompleted;
    }

    public async Task DeleteTodoItemAsync (string id)
    {
        try
        {
            deleteRequestComplete = new TaskCompletionSource<bool>();
            todoService.DeleteTodoItemAsync(id);
            await deleteRequestComplete.Task;
        }
        catch (SoapException se)
        {
            Debug.WriteLine("\t\t{0}", se.Message);
        }
        catch (Exception ex)
        {
            Debug.WriteLine("\t\tERROR {0}", ex.Message);
        }
    }

    private void TodoService_DeleteTodoItemCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
    {
        deleteRequestComplete?.TrySetResult(true);
    }

    ...
}

Testar o serviço Web

O teste de dispositivos físicos ou emulados com um serviço hospedado localmente requer a Configuração personalizada do IIS, endereços de ponto de extremidade e regras de firewall para estar em vigor. Para obter mais detalhes sobre como configurar seu ambiente para teste, consulte Configurar o acesso remoto ao IIS Express. A única diferença entre testar o WCF e o ASMX é o número da porta do TodoService.