Consumo de un servicio web RESTfulConsume a RESTful Web Service

Descargar ejemplo Descargar el ejemploDownload Sample Download the sample

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 aplicación de Xamarin. Forms.Integrating a web service into an application is a common scenario. This article demonstrates how to consume a RESTful web service from a Xamarin.Forms application.

La transferencia de estado representacional (REST) es un estilo arquitectónico para la creación de servicios Web.Representational State Transfer (REST) is an architectural style for building web services. Las solicitudes REST se realizan a través de HTTP usando los mismos verbos HTTP que los exploradores web utilizan para recuperar páginas web y enviar datos a los servidores.REST requests are made over HTTP using the same HTTP verbs that web browsers use to retrieve web pages and to send data to servers. Los verbos son:The verbs are:

  • Get : esta operación se usa para recuperar datos del servicio Web.GET – this operation is used to retrieve data from the web service.
  • Post : esta operación se usa para crear un nuevo elemento de datos en el servicio Web.POST – this operation is used to create a new item of data on the web service.
  • Put : esta operación se usa para actualizar un elemento de datos en el servicio Web.PUT – this operation is used to update an item of data on the web service.
  • Patch : esta operación se usa para actualizar un elemento de datos en el servicio Web mediante la descripción de un conjunto de instrucciones sobre cómo se debe modificar el elemento.PATCH – this operation is used to update an item of data on the web service by describing a set of instructions about how the item should be modified. Este verbo no se utiliza en la aplicación de ejemplo.This verb is not used in the sample application.
  • Delete : esta operación se usa para eliminar un elemento de datos en el servicio Web.DELETE – this operation is used to delete an item of data on the web service.

Las API de servicios web que se adhieren a REST se denominan API de RESTful y se definen mediante:Web service APIs that adhere to REST are called RESTful APIs, and are defined using:

  • URI base.A base URI.
  • Métodos HTTP, como GET, POST, PUT, PATCH o DELETE.HTTP methods, such as GET, POST, PUT, PATCH, or DELETE.
  • Un tipo de medio para los datos, como notación de objetos JavaScript (JSON).A media type for the data, such as JavaScript Object Notation (JSON).

Los servicios web RESTful normalmente usan mensajes JSON para devolver datos al cliente.RESTful web services typically use JSON messages to return data to the client. JSON es un formato de intercambio de datos basado en texto que genera cargas compactos, lo que reduce los requisitos de ancho de banda cuando se envían datos.JSON is a text-based data-interchange format that produces compact payloads, which results in reduced bandwidth requirements when sending data. La aplicación de ejemplo usa la biblioteca de NewtonSoft JSON.net de código abierto para serializar y deserializar mensajes.The sample application uses the open source NewtonSoft JSON.NET library to serialize and deserialize messages.

La simplicidad de REST ha ayudado a convertirlo en el método principal para tener acceso a los servicios web en aplicaciones móviles.The simplicity of REST has helped make it the primary method for accessing web services in mobile applications.

Cuando se ejecute la aplicación de ejemplo, se conectará a un servicio REST hospedado localmente, como se muestra en la siguiente captura de pantalla:When the sample application is run, it will connect to a locally hosted REST service, as shown in the following screenshot:

Nota

En iOS 9 y versiones posteriores, la seguridad de transporte de aplicaciones (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.In iOS 9 and greater, App Transport Security (ATS) enforces secure connections between internet resources (such as the app's back-end server) and the app, thereby preventing accidental disclosure of sensitive information. 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.Since ATS is enabled by default in apps built for iOS 9, all connections will be subject to ATS security requirements. Si las conexiones no cumplen estos requisitos, se producirá un error con una excepción.If connections do not meet these requirements, they will fail with an exception.

ATS puede no participar en si no es posible usar el protocolo https y proteger la comunicación para los recursos de Internet.ATS can be opted out of if it is not possible to use the HTTPS protocol and secure communication for internet resources. Esto se puede lograr actualizando el archivo info. plist de la aplicación.This can be achieved by updating the app's Info.plist file. Para obtener más información, vea seguridad de transporte de aplicaciones.For more information see App Transport Security.

Consumo del servicio WebConsuming the Web Service

El servicio REST se escribe utilizando ASP.NET Core y proporciona las operaciones siguientes:The REST service is written using ASP.NET Core and provides the following operations:

OperaciónOperation Método HTTPHTTP method URI relativoRelative URI ParámetrosParameters
Obtención de una lista de tareas pendientesGet a list of to-do items GETGET /api/todoitems//api/todoitems/
Crear un nuevo elemento de tareas pendientesCreate a new to-do item ExponerPOST /api/todoitems//api/todoitems/ Un TodoItem con formato JSONA JSON formatted TodoItem
Actualizar una tarea pendienteUpdate a to-do item PONDRÁNPUT /api/todoitems//api/todoitems/ Un TodoItem con formato JSONA JSON formatted TodoItem
Eliminar una tarea pendienteDelete a to-do item SUPRIMIRDELETE /api/todoitems/{id}/api/todoitems/{id}

La mayoría de los URI incluyen el identificador de TodoItem en la ruta de acceso.The majority of the URIs include the TodoItem ID in the path. Por ejemplo, para eliminar la 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.For example, to delete the TodoItem whose ID is 6bb8a868-dba1-4f1a-93b7-24ebce87e243, the client sends a DELETE request to http://hostname/api/todoitems/6bb8a868-dba1-4f1a-93b7-24ebce87e243. Para obtener más información sobre el modelo de datos utilizado en la aplicación de ejemplo, vea modelar los datos.For more information about the data model used in the sample application, see Modeling the data.

Cuando el marco de la API Web recibe una solicitud, enruta la solicitud a una acción.When the Web API framework receives a request it routes the request to an action. Estas acciones son simplemente métodos públicos en la clase TodoItemsController.These actions are simply public methods in the TodoItemsController class. El marco de trabajo utiliza una tabla de enrutamiento para determinar qué acción se debe invocar en respuesta a una solicitud, que se muestra en el ejemplo de código siguiente:The framework uses a routing table to determine which action to invoke in response to a request, which is shown in the following code example:

config.Routes.MapHttpRoute(
    name: "TodoItemsApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { controller="todoitems", id = RouteParameter.Optional }
);

La tabla de enrutamiento contiene una plantilla de ruta y, cuando el marco de la API Web recibe una solicitud HTTP, intenta hacer coincidir el URI con la plantilla de ruta de la tabla de enrutamiento.The routing table contains a route template, and when the Web API framework receives an HTTP request, it tries to match the URI against the route template in the routing table. Si no se encuentra una ruta coincidente, el cliente recibe un error 404 (no encontrado).If a matching route cannot be found the client receives a 404 (not found) error. Si se encuentra una ruta coincidente, la API Web selecciona el controlador y la acción como se indica a continuación:If a matching route is found, Web API selects the controller and the action as follows:

  • Para buscar el controlador, la API web agrega "controller" en el valor de la variable {controller} .To find the controller, Web API adds "controller" to the value of the {controller} variable.
  • Para encontrar la acción, la API Web examina el método HTTP y examina las acciones del controlador que se representan con el mismo método HTTP que un atributo.To find the action, Web API looks at the HTTP method and looks at controller actions that are decorated with the same HTTP method as an attribute.
  • La variable de marcador de posición {ID} está asignada a un parámetro de acción.The {id} placeholder variable is mapped to an action parameter.

El servicio REST utiliza la autenticación básica.The REST service uses basic authentication. Para obtener más información, consulte autenticación de un servicio web RESTful.For more information see Authenticating a RESTful web service. Para obtener más información sobre el enrutamiento de ASP.NET Web API, consulte enrutamiento en ASP.net web API en el sitio web de ASP.net.For more information about ASP.NET Web API routing, see Routing in ASP.NET Web API on the ASP.NET website. Para obtener más información sobre cómo compilar el servicio REST mediante ASP.NET Core, vea crear servicios back-end para aplicaciones móviles nativas.For more information about building the REST service using ASP.NET Core, see Creating Backend Services for Native Mobile Applications.

La clase HttpClient se utiliza para enviar y recibir solicitudes a través de HTTP.The HttpClient class is used to send and receive requests over HTTP. Proporciona funcionalidad para enviar solicitudes HTTP y recibir respuestas HTTP de un recurso identificado por un URI.It provides functionality for sending HTTP requests and receiving HTTP responses from a URI identified resource. Cada solicitud se envía como una operación asincrónica.Each request is sent as an asynchronous operation. Para obtener más información acerca de las operaciones asincrónicas, vea información general sobre la compatibilidad con Async.For more information about asynchronous operations, see Async Support Overview.

La clase HttpResponseMessage representa un mensaje de respuesta HTTP recibido del servicio Web después de que se haya realizado una solicitud HTTP.The HttpResponseMessage class represents an HTTP response message received from the web service after an HTTP request has been made. Contiene información sobre la respuesta, incluido el código de estado, los encabezados y cualquier cuerpo.It contains information about the response, including the status code, headers, and any body. La clase HttpContent representa el cuerpo HTTP y los encabezados de contenido, como Content-Type y Content-Encoding.The HttpContent class represents the HTTP body and content headers, such as Content-Type and Content-Encoding. El contenido se puede leer mediante cualquiera de los métodos de ReadAs, como ReadAsStringAsync y ReadAsByteArrayAsync, dependiendo del formato de los datos.The content can be read using any of the ReadAs methods, such as ReadAsStringAsync and ReadAsByteArrayAsync, depending upon the format of the data.

Creación del objeto HTTPClientCreating the HTTPClient Object

La instancia de HttpClient se declara en el nivel de clase para que el objeto se encuentre siempre y cuando la aplicación tenga que hacer solicitudes HTTP, como se muestra en el ejemplo de código siguiente:The HttpClient instance is declared at the class-level so that the object lives for as long as the application needs to make HTTP requests, as shown in the following code example:

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

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

Recuperar datosRetrieving Data

El método HttpClient.GetAsync 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:The HttpClient.GetAsync method is used to send the GET request to the web service specified by the URI, and then receive the response from the web service, as shown in the following code example:

public async Task<List<TodoItem>> RefreshDataAsync ()
{
  ...
  var uri = new Uri (string.Format (Constants.TodoItemsUrl, string.Empty));
  ...
  var response = await _client.GetAsync (uri);
  if (response.IsSuccessStatusCode)
  {
      var content = await response.Content.ReadAsStringAsync ();
      Items = JsonConvert.DeserializeObject <List<TodoItem>> (content);
  }
  ...
}

El servicio REST envía un código de Estado HTTP en la propiedad HttpResponseMessage.IsSuccessStatusCode para indicar si la solicitud HTTP se ha realizado correctamente o no.The REST service sends an HTTP status code in the HttpResponseMessage.IsSuccessStatusCode property, to indicate whether the HTTP request succeeded or failed. Para esta operación, el servicio REST envía el código de Estado HTTP 200 (OK) en la respuesta, que indica que la solicitud se realizó correctamente y que la información solicitada se encuentra en la respuesta.For this operation the REST service sends HTTP status code 200 (OK) in the response, which indicates that the request succeeded and that the requested information is in the response.

Si la operación HTTP se realizó correctamente, se lee el contenido de la respuesta para su presentación.If the HTTP operation was successful, the content of the response is read, for display. La propiedad HttpResponseMessage.Content representa el contenido de la respuesta HTTP y el método HttpContent.ReadAsStringAsync escribe asincrónicamente el contenido HTTP en una cadena.The HttpResponseMessage.Content property represents the content of the HTTP response, and the HttpContent.ReadAsStringAsync method asynchronously writes the HTTP content to a string. A continuación, este contenido se convierte de JSON a un List de instancias de TodoItem.This content is then converted from JSON to a List of TodoItem instances.

Crear datosCreating Data

El método HttpClient.PostAsync 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:The HttpClient.PostAsync method is used to send the POST request to the web service specified by the URI, and then to receive the response from the web service, as shown in the following code example:

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

  ...
  var json = JsonConvert.SerializeObject (item);
  var 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 instancia de TodoItem se convierte en una carga JSON para enviarla al servicio Web.The TodoItem instance is converted to a JSON payload for sending to the web service. Esta carga se inserta entonces en el cuerpo del contenido HTTP que se enviará al servicio Web antes de que se realice la solicitud con el método PostAsync.This payload is then embedded in the body of the HTTP content that will be sent to the web service before the request is made with the PostAsync method.

El servicio REST envía un código de Estado HTTP en la propiedad HttpResponseMessage.IsSuccessStatusCode para indicar si la solicitud HTTP se ha realizado correctamente o no.The REST service sends an HTTP status code in the HttpResponseMessage.IsSuccessStatusCode property, to indicate whether the HTTP request succeeded or failed. Las respuestas comunes para esta operación son:The common responses for this operation are:

  • 201 (creado) : la solicitud dio lugar a la creación de un nuevo recurso antes de que se enviara la respuesta.201 (CREATED) – the request resulted in a new resource being created before the response was sent.
  • 400 (solicitud incorrecta) : el servidor no entiende la solicitud.400 (BAD REQUEST) – the request is not understood by the server.
  • 409 (conflicto) : no se pudo realizar la solicitud debido a un conflicto en el servidor.409 (CONFLICT) – the request could not be carried out because of a conflict on the server.

Actualizar datosUpdating Data

El método HttpClient.PutAsync 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:The HttpClient.PutAsync method is used to send the PUT request to the web service specified by the URI, and then receive the response from the web service, as shown in the following code example:

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

El funcionamiento del método PutAsync es idéntico al del método PostAsync que se usa para crear datos en el servicio web, pero varían las posibles respuestas enviadas desde el servicio web.The operation of the PutAsync method is identical to the PostAsync method that's used for creating data in the web service. Sin embargo, las posibles respuestas enviadas desde el servicio Web difieren.However, the possible responses sent from the web service differ.

El servicio REST envía un código de Estado HTTP en la propiedad HttpResponseMessage.IsSuccessStatusCode para indicar si la solicitud HTTP se ha realizado correctamente o no.The REST service sends an HTTP status code in the HttpResponseMessage.IsSuccessStatusCode property, to indicate whether the HTTP request succeeded or failed. Las respuestas comunes para esta operación son:The common responses for this operation are:

  • 204 (sin contenido) : la solicitud se ha procesado correctamente y la respuesta está en blanco intencionadamente.204 (NO CONTENT) – the request has been successfully processed and the response is intentionally blank.
  • 400 (solicitud incorrecta) : el servidor no entiende la solicitud.400 (BAD REQUEST) – the request is not understood by the server.
  • 404 (no encontrado) : el recurso solicitado no existe en el servidor.404 (NOT FOUND) – the requested resource does not exist on the server.

Eliminar datosDeleting Data

El método HttpClient.DeleteAsync se usa para enviar la solicitud de eliminación 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:The HttpClient.DeleteAsync method is used to send the DELETE request to the web service specified by the URI, and then receive the response from the web service, as shown in the following code example:

public async Task DeleteTodoItemAsync (string id)
{
  var uri = new Uri (string.Format (Constants.TodoItemsUrl, id));
  ...
  var 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 propiedad HttpResponseMessage.IsSuccessStatusCode para indicar si la solicitud HTTP se ha realizado correctamente o no.The REST service sends an HTTP status code in the HttpResponseMessage.IsSuccessStatusCode property, to indicate whether the HTTP request succeeded or failed. Las respuestas comunes para esta operación son:The common responses for this operation are:

  • 204 (sin contenido) : la solicitud se ha procesado correctamente y la respuesta está en blanco intencionadamente.204 (NO CONTENT) – the request has been successfully processed and the response is intentionally blank.
  • 400 (solicitud incorrecta) : el servidor no entiende la solicitud.400 (BAD REQUEST) – the request is not understood by the server.
  • 404 (no encontrado) : el recurso solicitado no existe en el servidor.404 (NOT FOUND) – the requested resource does not exist on the server.