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:
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
:
- Instancia o
TodoService
como uma instância de nível de classe - Cria uma coleção chamada
Items
para armazenarTodoItem
objetos - Especifica um ponto de extremidade personalizado para a propriedade opcional
Url
noTodoService
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.