Consumo de servicios web de RESTful

Descargar ejemploDescargar el ejemplo

La integración de un servicio web en una aplicación es un escenario común. En este artículo se muestra cómo consumir un servicio web RESTful desde una Xamarin.Forms aplicación.

Transferencia de estado representacional (REST) es un estilo arquitectónico para compilar servicios web. Las solicitudes REST se realizan a través de HTTP con los mismos verbos HTTP que usan los exploradores web para recuperar páginas web y enviar datos a los servidores. Los verbos son:

  • GET: esta operación se usa para recuperar datos del servicio web.
  • POST: esta operación se usa para crear un nuevo elemento de datos en el servicio web.
  • PUT: esta operación se usa para actualizar un elemento de datos en el servicio web.
  • PATCH: esta operación se usa para actualizar un elemento de datos en el servicio web describiendo un conjunto de instrucciones sobre cómo se debe modificar el elemento. Este verbo no se usa en la aplicación de ejemplo.
  • DELETE: esta operación se usa para eliminar un elemento de datos en el servicio web.

Las API de servicio web que se adhieren a REST se denominan API de RESTful y se definen mediante:

  • Identificador URI base.
  • Métodos HTTP, como GET, POST, PUT, PATCH o DELETE.
  • Tipo de medio para los datos, como notación de objetos JavaScript (JSON).

Normalmente, los servicios web RESTful usan mensajes JSON para devolver datos al cliente. JSON es un formato de intercambio de datos basado en texto que genera cargas compactas, lo que produce requisitos de ancho de banda reducidos al enviar datos. La aplicación de ejemplo usa la biblioteca código abierto NewtonSoft JSON.NET para serializar y deserializar mensajes.

La simplicidad de REST ha ayudado a convertirla en el método principal para acceder a los servicios web en aplicaciones móviles.

Cuando se ejecute la aplicación de ejemplo, se conectará a un servicio REST hospedado localmente, como se muestra en la captura de pantalla siguiente:

Aplicación de ejemplo

Nota

En iOS 9 y versiones posteriores, App Transport Security (ATS) exige conexiones seguras entre recursos de Internet (como el servidor back-end de la aplicación) y la aplicación, lo que evita la divulgación accidental de información confidencial. Dado que ATS está habilitado de forma predeterminada en las aplicaciones compiladas para iOS 9, todas las conexiones estarán sujetas a los requisitos de seguridad de ATS. Si las conexiones no cumplen estos requisitos, se producirá un error con una excepción.

ATS puede rechazarse si no es posible usar el protocolo HTTPS y la comunicación segura para los recursos de Internet. Esto se puede lograr actualizando el archivo Info.plist de la aplicación. Para obtener más información, consulte App Transport Security.

Consumo del servicio web

El servicio REST se escribe mediante ASP.NET Core y proporciona las siguientes operaciones:

Operación HTTP method URI relativo Parámetros
Obtención de una lista de tareas pendientes GET /api/todoitems/
Crear un nuevo elemento de tareas pendientes POST /api/todoitems/ Un objeto TodoItem con formato JSON
Actualizar una tarea pendiente PUT /api/todoitems/ Un objeto TodoItem con formato JSON
Eliminar una tarea pendiente Delete /api/todoitems/{id}

La mayoría de los URI incluyen el TodoItem identificador en la ruta de acceso. Por ejemplo, para eliminar el TodoItem cuyo identificador es 6bb8a868-dba1-4f1a-93b7-24ebce87e243, el cliente envía una solicitud DELETE a http://hostname/api/todoitems/6bb8a868-dba1-4f1a-93b7-24ebce87e243. Para obtener más información sobre el modelo de datos usado en la aplicación de ejemplo, consulte Modelado de los datos.

Cuando el marco de api web recibe una solicitud, enruta la solicitud a una acción. Estas acciones son simplemente métodos públicos en la TodoItemsController clase . El marco de trabajo usa middleware de enrutamiento para buscar coincidencias con las direcciones URL de las solicitudes entrantes y asignarlas a acciones. Las API REST deben usar el enrutamiento de atributos del modelo de la funcionalidad de la aplicación como un conjunto de recursos cuyas operaciones se representan mediante verbos HTTP. El enrutamiento mediante atributos utiliza un conjunto de atributos para asignar acciones directamente a las plantillas de ruta. Para obtener más información sobre el enrutamiento de atributos, consulte Enrutamiento de atributos para las API REST. Para obtener más información sobre cómo crear el servicio REST mediante ASP.NET Core, consulte Creación de servicios back-end para aplicaciones móviles nativas.

La HttpClient clase se usa para enviar y recibir solicitudes a través de HTTP. Proporciona funcionalidad para enviar solicitudes HTTP y recibir respuestas HTTP de un recurso identificado de URI. Cada solicitud se envía como una operación asincrónica. Para obtener más información sobre las operaciones asincrónicas, vea Async Support Overview.

La HttpResponseMessage clase representa un mensaje de respuesta HTTP recibido del servicio web después de realizar una solicitud HTTP. Contiene información sobre la respuesta, incluido el código de estado, los encabezados y cualquier cuerpo. La HttpContent clase representa el cuerpo HTTP y los encabezados de contenido, como Content-Type y Content-Encoding. El contenido se puede leer mediante cualquiera de los ReadAs métodos, como ReadAsStringAsync y ReadAsByteArrayAsync, en función del formato de los datos.

Creación del objeto HTTPClient

La HttpClient instancia se declara en el nivel de clase para que el objeto resida mientras la aplicación necesite realizar solicitudes HTTP, como se muestra en el ejemplo de código siguiente:

public class RestService : IRestService
{
  HttpClient client;
  ...

  public RestService ()
  {
    client = new HttpClient ();
    ...
  }
  ...
}

Recuperación de datos

El HttpClient.GetAsync método se usa para enviar la solicitud GET al servicio web especificado por el URI y, a continuación, recibir la respuesta del servicio web, como se muestra en el ejemplo de código siguiente:

public async Task<List<TodoItem>> RefreshDataAsync ()
{
  ...
  Uri uri = new Uri (string.Format (Constants.TodoItemsUrl, string.Empty));
  ...
  HttpResponseMessage response = await client.GetAsync (uri);
  if (response.IsSuccessStatusCode)
  {
      string content = await response.Content.ReadAsStringAsync ();
      Items = JsonSerializer.Deserialize<List<TodoItem>>(content, serializerOptions);
  }
  ...
}

El servicio REST envía un código de estado HTTP en la HttpResponseMessage.IsSuccessStatusCode propiedad para indicar si la solicitud HTTP se realizó correctamente o no. Para esta operación, el servicio REST envía el código de estado HTTP 200 (CORRECTO) en la respuesta, lo que indica que la solicitud se realizó correctamente y que la información solicitada está en la respuesta.

Si la operación HTTP se realizó correctamente, se lee el contenido de la respuesta para mostrarlo. La HttpResponseMessage.Content propiedad representa el contenido de la respuesta HTTP y el HttpContent.ReadAsStringAsync método escribe de forma asincrónica el contenido HTTP en una cadena. A continuación, este contenido se deserializa de JSON a una List de TodoItem instancias.

Advertencia

El uso del ReadAsStringAsync método para recuperar una respuesta grande puede tener un impacto negativo en el rendimiento. En tales circunstancias, la respuesta debe deserializarse directamente para evitar tener que almacenarla completamente en búfer.

Crear datos

El HttpClient.PostAsync método se usa para enviar la solicitud POST al servicio web especificado por el URI y, a continuación, para recibir la respuesta del servicio web, como se muestra en el ejemplo de código siguiente:

public async Task SaveTodoItemAsync (TodoItem item, bool isNewItem = false)
{
  Uri uri = new Uri (string.Format (Constants.TodoItemsUrl, string.Empty));

  ...
  string json = JsonSerializer.Serialize<TodoItem>(item, serializerOptions);
  StringContent content = new StringContent (json, Encoding.UTF8, "application/json");

  HttpResponseMessage response = null;
  if (isNewItem)
  {
    response = await client.PostAsync (uri, content);
  }
  ...

  if (response.IsSuccessStatusCode)
  {
    Debug.WriteLine (@"\tTodoItem successfully saved.");
  }
  ...
}

La TodoItem instancia se serializa en una carga JSON para enviar al servicio web. A continuación, esta carga se inserta en el cuerpo del contenido HTTP que se enviará al servicio web antes de que se realice la solicitud con el PostAsync método .

El servicio REST envía un código de estado HTTP en la HttpResponseMessage.IsSuccessStatusCode propiedad para indicar si la solicitud HTTP se realizó correctamente o no. Las respuestas comunes para esta operación son:

  • 201 (CREATED): la solicitud dio lugar a que se creara un nuevo recurso antes de enviar la respuesta.
  • 400 (SOLICITUD INCORRECTA): el servidor no entiende la solicitud.
  • 409 (CONFLICT): no se pudo realizar la solicitud debido a un conflicto en el servidor.

Actualización de datos

El HttpClient.PutAsync método se usa para enviar la solicitud PUT al servicio web especificado por el URI y, a continuación, recibir la respuesta del servicio web, como se muestra en el ejemplo de código siguiente:

public async Task SaveTodoItemAsync (TodoItem item, bool isNewItem = false)
{
  ...
  response = await client.PutAsync (uri, content);
  ...
}

La operación del PutAsync método es idéntica al PostAsync método que se usa para crear datos en el servicio web. Sin embargo, las posibles respuestas enviadas desde el servicio web difieren.

El servicio REST envía un código de estado HTTP en la HttpResponseMessage.IsSuccessStatusCode propiedad para indicar si la solicitud HTTP se realizó correctamente o no. Las respuestas comunes para esta operación son:

  • 204 (SIN CONTENIDO): la solicitud se ha procesado correctamente y la respuesta está en blanco intencionadamente.
  • 400 (SOLICITUD INCORRECTA): el servidor no entiende la solicitud.
  • 404 (NO ENCONTRADO): el recurso solicitado no existe en el servidor.

Eliminación de datos

El HttpClient.DeleteAsync método se usa para enviar la solicitud DELETE al servicio web especificado por el URI y, a continuación, recibir la respuesta del servicio web, como se muestra en el ejemplo de código siguiente:

public async Task DeleteTodoItemAsync (string id)
{
  Uri uri = new Uri (string.Format (Constants.TodoItemsUrl, id));
  ...
  HttpResponseMessage response = await client.DeleteAsync (uri);
  if (response.IsSuccessStatusCode)
  {
    Debug.WriteLine (@"\tTodoItem successfully deleted.");
  }
  ...
}

El servicio REST envía un código de estado HTTP en la HttpResponseMessage.IsSuccessStatusCode propiedad para indicar si la solicitud HTTP se realizó correctamente o no. Las respuestas comunes para esta operación son:

  • 204 (SIN CONTENIDO): la solicitud se ha procesado correctamente y la respuesta está en blanco intencionadamente.
  • 400 (SOLICITUD INCORRECTA): el servidor no entiende la solicitud.
  • 404 (NO ENCONTRADO): el recurso solicitado no existe en el servidor.

Desarrollo local

Si va a desarrollar el servicio web REST localmente con un marco como ASP.NET Core API web, puede depurar el servicio web y la aplicación móvil al mismo tiempo. En este escenario, debe habilitar el tráfico HTTP de texto no cifrado para el simulador de iOS y android emulator. Para obtener información sobre la configuración del proyecto para permitir la comunicación, consulte Conexión a servicios web locales.