Consumiendo REST desde C#.NET

Consumir RESTful en .NET
Consumir RESTful en .NET

Hace algunos días atras buscaba una forma decente y elegante de crear mi propia api utilizando RESTful para Celestic .. de esa forma fue que llegue a StackOverflow y muchas preguntas de usuarios necesitando código para consumir servicios basados en REST.. En este sitio todavía no colaboro por lo que no quize responder, ya pensándolo bien fue que decidí escribir este artículo.

Sé que hay otra manera de hacerlo.. pero para este ejemplo utilizaremos el objeto HttpWebRequest y HttpWebResponse, entonces comenzamos:

var postString = new {clave1:valor1, clave2:valor2};
byte[] data = UTF8Encoding.UTF8.GetBytes(postString);
 
HttpWebRequest request;
request = WebRequest.Create("http://localhost/ejemplo/api") as HttpWebRequest;
request.Timeout = 10 * 1000;
request.Method = "POST";
request.ContentLength = data.Length;
request.ContentType = "application/json; charset=utf-8";

Básicamente lo que se hace es instanciar de HttpWebRequest y setear algunos parámetros, entre ellos y mas importante el método (Method), la longitud de la petición (ContentLength) y el tipo de dato a enviar (ContentType). No pierdan de vista que estoy enviando postString que a su vez es un objeto tipo Json.

La mayoría de servicios basados en REST requieren autenticación básica.. y pues es una de las más fáciles de utilizar.. inclusive desde el navegador se puede hacer, lo único que se requiere es un usuario y una clave de acceso..

string credentials = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes("usuario:clave"));
request.Headers.Add("Authorization", "Basic " + credentials);

Esto es como algunas páginas en internet que piden autenticación para entrar, donde puedes escribir la url y esperar a que aparezca el formulario de inicio de sesion o escribirlo directamente en la url.. de la forma: “usuario:clave@http://localhost/ejemplo/api”

Ahora lo siguiente y último paso es enviar los datos y obtener la respuesta..

Stream postStream = request.GetRequestStream();
postStream.Write(data, 0, data.Length);
 
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
StreamReader reader = new StreamReader(response.GetResponseStream());
string body = reader.ReadToEnd();

Y para finalizar body es el contenido de lo que ha respondido el servicio, recuerden que la respuesta es tipo Json.. por lo que pueden interpretarla facilmente con javascript o hacer algo más complejo si desean parsearlo desde .NET.

Espero les sirva el código.. y si encuentran algun error, recuerden que el formulario de comentarios no muerde.. 😀

Co-fundador de Qbit Mexhico, usuario de linux, Developer en tecnologías web.. Nicaragüense, centro en basketball, primer centro en rugby y pintor los fines de semana. Ortögrafo y ambientalista psicológico (de escritorio).. ese soy yo!

Si te ha servido compártelo y difunde nuestro blog..

Twitter LinkedIn Flickr YouTube 

36 thoughts on “Consumiendo REST desde C#.NET

  1. Hola, por favor me podrías decir cómo interpreto esa respuesta en .net si parte de la respuesta es una lista de objetos? … muchas gracias =(

    1. Saly lo que necesitas es deserializar el objeto que ha respondido el servidor.. y de ese tema hay mucha información en internet, de hecho en google si buscas el término “c# json to object” puede que encuentres el resultado que buscas..

  2. Muy buena explicación, de verdad te agradezco, ya que estuve sufriendo varios días poder hacerlo de la manera correcta y cuando tenia caracteres especiales el servicio me generaba error. De antemano gracias y saludos desde lima-peru

  3. Olle amigo tengo un problema para este codigo, quiero enviar un string a dicho servico pero no se como invocarlo, busque y me encontre con tu block, el detalle que me marca error en esta linea var postString = new {“xmlPedido” : Xml}; el xml es eso uan cadena con xml, me podria ayudar

  4. hola disculpa soy nuevo en el uso de c#, tengo esta funcion en PHP …
    public function testLogin($remote_ip, $app, $pass)
    {
    $opencryted = “false”;
    $opalgorithm = “aes-128-ecb”;
    $verb = “login”;
    $fields = array(
    ‘name_app’ => urlencode($app),
    ‘secret_key’ => urlencode($pass),
    ‘encrypted’ => urlencode($opencryted),
    ‘algorithm’ => urldecode($opalgorithm)
    );
    $fields_string = “”;
    foreach ($fields as $key => $value) {
    $fields_string .= $key . ‘=’ . $value . ‘&’;
    }
    rtrim($fields_string, ‘&’);
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $remote_ip . $verb);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, count($fields));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
    }
    me podrías ayudar a interpretarlo en c#

    1. Hola gibran, no precisamente te ayudaré con el código, porque se pierde toda la diversión, pero con estas referencias podrás hacerlo tu mismo casi sin problemas.

      HttpWebRequest/HttpWebResponse
      WebClient
      HttpClient (disponible en la la versión 4.5 de .NET — este me gusta mucho)

      Y si esas clases no te gustan, puedes utilizar RestSharp (http://restsharp.org/) que es bastante fácil de implementarlo.

  5. Hola, no me queda claro que hace esta linea
    var postString = new {clave1:valor1, clave2:valor2};

    Y me genera error, de pronto es algo obvio pero no sé que se supone que deba hacer previamente. Gracias

  6. Hola, como quedaria esta linea en VB, resulta que me da error y no he podido acomodarla
    var postString = new {clave1:valor1, clave2:valor2};

  7. Hola como estas, estoy tratando de implementar PayU con un sistema Web, en teoria PayU tiene un WebService REst para ser consumido(http://developers.payulatam.com/es/api/queries.html) , en tu codigo de ejemplo, como se le puede enviar un parametro Json asi:
    {
    “test”: false,
    “language”: “en”,
    “command”: “PING”,
    “merchant”: {
    “apiLogin”: “pRRXKOl8ikMmt9u”,
    “apiKey”: “4Vj8eK4rloUd272L48hsrarnUA”
    }
    }

    o tu crees que tu codigo es para otros ejemplos.. Saludos y Agradeceria tu respuesta.

  8. hola, estoy desarrollando una aplicacion de escritorio que debe consumir un servicio con autenticacion AUTH 2.0 y que trabaja con REST. es posible trabajar con esa seguridad auth mediante este tipo de codigo?

    1. Hola Juan, este código no te servirá para autenticarte en un servicio de oauth, aunque con la librería webrequest si puedes conseguirlo, tendrías que hacer muchos pasos más y crear un poco más de código, yo te recomendaría utilizar una librería desarrollada y probada para este fin, hay muchas en la red y muchas de ellas son mantenidas por la comunidad.

      Suerte!

  9. Muy buena explicacion, me sirvio mucho para un inconveniente que tenia ya que algunos clientes usan distintos frameworks y este pues se adapta de lo antiguo a lo nuevo

  10. hola estoy elaborando una aplicaciòn en asp.net y necesito consumir un web service rest-ful enviandole los valores de los parametros mediante el metodo post en c# se me complica demaciado espero puedas ayudarme

  11. Estimados, estoy intentando conectarme a este sitio un sitio “https://api.etadirect.com/rest/ofscCore/v1/folders/dailyExtract/folders/2017-11-01/files/gtd.xml.2017-11-01.zip”, uso la aplicación Postman para validar si existe la url y el archivo que quiero bajar. usando postman con las credenciales (usuario, contraseña) como se muestra en la siguiente imagen:

    este es mi codigo de conexion usando SSIS:

    #region Help: Introduction to the script task
    /* The Script Task allows you to perform virtually any operation that can be accomplished in
    * a .Net application within the context of an Integration Services control flow.
    *
    * Expand the other regions which have “Help” prefixes for examples of specific ways to use
    * Integration Services features within this script task. */
    #endregion

    #region Namespaces
    using System;
    using System.Data;
    using Microsoft.SqlServer.Dts.Runtime;
    using System.Windows.Forms;
    using System.Net;
    using System.IO;
    using System.IO.Compression;
    using System.Web;
    using System.Runtime.Serialization.Json;
    using System.Threading;
    //using System.Net.Http;
    using System.Security.Cryptography.X509Certificates;
    using System.Diagnostics;
    #endregion

    namespace ST_3846ee711a6f4f7dadd10ddd4181a89c
    {
    ///
    /// ScriptMain is the entry point class of the script. Do not change the name, attributes,
    /// or parent of this class.
    ///
    [Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
    public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
    {
    #region Help: Using Integration Services variables and parameters in a script
    /* To use a variable in this script, first ensure that the variable has been added to
    * either the list contained in the ReadOnlyVariables property or the list contained in
    * the ReadWriteVariables property of this script task, according to whether or not your
    * code needs to write to the variable. To add the variable, save this script, close this instance of
    * Visual Studio, and update the ReadOnlyVariables and
    * ReadWriteVariables properties in the Script Transformation Editor window.
    * To use a parameter in this script, follow the same steps. Parameters are always read-only.
    *
    * Example of reading from a variable:
    * DateTime startTime = (DateTime) Dts.Variables[“System::StartTime”].Value;
    *
    * Example of writing to a variable:
    * Dts.Variables[“User::myStringVariable”].Value = “new value”;
    *
    * Example of reading from a package parameter:
    * int batchId = (int) Dts.Variables[“$Package::batchId”].Value;
    *
    * Example of reading from a project parameter:
    * int batchId = (int) Dts.Variables[“$Project::batchId”].Value;
    *
    * Example of reading from a sensitive project parameter:
    * int batchId = (int) Dts.Variables[“$Project::batchId”].GetSensitiveValue();
    * */

    #endregion

    #region Help: Firing Integration Services events from a script
    /* This script task can fire events for logging purposes.
    *
    * Example of firing an error event:
    * Dts.Events.FireError(18, “Process Values”, “Bad value”, “”, 0);
    *
    * Example of firing an information event:
    * Dts.Events.FireInformation(3, “Process Values”, “Processing has started”, “”, 0, ref fireAgain)
    *
    * Example of firing a warning event:
    * Dts.Events.FireWarning(14, “Process Values”, “No values received for input”, “”, 0);
    * */
    #endregion

    #region Help: Using Integration Services connection managers in a script
    /* Some types of connection managers can be used in this script task. See the topic
    * “Working with Connection Managers Programatically” for details.
    *
    * Example of using an ADO.Net connection manager:
    * object rawConnection = Dts.Connections[“Sales DB”].AcquireConnection(Dts.Transaction);
    * SqlConnection myADONETConnection = (SqlConnection)rawConnection;
    * //Use the connection in some code here, then release the connection
    * Dts.Connections[“Sales DB”].ReleaseConnection(rawConnection);
    *
    * Example of using a File connection manager
    * object rawConnection = Dts.Connections[“Prices.zip”].AcquireConnection(Dts.Transaction);
    * string filePath = (string)rawConnection;
    * //Use the connection in some code here, then release the connection
    * Dts.Connections[“Prices.zip”].ReleaseConnection(rawConnection);
    * */
    #endregion

    public const int _bufferSize = 1024 * 1000; // 1M mas que suficiente.

    /**
    * se requiere con las funciones del API, luego, como respuesta se recibe JSON.
    * aun hay que verificar como es enviado el archivo…..
    */
    string baseURL = “https://api.etadirect.com”;

    //string listFilesAPI = “/rest/ofscCore/v1/folders/dailyExtract/folders/${DATE}/files/?company=${COMPANY}”;
    //string getDeFileAPI = “/rest/ofscCore/v1/folders/dailyExtract/folders/${DATE}/files/${FILENAME}?company=${COMPANY}”;
    string repoToa = “”;

    /**
    * Callback para validar el certificado desde la red.
    */
    public bool AcceptAllCertifications(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certification, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
    {
    return true;
    }

    /**
    * Copia el stream src (usualmente el archivo de la red)
    * en el stream dest (usualmente el archivo de salida).
    */
    private void CopyStream(StreamReader src, StreamWriter dest)
    {
    var buffer = new char[_bufferSize];
    int len;
    while ((len = src.Read(buffer, 0, buffer.Length)) > 0)
    {
    dest.Write(buffer, 0, len);
    }
    }

    /**
    * Consigue el archivo del dia fDate desde la direccion EtaDirect reqURL,
    * lo deja en repoToa
    */
    public void WRequest(string fDate, string reqURL)
    {
    try
    {
    ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(AcceptAllCertifications);
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Ssl3;
    CookieContainer myContainer = new CookieContainer();

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(baseURL + reqURL)) as HttpWebRequest;

    //+
    Uri uri = null;
    Uri.TryCreate(baseURL, UriKind.Absolute, out uri);
    //
    var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(“api@gtd:gtd12345”); //System.Text.Encoding.UTF8.GetBytes(“rest_API:toa*2016”);
    request.Headers.Add(HttpRequestHeader.Authorization, “Basic ” + System.Convert.ToBase64String(plainTextBytes));
    request.Accept = “application/octect-stream”;
    //.
    request.CookieContainer = myContainer;
    request.PreAuthenticate = true;
    request.KeepAlive = false;
    request.ProtocolVersion = HttpVersion.Version10;
    request.Timeout = 10000;
    request.AllowAutoRedirect = true;

    System.Net.ServicePointManager.Expect100Continue = false;

    Console.Error.WriteLine(“Content-Type : {0}”, request.GetResponse().ContentType);
    Console.Error.WriteLine(“Content-Lenght : {0}”, request.GetResponse().ContentLength);

    String filename = “”;

    using (var myStreamReader = new StreamReader(request.GetResponse().GetResponseStream(), System.Text.Encoding.Default, false))
    {
    filename = “gtd.xml.” + fDate + “.zip”;

    StreamWriter myStreamWriter = new StreamWriter(repoToa + @”\” + filename, false, System.Text.Encoding.Default);
    CopyStream(myStreamReader, myStreamWriter);
    myStreamReader.Close();
    myStreamWriter.Close();
    }

    //Console.WriteLine(“Archivo en : ” + repoToa + @”\” + filename);
    var apa = false;
    Dts.Events.FireInformation(1, “TRACE”, “Archivo en : ” + repoToa + @”\” + filename, “”, 0, ref apa);

    }
    catch (System.InvalidCastException e)
    {
    var apa = false;
    Dts.Events.FireInformation(1, “TRACE”, “InvalidCastException : ” + e.Message, “”, 0, ref apa);
    Dts.TaskResult = (int)ScriptResults.Failure;
    return;
    }
    catch (System.Net.ProtocolViolationException e)
    {
    var apa = false;
    Dts.Events.FireInformation(1, “TRACE”, “ProtocolViolationException : ” + e.Message, “”, 0, ref apa);
    Dts.TaskResult = (int)ScriptResults.Failure;
    return;
    }
    catch (System.NotSupportedException e)
    {
    var apa = false;
    Dts.Events.FireInformation(1, “TRACE”, “NotSupportedException : ” + e.Message, “”, 0, ref apa);
    Dts.TaskResult = (int)ScriptResults.Failure;
    return;
    }
    catch (System.Net.WebException e)
    {
    var apa = false;
    Dts.Events.FireInformation(1, “TRACE”, “Net.WebException : ” + e.Message, “”, 0, ref apa);
    Dts.TaskResult = (int)ScriptResults.Failure;
    return;
    }
    catch (Exception e)
    {
    //Console.WriteLine(e.Message);
    var apa = false;
    Dts.Events.FireInformation(1, “TRACE”, “Exception : ” + e.Message, “”, 0, ref apa);
    Dts.TaskResult = (int)ScriptResults.Failure;
    return;
    }
    }

    /**
    * Extrae los archivos .xml desde fName dentro de la carpeta iFolder
    */
    public void ExtractXMLFiles(string fName, string iFolder)
    {
    // extraemos los .xml desde el daily extract
    //using (ZipArchive arch = ZipFile.OpenRead(fName))
    //{
    // foreach (ZipArchiveEntry entry in arch.Entries)
    // {
    // if (entry.Name.Contains(“.xml”))
    // entry.ExtractToFile(Path.Combine(iFolder, entry.FullName));
    // }
    //}
    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.CreateNoWindow = false;
    startInfo.UseShellExecute = false;
    startInfo.WindowStyle = ProcessWindowStyle.Hidden | ProcessWindowStyle.Minimized;
    startInfo.FileName = “7z.exe”;
    startInfo.Arguments = ” e -y -o” + iFolder + ” ” + fName + ” *.xml”;

    try
    {
    // Start the process with the info we specified.
    // Call WaitForExit and then the using-statement will close.
    using (Process exeProcess = Process.Start(startInfo))
    {
    exeProcess.WaitForExit();
    }
    }
    catch (Exception e)
    {
    // Log error.
    //Console.WriteLine(e.Message);
    var apa = false;
    Dts.Events.FireInformation(1, “TRACE”, “Exception : ” + e.Message, “”, 0, ref apa);
    Dts.TaskResult = (int)ScriptResults.Failure;
    }
    }

    ///
    /// This method is called when this script task executes in the control flow.
    /// Before returning from this method, set the value of Dts.TaskResult to indicate success or failure.
    /// To open Help, press F1.
    ///
    public void Main()
    {
    // La relaci?n con el contexto del SSIS….
    //
    string dayExtract = null;

    TimeSpan ts = new TimeSpan(2, 0, 0, 0);
    dayExtract = DateTime.Today.Subtract(ts).ToString(“yyyy-MM-dd”);

    string fileDate = “”;
    DateTime dDate;
    if (DateTime.TryParse(dayExtract, out dDate))
    {
    fileDate = String.Format(“{0:yyyy-MM-dd}”, dDate);
    }
    else
    {
    //Console.WriteLine(“Error: Fecha invalida.”);
    var apa = false;
    Dts.Events.FireInformation(1, “TRACE”, “Exception : Fecha invalida.”, “”, 0, ref apa);
    Dts.TaskResult = (int)ScriptResults.Failure;
    }

    /**
    * Ajustamos carpeta de respaldo de los archivos descargados desde el EtaDirect
    */
    repoToa = Dts.Variables[“DriveName”].Value + @”\repoToa”;

    if (repoToa == null || repoToa == String.Empty)
    {
    repoToa = @”E:\EtaDirect\repoToa”;
    //Console.WriteLine(“INFO: Empleando valor por defecto para espacio de respaldo REPOTOA : ” + repoToa);
    }

    if (!Directory.Exists(repoToa))
    {
    Directory.CreateDirectory(repoToa);
    }

    /**
    * Ajustamos el espacio de trabajo para este proceso
    */
    string wkDir = Dts.Variables[“DriveName”].Value + @”\etltemp”;
    if (wkDir == null || wkDir == String.Empty)
    {
    wkDir = @”E:\EtaDirect\etltemp”;
    //Console.WriteLine(“INFO: Empleando valor por defecto para espacio de trabajo TEMP : ” + wkDir);
    }

    //string fileDesde = wkDir + @”\xml”;

    if (!Directory.Exists(wkDir))
    {
    Directory.CreateDirectory(wkDir);
    Directory.CreateDirectory(wkDir + @”\xml”); // aqui se dejan los extraidos, tipo meta
    Directory.CreateDirectory(wkDir + @”\forProceso”); // aqui se dejan los traducidos
    }

    /**
    * Borramos los archivos de .\xml\*.*
    */
    System.IO.DirectoryInfo directoryXml = new System.IO.DirectoryInfo(wkDir + @”\xml”);
    foreach (System.IO.FileInfo file in directoryXml.GetFiles()) file.Delete();

    /**
    * Borramos los archivos de .\forProceso\*.*
    */
    System.IO.DirectoryInfo directoryPro = new System.IO.DirectoryInfo(wkDir + @”\forProceso”);
    foreach (System.IO.FileInfo file in directoryPro.GetFiles()) file.Delete();

    /**
    * Aqui nos conectamos al API y usamos API REStful documentados…..
    * para descargar el .zip correspondiente al dia (actual – 2)
    */
    string lstFile = “/rest/ofscCore/v1/folders/dailyExtract/folders/” + fileDate + “/files/?company=gtd”;
    //string getFile = “/rest/ofscCore/v1/folders/dailyExtract/folders/” + fileDate + “/files/gtd.xml.” + fileDate + “.zip?company=gtd”;
    string getFile = “/rest/ofscCore/v1/folders/dailyExtract/folders/2017-11-01/files/gtd.xml.2017-11-01.zip”;

    // TRACE:
    //Console.Error.WriteLine(“wkDir : ” + wkDir);
    //Console.Error.WriteLine(“xml : ” + wkDir + @”\xml”);
    //Console.Error.WriteLine(“forProcess : ” + wkDir + @”\forProceso”);
    //Console.WriteLine(“lstFile = ” + lstFile);
    //Console.WriteLine(“getFile = ” + getFile);
    //.
    {
    var apa = false;
    Dts.Events.FireInformation(1, “TRACE”, “wkDir : ” + wkDir, “”, 0, ref apa);
    Dts.Events.FireInformation(1, “TRACE”, “xml : ” + wkDir + @”\xml”, “”, 0, ref apa);
    Dts.Events.FireInformation(1, “TRACE”, “forProcess : ” + wkDir + @”\forProceso”, “”, 0, ref apa);
    Dts.Events.FireInformation(1, “TRACE”, “fileDate : ” + fileDate, “”, 0, ref apa);
    Dts.Events.FireInformation(1, “TRACE”, “getFile : ” + getFile, “”, 0, ref apa);
    }

    /**
    * Aqui solo no interesa recuperar un solo archivo….
    * el que tiene la ultima fecha no descargado, la fecha debe ser tomada desde parametro $1
    * Esto deja el archivo descargado en “repoToa”
    */
    WRequest(fileDate, getFile);

    //
    string fName = repoToa + @”\gtd.xml.” + fileDate + “.zip”;
    string iFolder = wkDir + @”\xml”;
    ExtractXMLFiles(fName, iFolder);

    //Console.WriteLine(“Ok, todo bien.”);

    // ajustamos el retorno para el SSIS
    //Dts.TaskResult = (int)ScriptResults.Success;

    Dts.TaskResult = (int)ScriptResults.Success;
    }

    #region ScriptResults declaration
    ///
    /// This enum provides a convenient shorthand within the scope of this class for setting the
    /// result of the script.
    ///
    /// This code was generated automatically.
    ///
    enum ScriptResults
    {
    Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
    Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
    };

    #endregion

    }
    }

  12. Hola Jackfiallos, muy interesante tu aporte, lo que yo quisiera es enviar datos desde un cliente c# (wsp) a un servidor php donde se encuentran los servicios rest, me puedes dar una idea de como podría hacerlo por favor?

    De antemano, muchas gracias.

  13. Buenas, muy buen post solo que cuando intento hacer esto me da error

    var postString = new {
    “employee”: “admin”,
    “date_in”: “2019-03-12T14:00:00”,
    “date_out”: “2019-03-15T11:00:00”,
    “language”: “en”,
    “guest_name”: “John Doe”,
    “open_zaccess”: false,
    “multiple_card”: false,
    “remote_control_always”: false,
    “pax”: 1,
    “room_service”: 0
    };

  14. Hola Jack! interesante tu aporte, estoy buscando ideas para resolver un dilema com mi API desarrollada en .Net, el caso se me da con un request recien modificado, donde se incluye unos montos con decimales en el response.

    Desde mi proyecto VS funciona muy bien, la respuesta muestra los valores esperados, pero cuando publico en el servidor, no obtengo la misma respuesta. los valores llegan como cero.

    De tantas consultas y pruebas, lo próximo será validar el conjunto de caracteres de mi localhost, contra el servidor destino. Si tienes alguna recomendación sería bien apreciada…

  15. Hola muy buenas tardes,
    el servidor me responde en la variable Body, un html (una paginita)
    de que manera puedo desplegar ese resultado en una pagina en blanco?

  16. Saludos.

    Caramba, yo no entiendo, que es valor 1 y valor 2 los parámetros del web service, me parece que para personas que para personas que iniciamos, le falta explicación, disculpas al autor, pero lo entiend.

Deja un comentario

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