Windows Phone Tips & Tricks. Cómo realizar peticiones web http GET y POST con async-await-Task

[Nota: Este artículo pertenece a la serie de Windows Phone Tips & Tricks de MSDN España]

Hola,

En una app que estoy haciendo en Windows Phone 8, estoy usando una clase muy similar a la siguiente para realizar peticiones web http con GET y POST utilizando async-await-Task. El utilizar este patrón asíncrono hace que mi código sea más limpio y los métodos de la clase sean más sencillos de utilizar:

using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading.Tasks;

namespace MyApp.Services
{
    // Peticiones web
    public class HttpService
    {
        // Constructor
        public HttpService()
        {
        }

        // Haz una petición GET
        public async Task<byte[]> GetAsync(string requestUriString)
        {
            // Crea la petición
            WebRequest webRequest = HttpWebRequest.Create(requestUriString) as HttpWebRequest;
            webRequest.Method = "GET";

            // Obtén la respuesta
            byte[] data = null;
            TaskFactory taskFactory = new TaskFactory();
            Task<WebResponse> responseTask = taskFactory.FromAsync<WebResponse>(webRequest.BeginGetResponse, webRequest.EndGetResponse, null);
            WebResponse webResponse = await responseTask;
            using (Stream responseStream = webResponse.GetResponseStream())
            {
                data = new byte[responseStream.Length];
                responseStream.Read(data, 0, data.Length);
                responseStream.Close();
            }

            return data;
        }

        // Haz una petición POST con contenido
        public async Task<string> PostAsync(string requestUriString, List<KeyValuePair<string, string>> content)
        {
            // Prepara el contenido de la petición
            string contentString = "";
            content.ForEach(kvp => contentString += HttpUtility.UrlEncode(kvp.Key) + "=" + HttpUtility.UrlEncode(kvp.Value) + "&");

            // Crea la petición
            WebRequest webRequest = HttpWebRequest.Create(requestUriString) as HttpWebRequest;
            webRequest.Method = "POST";
            webRequest.ContentType = "application/x-www-form-urlencoded";

            // Envía el contenido de la petición
            TaskFactory taskFactory = new TaskFactory();
            Task<Stream> requestTask = taskFactory.FromAsync<Stream>(webRequest.BeginGetRequestStream, webRequest.EndGetRequestStream, null);
            using (Stream requestStream = await requestTask)
            {
                using (StreamWriter streamWriter = new StreamWriter(requestStream))
                {
                    streamWriter.Write(contentString);
                    streamWriter.Close();
                }
                requestStream.Close();
            }

            // Obtén la respuesta
            string responseString = null;
            Task<WebResponse> responseTask = taskFactory.FromAsync<WebResponse>(webRequest.BeginGetResponse, webRequest.EndGetResponse, null);
            WebResponse webResponse = await responseTask;
            using (Stream responseStream = webResponse.GetResponseStream())
            {
                using (StreamReader streamReader = new StreamReader(responseStream))
                {
                    responseString = streamReader.ReadToEnd();
                    streamReader.Close();
                }
                responseStream.Close();
            }
            return responseString;
        }

        // Haz una petición POST con contenido
        public async Task<string> PostAsync(string requestUriString, string contentType, byte[] content)
        {
            // Crea la petición
            WebRequest webRequest = HttpWebRequest.Create(requestUriString) as HttpWebRequest;
            webRequest.Method = "POST";
            webRequest.ContentType = contentType;

            // Envía el contenido de la petición
            TaskFactory taskFactory = new TaskFactory();
            Task<Stream> requestTask = taskFactory.FromAsync<Stream>(webRequest.BeginGetRequestStream, webRequest.EndGetRequestStream, null);
            using (Stream requestStream = await requestTask)
            {
                requestStream.Write(content, 0, content.Length);
                requestStream.Close();
            }

            // Obtén la respuesta
            string responseString = null;
            Task<WebResponse> responseTask = taskFactory.FromAsync<WebResponse>(webRequest.BeginGetResponse, webRequest.EndGetResponse, null);
            WebResponse webResponse = await responseTask;
            using (Stream responseStream = webResponse.GetResponseStream())
            {
                using (StreamReader streamReader = new StreamReader(responseStream))
                {
                    responseString = streamReader.ReadToEnd();
                    streamReader.Close();
                }
                responseStream.Close();
            }
            return responseString;
        }
    }
}

Como ves esta clase tiene 3 ejemplos de peticiones, una GET que devuelve un array de bytes con la respuesta, y un par de POST a las que podemos pasar parámetros en diferentes formatos y que devuelven una cadena de texto con la respuesta.

La petición GET la uso en mi app por ejemplo para descargarme imágenes que luego cacheo. Un ejemplo de uso sería el siguiente:

HttpService httpService = new HttpService();
byte[] imageData = await httpService.GetAsync("http://www.somewebsite.com/someimage.jpg");

La primera de las peticiones POST la uso en mi app por ejemplo para llamar a una API REST de terceros que requiere el nombre del usuario y un hash de su contraseña para realizar la autenticación. Un ejemplo de uso sería el siguiente:

HttpService httpService = new HttpService();

// Llama a la API
string responseString = await httpService.PostAsync(
    "http://somewebservice/someAPI/myAPIkey",
    new List<KeyValuePair<string, string>>
    {
        new KeyValuePair<string, string>("username", "the user name"),
        new KeyValuePair<string, string>("password", "the hash of the password")
    }
);

La segunda de las peticiones POST la uso en mi app por ejemplo para llamar a otra de las APIs REST de terceros que requiere una serie de parámetros en forma de Json con dichos parámetros (que incluyen el usuario y el hash de su contraseña para la autenticación). Un ejemplo de uso sería el siguiente:

HttpService httpService = new HttpService();

// Prepara los parámetros de la API
byte[] jsonContent = ...

// Llama a la API
string responseString = await httpService.PostAsync(
    "http://somewebservice/someOtherAPI/myAPIkey",
    "text/json",
    jsonContent
);

Nota: para preparar el array de bytes con los parámeros de la API (“jsonContent”) utilizo lo siguiente: Windows Tips & Tricks. Cómo serializar un objeto a un array de bytes Json.

Espero que te sea de utilidad.

Un saludo,

Alejandro Campos Magencio (@alejacma)

PD: Mantente informado de todas las novedades de Microsoft para los desarrolladores españoles a través del Twitter de MSDN, el Facebook de MSDN, el Blog de MSDN y la Newsletter MSDN Flash.

About these ads

3 pensamientos en “Windows Phone Tips & Tricks. Cómo realizar peticiones web http GET y POST con async-await-Task

  1. Si añades el paquete Microsoft.Bcl.Async desde Nuget, vas a tener acceso a una pila de métodos de extensión con los que puedes simplificar tu código:

    var request = (HttpWebRequest)WebRequest.Create(uri);
    request.Method = “POST”;
    request.ContentType = contentType;
    request.ContentLength = content.Length;

    using (var ws = await request.GetRequestStreamAsync())
    {
    await ws.WriteAsync(content, 0, content.Length);
    }

    var response = (HttpWebResponse)await request.GetResponseAsync();

    using (var reader = new StreamReader(response.GetResponseStream()))
    {
    return await reader.ReadToEndAsync();
    }

  2. Pingback: Tips & Tricks de desarrollo para Windows Phone - MSDN España - Site Home - MSDN Blogs

Deja un comentario

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s