none
Consumir un WebService RRS feed

  • Pregunta

  • Hola comunidad.

    Aqui estoy de nuevo volviendome loco, y como siempre, tras unos dias intentanto leer informacion de aqui y de alli, consultando MSDN por todos lados y conseguir lo que quiero, aqui va el tema.

    Tengo una app para Windows 8 que he migrado ha windows 8.1 sin problema, la tengo que probar en Windows 10 a ver que tal, pero creo que tambien funcionara. El tema esta en que esta aplicacion se comunica con el servidor de dos maneras.

    Por un lado hace una comunicacion tipo CHAT.
    Por otro obtiene datos de la base de datos del servidor mediente un servicio web.

    Cuando he migrado la aplicacion a Windows Phone me he encontrado con 2 problemas.

    Primero (solucionado) es que Windows Phone no soporta WebService directamente, por lo que he optado por utilizar una aplicacion Windows Phone Silverlight que si lo soporta.

    Segudo (el que me tiene loco) Cuando agrego el Web Service siempre me poner todos los metodos como VOID, y no como String que es el formato en el que me devuelve los datos.

    He intentado cambiar esto y que me devuelva string mediente Task<string> y entonces me encuentro con el problema de que Silverlight no soporta Task.

    Utilizando el namespace Windows.Web he conseguido comunicar, pero mi problema es que no se como hacer que ejecute el servicio web.

            public async Task<string> CallService()
            {
                Uri url = new Uri("https://service.xxx.com/service_phone/Phone.svc/GetData/sergi");
                HttpClient httpClient = new HttpClient();
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get,url);
                HttpResponseMessage response = await httpClient.SendRequestAsync(request);
                string data = await response.Content.ReadAsStringAsync();
                return data;
            }

    En mis pruebas tengo dos servicios web, este llamado Phone.svc creado con WCF y otro creado con webservice en ASP directamente

    https://service.xxx.com/service_phone/WindowsUp7.aspx

    El lenguaje utilizado siempre en c# que me olvide de comentarlo.

            public static async Task<string> executeQUERY(string commandSQL, int col)
            {
                webService.WindowsUp7SoapClient ws = new webService.WindowsUp7SoapClient();
                string xDoc = await ws.ObtenerDatoAsync(commandSQL, col);
                await ws.CloseAsync();
                ws = null;
                return xDoc;
            }

    Esta procedimiento me da un campo de la consulta que ejecute. "SELECT Nombre, Apellido FROM CLientes" Col indica la posicion del campo que quiero 0, para nombre, 1 para Apellido... esto es solo un ejemplo para que entiendan el metodo.

    Pues bien, este metodo como pueden observer, me retorna un string con el dato que quiero, porque el objero webservice tiene todo como Task<string> a la hora de llamar al servicio web.

    En windows no hay problema pero en Phone no puedo hacerlo asi.

    Tambien he intentao algo como esto, que aparentemente deberia de funcionar.

        class DataTest
        {
            public string query { get; set; }
            public int col { get; set; }
            public string parametro { get; set; }
            public string retorno { get; set; }
    
            public DataTest(string nameSP, int col = 1, string param = "")
            {
                this.query = nameSP;
                this.col = col;
                this.parametro = param;
    
                ServiceReference1.WindowsUp7SoapClient proxy = new ServiceReference1.WindowsUp7SoapClient();
                proxy.ObtenerDatoCompleted += new EventHandler<ServiceReference1.ObtenerDatoCompletedEventArgs>(execute);
                proxy.ObtenerDatoAsync(this.query, this.col);
            }
    
            /// <summary>
            /// Execute a Storage Procedure and return XML data
            /// </summary>
            /// <param name="nameSP">Name of storage procedure</param>
            /// <param name="param">Params with separator ","</param>
            /// <returns>XML with result</returns>
            public void execute(object sender, ServiceReference1.ObtenerDatoCompletedEventArgs e)
            {
                this.retorno = e.Result;
            }
    }


    En este caso el objero webService ya solo retorna VOID...

    Mi problema es, "como puedo ejecutar [execute] si no tengo un objero que envia la peticion?" a ver si me explico, el tema seria algo asi.

                DataTest cnn = new DataTest("HOLA",1);
                cnn.execute();
                string dato = cnn.retorno;

    Pero no tengo un "sender" ni un "Evento" para pasar...

    Muchas gracias de antemano. Espero que me hayan comprendido lo que necestio y como siemrpe JUNTOS encontremos la solucion...

    Como estoy bloqueadiiisimo voy a cambiar de proyecto a una web que tengo en lo que espero respuestas, dejo de buscar como otras veces....


    DrUalcman

    viernes, 18 de diciembre de 2015 3:25

Respuestas

  • Hola de nuevo. Como siempre cuando consigo las cosas las publico para que quede constancia.

    Como ya decia en mi post este codigo

      class DataTest
        {
            public string query { get; set; }
            public int col { get; set; }
            public string parametro { get; set; }
            public string retorno { get; set; }
    
            public DataTest(string nameSP, int col = 1, string param = "")
            {
                this.query = nameSP;
                this.col = col;
                this.parametro = param;
    
                ServiceReference1.WindowsUp7SoapClient proxy = new ServiceReference1.WindowsUp7SoapClient();
                proxy.ObtenerDatoCompleted += new EventHandler<ServiceReference1.ObtenerDatoCompletedEventArgs>(execute);
                proxy.ObtenerDatoAsync(this.query, this.col);
            }
    
            /// <summary>
            /// Execute a Storage Procedure and return XML data
            /// </summary>
            /// <param name="nameSP">Name of storage procedure</param>
            /// <param name="param">Params with separator ","</param>
            /// <returns>XML with result</returns>
            public void execute(object sender, ServiceReference1.ObtenerDatoCompletedEventArgs e)
            {
                this.retorno = e.Result;
            }

    Es el que funciona, lo que yo soy un poco tonto a veces, sobre todo cuando me bloqueo como el otro dia, y no me doy cuenta de las cosas bien. 

    El tema esta en que no se puede poner en un modulo aparte, en donde lo necesites tienes que poner

    // la llamada al servicio con los parametros que necesite cada llamada
    
                ServiceReference1.WindowsUp7SoapClient proxy = new ServiceReference1.WindowsUp7SoapClient();
                proxy.ObtenerDatoCompleted += new EventHandler<ServiceReference1.ObtenerDatoCompletedEventArgs>(execute);
                proxy.ObtenerDatoAsync(query, col);  //parametros del servicio
    
    // y el evento que gestionara esos datos cuando sean recibidos
    
            public void execute(object sender, ServiceReference1.ObtenerDatoCompletedEventArgs e)
            {
                string retorno = e.Result;
    
                // mas el manejo de los datos
    
            }

    Yo de todas formas voy a ver si lo consigo poner dentro de algun modulo, ya que me gusta poder reutilizar el maximo codigo posible.

    Desde mi punto de vista, cuando se trabaja con muchos datos, como es mi caso, esto nos complica la vida a los programadores si no se puede poner en un modulo y hacerlo "algo mas reutilizable". Ya que el problema que tiene es que para manejar los datos retornados desbes tener un procidimiento como que como evento que espere por los datos, y asi se me complica mucho el codigo...

    Un saludo y espero que ayude a otros.

    DrUalcman

    P.D.: como siempre si alguien puede agregar algo mas, bienvenido sea, que para algo estan las actualizaciones :P


    DrUalcman

    martes, 22 de diciembre de 2015 0:15

Todas las respuestas

  • Hola de nuevo. Como siempre cuando consigo las cosas las publico para que quede constancia.

    Como ya decia en mi post este codigo

      class DataTest
        {
            public string query { get; set; }
            public int col { get; set; }
            public string parametro { get; set; }
            public string retorno { get; set; }
    
            public DataTest(string nameSP, int col = 1, string param = "")
            {
                this.query = nameSP;
                this.col = col;
                this.parametro = param;
    
                ServiceReference1.WindowsUp7SoapClient proxy = new ServiceReference1.WindowsUp7SoapClient();
                proxy.ObtenerDatoCompleted += new EventHandler<ServiceReference1.ObtenerDatoCompletedEventArgs>(execute);
                proxy.ObtenerDatoAsync(this.query, this.col);
            }
    
            /// <summary>
            /// Execute a Storage Procedure and return XML data
            /// </summary>
            /// <param name="nameSP">Name of storage procedure</param>
            /// <param name="param">Params with separator ","</param>
            /// <returns>XML with result</returns>
            public void execute(object sender, ServiceReference1.ObtenerDatoCompletedEventArgs e)
            {
                this.retorno = e.Result;
            }

    Es el que funciona, lo que yo soy un poco tonto a veces, sobre todo cuando me bloqueo como el otro dia, y no me doy cuenta de las cosas bien. 

    El tema esta en que no se puede poner en un modulo aparte, en donde lo necesites tienes que poner

    // la llamada al servicio con los parametros que necesite cada llamada
    
                ServiceReference1.WindowsUp7SoapClient proxy = new ServiceReference1.WindowsUp7SoapClient();
                proxy.ObtenerDatoCompleted += new EventHandler<ServiceReference1.ObtenerDatoCompletedEventArgs>(execute);
                proxy.ObtenerDatoAsync(query, col);  //parametros del servicio
    
    // y el evento que gestionara esos datos cuando sean recibidos
    
            public void execute(object sender, ServiceReference1.ObtenerDatoCompletedEventArgs e)
            {
                string retorno = e.Result;
    
                // mas el manejo de los datos
    
            }

    Yo de todas formas voy a ver si lo consigo poner dentro de algun modulo, ya que me gusta poder reutilizar el maximo codigo posible.

    Desde mi punto de vista, cuando se trabaja con muchos datos, como es mi caso, esto nos complica la vida a los programadores si no se puede poner en un modulo y hacerlo "algo mas reutilizable". Ya que el problema que tiene es que para manejar los datos retornados desbes tener un procidimiento como que como evento que espere por los datos, y asi se me complica mucho el codigo...

    Un saludo y espero que ayude a otros.

    DrUalcman

    P.D.: como siempre si alguien puede agregar algo mas, bienvenido sea, que para algo estan las actualizaciones :P


    DrUalcman

    martes, 22 de diciembre de 2015 0:15
  • Estimados comis,

    Encontre otra forma de hacerlo, algo mas "facil". Y que te funciona en TODAS las versiones de Windows Phone, ya que la forma comentada arriba solo es valida en Windows Phone 7 y en Windows Phone Silverlight.

    Con este codigo te libras de tener que hacer una declaracion de evento, pero solo es funcional si tu servicio es del tipo SOAP. Yo tenia mi servicio montado sobre un archivo ASMX y no SVC.

    Al acceder a la pagina del servicio tienes la lista con las funciones y al acceder a la funcion deseada te muestra el XML que tienes que enviar y lo que te retorna. En lo que tienes que enviar es lo que tienes, si acaso, que modificar en mi rutina.

    La rutina para que todos puedan disfrutar de ella es:

            /// <summary>  
            /// Utility function to post WCFRESTService  
            /// </summary>  
            /// <param name="methodName">WCFREST Method Name To POST</param>  
            /// <param name="bodyParam">Parameter of POST Method (Need serialize to XML before passed in). If have more than 1 separate with ;</param>  
            public static async Task<string> WCFRESTServiceCall(string methodName, string bodyParam = "")
            {
                //string respuesta = await webProxy.WCFRESTServiceCall("ConsultarConXML", "SELECT TOP 1 nombre, apellido1 FROM Clientes");
                try
                {
                    string ServiceURI = "[ruta exacta al servicio/nombre de la pagina].asmx";
                    string body = @"<?xml version=""1.0"" encoding=""utf-8""?>
                        <soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
                          <soap:Body>
                            <" + methodName + @" xmlns=""[ruta servicio web]"">";
                    string[] bodyParams;
    		// si tiene varios tipos de metodos con diferentes parametros es necesario diferenciarlos
                    switch (methodName)
                    {
                        case "getDateTime":
                            body += @"<format>" + bodyParam + @"</format>";
                            break;
                        case "MetodoCon2Parametros":
                            bodyParams = bodyParam.Split(';');
                            body += @"<param1>" + bodyParams[0] + @"</param1>";
                            body += @"<param2>" + bodyParams[1] + @"</param2>";
                            break;
                        case "MetodoSinMarametros":
                            break;
    		
    		.
    		.
    		.
                        default:
                            body += @"<param>" + bodyParam + @"</param>";
                            break;
                    }
    
                    body += @"</" + methodName + @">
                          </soap:Body>
                        </soap:Envelope>";
    
                    HttpClient httpClient = new HttpClient();
                    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, ServiceURI);
                    request.Content = new StringContent(body, System.Text.Encoding.UTF8, "text/xml");
                    HttpResponseMessage response = await httpClient.SendAsync(request);
                    string returnString = await response.Content.ReadAsStringAsync();
    
                    // get XML data
                    try
                    {
                        XDocument doc = XDocument.Parse(returnString);
                        XmlReader read = doc.CreateReader();
                        read.MoveToContent();
                        read.ReadToDescendant(methodName + "Result");
                        returnString = read.ReadElementContentAsString();
                        read = null;
                        doc = null;
                    }
                    catch (Exception ex)
                    {
                        returnString = "Error to get XML.\r\n" +  ex.Message + "\r\n" + ex.StackTrace;
                    }
                    return returnString;
                }
                catch (Exception ex)
                {
                    return "Error in request of service.\r\n" + ex.Message + "\r\n" + ex.StackTrace;
                }
            }
    Happy codding :D



    DrUalcman


    miércoles, 3 de febrero de 2016 3:14