Enviar parámetros a un API REST usando los métodos GET y POST sin formulario

[ 24 ] Comentarios
Compartir
Arquitectura cliente-servidor del blog de carmen-suarez

Algo que encuentro con frecuencia en internet al buscar información sobre APIs y servicios web, es un buen número de usuarios que desconocen como realizar consultas a este tipo de interfaces utilizando los métodos GET y POST. Esto es especialmente notable en el caso de POST, donde a menudo preguntan como se pueden enviar y recibir parámetros a un API REST con los métodos GET y POST sin utilizar un formulario.

Hoy voy a intentar resolver esta duda con un ejemplo en C# ASP .NET.

Antes de nada debo aclarar que este ejemplo se ha realizado únicamente con finalidad divulgativa, y que muy probablemente en cada caso encontreis otras formas (mejores y peores) de enviar parámetros a un servicio web; pero al menos espero que esta os sirva y os ayude a entender el asunto.

Método GET

Formato de los parámetros

Cuando enviamos los parámetros a un servicio web, utilizando el método GET, los parámetros se envían en la URL, concatenados, codificados en formato URL y separados por símbolos ampersand. Veamos un ejemplo:

Queremos enviar al servicio web…

  • http://findemor.porExpertos.es/ServicioInventado.aspx

información de una persona, para que la registre. El servicio en este caso nos responderá con “OK” si todo ha ido bien, o un mensaje de error en otro caso.

Los parámetros que el servicio espera, en este caso, serán:

  • nombre
  • fecha

Y por lo tanto estos serán los pares clave-valor que enviaremos:

  • nombre: Manuel
  • fecha: 2012

Como hemos dicho antes, hay que concatenarlos de la forma adecuada, por lo que quedarían así:

  • nombre=Manuel&fecha=2012

Finalmente, esta cadena se envía al servicio web, separando la dirección del servicio de los parámetros por un simbolo de interrogación, de este modo:

  • http://findemor.porExpertos.es/ServicioInventado.aspx?nombre=Manuel&fecha=2012

Nos queda un detalle, respecto a la codificación en formato URL que mencionaba al principio. Hay ciertos caracteres que no pueden ser enviados en una dirección web: por ejemplo un espacio en blanco. Para solucionar esto, hay que codificar los valores de los parámetros antes de enviarlos. Supongamos que el nombre que vamos a enviar es compuesto:

  • Nombre: Manuel Joaquín

En este caso no podemos enviar la url con un espacio en blanco, por lo que antes de enviar los parámetros siempre es conveniente asegurarnos de que están escritos utilizando la codificación adecuada. Así quedaría el nombre después de codificarlo, y así sería el parámetro que deberíamos enviar.

  • Nombre: Manuel%20Joaqu%C3%ADn

Fijaos en que se ha codificado, además, la “i” que tenía una tilde.

Una herramienta online para codificar esto, está en este enlace. Por código, sin embargo, veremos en el ejemplo que existen métodos para codificar esto automáticamente.

El resto de la url, así como el nombre de los parámetros, no es necesario codificarlo porque asumimos que el servicio que los define no está utilizando caracteres incompatibles con este método.

Código

Definiendo éste método, tendremos una forma fácil de concatenar los parámetros y codificarlos, enviados a traves de una colección de claves-valor:

[code lang=”csharp”]
private static string ConcatParams(Dictionary parameters)
{
bool FirstParam = true;
StringBuilder Parametros = null;

if (parameters != null)
{
Parametros = new StringBuilder();
foreach (KeyValuePair param in parameters)
{
Parametros.Append(FirstParam ? "" : "&");
Parametros.Append(param.Key + "=" + System.Web.HttpUtility.UrlEncode(param.Value));
FirstParam = false;
}
}

return Parametros == null ? string.Empty : Parametros.ToString();
}
[/code]

Una vez definido este método, podemos implementar el envio y obtención de respuesta por parte del servidor, así:

[code lang=”csharp”]
public static string GetResponse_GET(string url, Dictionary<string, string> parameters)
{
try
{
//Concatenamos los parametros, OJO: antes del primero debe estar el caracter "?"
string parametrosConcatenados = ConcatParams(parameters);
string urlConParametros = url + "?" + parametrosConcatenados;

System.Net.WebRequest wr = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(urlConParametros);
wr.Method = "GET";

wr.ContentType = "application/x-www-form-urlencoded";

System.IO.Stream newStream;
// Obtiene la respuesta
System.Net.WebResponse response = wr.GetResponse();
// Stream con el contenido recibido del servidor
newStream = response.GetResponseStream();
System.IO.StreamReader reader = new System.IO.StreamReader(newStream);
// Leemos el contenido
string responseFromServer = reader.ReadToEnd();

// Cerramos los streams
reader.Close();
newStream.Close();
response.Close();
return responseFromServer;
}
catch (System.Web.HttpException ex)
{
if (ex.ErrorCode == 404)
throw new Exception("Not found remote service " + url);
else throw ex;
}
}
[/code]

Método POST

El método POST se realiza de forma muy parecida al GET, salvo porque los parámetros se envian en el cuerpo del mensaje, en lugar de en la URL.

Además, tiene otra diferencia: como la URL y la cadena de parámetros no “van unidos”, no hay que separarlos con un símbolo de interrogación, como si hacíamos en el GET.

(En realidad las diferencias, en cuanto al significado de emplear un método u otro, y las características funcionales de cada uno, van mucho más allá; pero el alcance de este tutorial es únicamente mostrar como se desarrolla el mecanismo.)

Como no hay más diferencias notables entre ambos métodos en este sentido, vamos a ver el código.

Código

[code lang=”csharp”]
public static string GetResponse_POST(string url, Dictionary<string, string> parameters)
{
try
{
//Concatenamos los parametros, OJO: NO se añade el caracter "?"
string parametrosConcatenados = ConcatParams(parameters);

System.Net.WebRequest wr = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
wr.Method = "POST";

wr.ContentType = "application/x-www-form-urlencoded";

System.IO.Stream newStream;
//Codificación del mensaje
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
byte[] byte1 = encoding.GetBytes(parametrosConcatenados);
wr.ContentLength = byte1.Length;
//Envio de parametros
newStream = wr.GetRequestStream();
newStream.Write(byte1, 0, byte1.Length);

// Obtiene la respuesta
System.Net.WebResponse response = wr.GetResponse();
// Stream con el contenido recibido del servidor
newStream = response.GetResponseStream();
System.IO.StreamReader reader = new System.IO.StreamReader(newStream);
// Leemos el contenido
string responseFromServer = reader.ReadToEnd();

// Cerramos los streams
reader.Close();
newStream.Close();
response.Close();
return responseFromServer;
}
catch (System.Web.HttpException ex)
{
if (ex.ErrorCode == 404)
throw new Exception("Not found remote service " + url);
else throw ex;
}
}
[/code]

Cómo utilizarlo

Una vez que hemos implementado estos métodos, falta ver como utilizarlos. Es una tarea muy sencilla e idéntica en ambos casos. Así sería una llamada al método GET:

[code lang=”csharp”]
public void EnviarDatos()
{
string UrlBase = "http://findemor.porExpertos.es/servicioInventado.aspx";

Dictionary<string, string> Parametros = new Dictionary<string,string>();
Parametros.Add("nombre","Manuel");
Parametros.Add("fecha","2012");

string respuestaServidor = GetResponse_GET(UrlBase, Parametros, Method.GET);
}

[/code]

Primero construimos la lista de parámetros, de tipo clave-valor, y los enviamos a la URL definida por el servidor.

Puedes descargartelo

Si lo deseas, o si tienes dudas para interpretar los bloques de código, puedes descargar el proyecto desde ESTE ENLACE. (Se puede abrir con Visual Studio 2010)

Espero que os haya resultado útil,

no dudeis en comentar o preguntar lo que deseeis.

Acerca de findemor

Técnico de Innovación en solusoft.

Warning: count(): Parameter must be an array or an object that implements Countable in /homepages/30/d298707731/htdocs/porexpertos.es/wp-includes/class-wp-comment-query.php on line 405

24 Respuestas a Enviar parámetros a un API REST usando los métodos GET y POST sin formulario

  1. dudasNet dice:

    Hola buenas.
    Muy bueno el artículo!

    Mi duda es, al obtener la respuesta del servidor (responseFromServer) recibo código HTML, si de ese HTML quisiera obentener sólo lo que hay dentro de un div ¿cómo podría tratar la información?
    ¿Almacenando la respuesta en un txt y utilizar el reader.Line()?

  2. Jesus Niño dice:

    Un agradecimiento grande por este trabajo, e estado buscando en distintos libros y paginas consumir servicios REST desde la aplicación en c# y la información es muy confusa lo que contrasta con la claridad y la simplicidad de este tutorial con un enfoque aplicativo muy claro.

  3. Jesus Niño dice:

    Este tutorial tiene un enfoque practico exelente gracias…

  4. Lu dice:

    Hola, oye del primer metodo, me marca error el objeto de Diccionario, creo que este no está definido como el ……

    Me pueden decir que esta mal o yo no importe algo?

    • Lu dice:

      Ya vi mi error, ahora mi pregunta es:

      Como se que tengo respuesta del servidor? o como me doy cuenta.

      Soy nueva en esto… Saludos

      • findemor dice:

        Hola Lu,
        Hay 3 formas en que un servidor puede indicar si ha recibido tu respuesta y qué ha pasado con ella, dependiendo de la capa que tu solicitud alcance.

        1- Si el servidor no pudo ser alcanzado (porque está caido, por ejemplo) recibirar una excepción que tendrás que procesar en el CATCH{}.

        2- Si el servidor se alcanzó, pero la solicitud es incorrecta de algún modo, pueden ocurrir dos cosas, en función de la definición del API que estás atacando.

        2a- En algunos casos el servidor te responderá empleando el StatusCode de la petición (un atributo del WebResponse, que vale 200 cuando la petición se ha procesado correctamente), y deberias ignorar el contenido de Response.

        2b- En otros casos, el servidor procesará la petición, y al determinar que es incorrecta te devolverá igualmente un StatusCode == 200 pero incluirá información acerca del error en el cuerpo (contenido) de la respuesta. Esto difiere en cada servicio y tienes que averiguarlo leyendo la documentación del API que vayas a atacar.

        Puedes ver como se usa el atributo StatusCode aqui: http://msdn.microsoft.com/es-es/library/system.net.httpwebresponse.statuscode(v=vs.110).aspx

        Tambien puedes ver los diferentes StatusCode que te puede responder (el código 200 indica que tu petición ha sido procesada por el servidor, como preguntabas): http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

        Espero haber aclarado tu duda.
        Un saludo.

    • Yo necesito llamar al metodo desde un form, como puedo hacer ??

  5. Lu dice:

    Hola gracias por contestar, pero ahora lo que quiero hacer es que:

    Tengo que enviar un archivo xml y 2 parámetros a un webservice, ya lo intente con el método de post pero me genera un error 404. Lo que modifique en el metodo fue:

    public static string GetResponse_POST(string url, Dictionary parameters, string archivo)

    Mandarle el parametro de archivo, esto adjunta con un metodo que es:

    public static string GetTextFromXMLFile(string file)
    {
    StreamReader reader = new StreamReader(file);
    string ret = reader.ReadToEnd();
    reader.Close();
    return ret;
    }

    pero al momento de recibir respuesta de webResponse me manda el error que les comente, saben uds de alguna manera de reparar este error?

    • findemor dice:

      Hola Lu,

      Un error 404 del servidor te indica que no se pudo encontrar el recurso que estas intentando acceder. Por eso, probablemente no tenga nada que ver con la forma en que serializas el contenido de tu fichero xml… sino más bien a como estas construyendo la petición POST o la URL. Asegurate de leer con atención la documentación de la operación del servidor que intentas ejecutar, ya que probablemente la URL no está bien construida, o requiere un parámetro que no estas entregando, o el elemento que intentas actualizar con la llamada no existe en el servidor, o los parametros no están bien codificados…

      Sin tener más detalles del servicio al que accedes y sin ver un ejemplo de la petición real que estás lanzando no te podría decir más 🙂

      Suerte!

  6. Bruno dice:

    Hola, qué tal, felicitaciones por la nota, está muy buena, estaba revisando y quería descargar el código para revisarlo pero al pinchar me doy cuenta que el enlace está roto, podrías volver a subirlo por favor.

    Un saludazo.!!!!

  7. orlando fernandez dice:

    para hacer un cross-domain necesita algun parametro especial como en el caso de javascript crossDomain: true o con que en la pagina a la cual se va acceder se habilite el acceso de otros dominios es suficiente???

    • findemor dice:

      Hola Orlando,

      La solución que se muestra aquí está enfocada a la configuración del servidor para admitir peticiones de este tipo, pero lo que apuntas es correcto, es necesario incluir el parámetro crossDomain: true en la llamada javascript, y tambien establecer true en support.cors de jQuery.

      Adjunto un ejemplo Ajax usando jQuery.

      function doAjaxRequest(code) {
      // permite cors en IE10
      jQuery.support.cors = true;
      // realiza la peticion
      $.ajax(
      {
      type: "GET",
      url: "http://...",
      data: {
      code: code
      },
      dataType: "text",
      crossDomain: true,
      success: function (data, textStatus, jqXHR) {
      ...
      },
      error: loadOnError,
      complete: loadOnComplete
      });
      }

  8. arkhej dice:

    Hola findemor, sin temor a equivocarme es la primera vez que google me lleva a su blog en respuesta a la incógnita que muchos otros foros y blogs no habían podido resolver con tanta sencillez y claridad, muchas gracias y felicidades por su trabajo. (Creo que visitaré más seguido su sitio)

  9. Primero dice:

    Consulta como hago para crear el servicio
    ¿Que se coloca en el UriTemplate? ¿Como le paso los parametros al servicio?

    [WebInvoke(Method = “POST”,
    ResponseFormat = WebMessageFormat.Json,
    RequestFormat = WebMessageFormat.Json,
    BodyStyle = WebMessageBodyStyle.Wrapped,
    // UriTemplate = “PostSampleMethod/{data}”)]
    UriTemplate = “PostSampleMethod”)]

  10. Primero dice:

    HttpWebResponse response = wr.GetResponse() as HttpWebResponse;

    Error en el servidor remoto: (400) Solicitud incorrecta.

    A
    ¿A que se debe?

    • findemor dice:

      Significa que ha llegado la petición al servidor, pero la url está mal formada (o mal escrita) o que faltan parametros imprescindibles. Examina la documentación del API al que intentas acceder y comparala con la request que estas realizando. Seguramente te des cuenta del problema con un vistazo.
      Un saludo!

  11. isaac dice:

    Buenos días, es necesario saber a qué método queremos llamar?, es decir si tengo una aplicación que consume un servicio web y envía como parámetro un json y yo quiero crear otra aplicación que sirva de intermediaria entre ambas para que la aplicación principal me envíe la petición a la mía y yo al webservice,,,, me tendrían que pasar el json y además la url con el método a invocar? o hay manera de que solo con el json puedo yo hacer la petición al webservice.. gracias.

  12. Galo Galarza dice:

    Excelente, concuerdo con muchas personas que escribieron, la información compartida es oro, muy bien explicado, MUCHAS GRACIAS. Ahora a implementarlo en mi framework, gracias.

  13. Hola maestro !!!
    Mil disculpas, pero tu ejemplo me aclara mucho las dudas del envió de datos a Web service.
    Pero tengo un pequeño problema, como llama al método desde un Formulario ?

  14. israel dice:

    amigo me puedes ayudar necesito recibir datos enviando solicitud post y debo adjuntar parametros esto en php o javascript me puedes ayudar

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *