none
Respuesta de servicio REST muestra lista vacia. RRS feed

  • Pregunta

  • Estoy consumiendo 2 servicios webs (hechos en java) recibiendo datos por metodo POST. Tengo mi servicio de login y mi servicio de listarcarros. A mi login le pongo 2 parametros: usuario y contraseña. A mi listarcarros no tiene ningun parametro y lista vacio. Sin embargo, mediante postman, cuando hago mi peticion de login con su usuario y contraseña, y luego hago una peticion a mi listarcarros, de alguna manera mi listarcarros esta logueado y lista los carros correspondientes. He leido un poco que es porque se genera un token para el ip que ha sido llamado por un tiempo limitado.

    Mi problema es cuando quiero hacer mi peticion por c# en consola de mi servicio de login con sus respectivos parametros, extraigo los datos correctamente pero luego realizo mi peticion de listarcarros, me bota vacio.

    Segun tengo entendido solo tenia que hacer mi peticion de login y si es correcto de alguna manera en el servidor web, detectando mi ip, me botaba mi listarcarros sin usar ningun parametro.

    Aclaro que mi aplicativo está hecho en consola por motivos de prueba y una mas facil depuracion pero está pensado para que funcioné en Xamarin. Y en resumen: el login me funciona correctamente en el codigo de c# pero el servidor no detecta que estoy logeado por lo cual no puedo listar los carros pero si me detecta cuando hago el mismo procedimiento por postman.

    // Segun me explicaron desde aqui me logueo desde el servidor
    public async void Ingreso(string url)
            {
                var client = new HttpClient();
                var uri = new Uri(string.Format(url+"/logeocliente.htm"string.Empty));
                string jsonData = @"{""usuario"" : ""admin""""clave"" : ""admin""}";
                var contentPOST = new StringContent(jsonDataEncoding.UTF8"application/json");
                var response = client.PostAsync(uricontentPOST).Result;
                response.EnsureSuccessStatusCode(); 
                var resultado = await response.Content.ReadAsStringAsync(); //esto lee los datos si quisiera extraerlo
            }
    // Una vez logeado con solo hacer la peticion anterior de login, deberia listarme los carros segun mi usuario
    // No logro recibir ningun dato del servidor
    public async Task<ObservableCollection<Carro>> ObtenerCarro(string url)
            {
                var client = new HttpClient();
                var uri = new Uri(string.Format(url+"/mobile/listacarro.htm"string.Empty));
                string jsonData = @"";
                var contentPOST = new StringContent(jsonDataEncoding.UTF8"application/json");
                var response = client.PostAsync(uricontentPOST).Result;
                response.EnsureSuccessStatusCode();
                var resultado = await response.Content.ReadAsStringAsync();
                var items = JsonConvert.DeserializeObject<ObservableCollection<Carro>>(resultado);
                return items;
            }

    //En ambos casos mi respuesta es de estatus 200.


    sábado, 4 de enero de 2020 21:03

Respuestas

  • Segun tengo entendido solo tenia que hacer mi peticion de login y si es correcto de alguna manera en el servidor web, detectando mi ip, me botaba mi listarcarros sin usar ningun parametro.

    Dudo mucho que funcione así. La IP no es una buena forma de detectar el llamante, porque podría estar detrás de una pasarela NAT, podría haber varios clientes distintos detrás de la misma IP NAT, podría tener una IP dinámica, podría tener varias IPs con round-robin, etc. etc. Por lo tanto, los sistemas de autenticación de los Web Services normalmente NO se basan en la dirección IP del llamante, y si lo hacen entonces fallan con mucha frecuencia.

    Usualmente lo que ocurre es que cuando llamas a la API de login te devuelve "algo" que luego tienes que enviar en las sucesivas peticiones para demostrar que te has autenticado. Ese "algo" se puede enviar de distintas formas, como por ejemplo un valor en una cabecera HTTP, o un parámetro adicional en las llamadas a las APIs. No hay para esto un mecanismo universal y único, así que tendrás que consultar la documentación de tu API para ver cómo lo implementa.

    • Propuesto como respuesta Diana AcuñaModerator lunes, 6 de enero de 2020 16:34
    • Marcado como respuesta iiFranz martes, 4 de febrero de 2020 16:08
    domingo, 5 de enero de 2020 8:08
    Moderador
  • Después de tanto, ese "algo" que el API tenia que devolverme eran las cookies y dichas cookies los usaría para identificar a mi usuario cada vez que quiera listar mi listarcarros. Les dejó mi codigo terminado. Gracias por la ayuda.

    // Aqui almacenaré la cookie que está en el Headers pero
    // lo ideal seria usar una variable de session pero estoy
    // usando la app de consola. 
    string cookieSession;
    public async void Ingreso(string url)
            {
            var client = new HttpClient();
            var uri = new Uri(string.Format(url+"/logeocliente.htm"string.Empty));
            string jsonData = @"{""usuario"" : ""admin""""clave"" : ""admin""}";
            var contentPOST = new StringContent(jsonDataEncoding.UTF8"application/json");
            var response = client.PostAsync(uricontentPOST).Result;
            //Guardo mi cookie en la siguiente variable
            cookieSession = response.Headers.GetValues("Set-Cookie").First().Substring(11);
            response.EnsureSuccessStatusCode(); 
        }
    public async Task<ObservableCollection<Carro>> ObtenerCarro(string url)
        {
            var client = new HttpClient();
            HttpMethod method = HttpMethod.Post;            
            var uri = new Uri(string.Format(url+"/mobile/listacarro.htm"string.Empty));
            var request = new HttpRequestMessage(methoduri);
            //Establezco mi cookie en mi headers
            request.Headers.TryAddWithoutValidation("Cookie""JSESSIONID=" + cookieSession);
            string jsonData = @"";
            request.Content = new StringContent(jsonDataEncoding.UTF8"application/json");
            var response = client.SendAsync(request).Result;
            var resultado = await response.Content.ReadAsStringAsync();
            var items = JsonConvert.DeserializeObject<ObservableCollection<Carro>>(resultado);
            return items;
        }


    • Marcado como respuesta iiFranz martes, 7 de enero de 2020 21:39
    • Editado iiFranz martes, 7 de enero de 2020 21:41 Error de palabra
    martes, 7 de enero de 2020 21:32

Todas las respuestas

  • Segun tengo entendido solo tenia que hacer mi peticion de login y si es correcto de alguna manera en el servidor web, detectando mi ip, me botaba mi listarcarros sin usar ningun parametro.

    Dudo mucho que funcione así. La IP no es una buena forma de detectar el llamante, porque podría estar detrás de una pasarela NAT, podría haber varios clientes distintos detrás de la misma IP NAT, podría tener una IP dinámica, podría tener varias IPs con round-robin, etc. etc. Por lo tanto, los sistemas de autenticación de los Web Services normalmente NO se basan en la dirección IP del llamante, y si lo hacen entonces fallan con mucha frecuencia.

    Usualmente lo que ocurre es que cuando llamas a la API de login te devuelve "algo" que luego tienes que enviar en las sucesivas peticiones para demostrar que te has autenticado. Ese "algo" se puede enviar de distintas formas, como por ejemplo un valor en una cabecera HTTP, o un parámetro adicional en las llamadas a las APIs. No hay para esto un mecanismo universal y único, así que tendrás que consultar la documentación de tu API para ver cómo lo implementa.

    • Propuesto como respuesta Diana AcuñaModerator lunes, 6 de enero de 2020 16:34
    • Marcado como respuesta iiFranz martes, 4 de febrero de 2020 16:08
    domingo, 5 de enero de 2020 8:08
    Moderador
  • hola

    >>Estoy consumiendo 2 servicios webs (hechos en java) recibiendo datos por metodo POST.

    a que servicio web haces referencia, en el codigo veo la url de paginas .htm, eso no son ningun servicio de ningun tipo

    solo son paginas web estaticas que retornan html


    >>He leido un poco que es porque se genera un token para el ip que ha sido llamado por un tiempo limitado.

    existe la autenticacion usando token, pero por lo que explicas no veo que sea tu caso

    >>el login me funciona correctamente en el codigo de c# pero el servidor no detecta que estoy logeado

    pues la verdad no logro entender que puede estar autenticandote cuando solo invocas paginas htm

    me pregunto, sabes lo que son paginas html, no? porque eso no es ningun servicio, ni en java ni en ningun otro lenguaje

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    lunes, 6 de enero de 2020 5:03
  • Les pondré un poco en contexto. Mi objetivo es replicar un aplicativo movil, hecho en cordova, y hacerlo en Xamarin forms. Este aplicativo hecho en cordova, segun me explicaron, es una pagina web html y lo convierte en un aplicativo movil. Dentro del codigo javascript,

    $$.ajax({
        type: 'POST',
        contentType: 'application/json',
        data: JSON.stringify(usuario), 
        url: server+"mobile/logeocliente.htm",
        timeout:60000,
        success: function(consulta){
            myApp.hidePreloader();
            consulta = JSON.parseSON.parse(consulta);
            if(consulta.codgt==null && consulta.codigo==null){                           
                 myApp.alert('Datos Incorrectos','MOVIL')
            }            
            else{                
                var apellido="";
                if(consulta.tipo=='u'){
                    tipo='u'
                    activate_subpage("#page_7_38"); 
                    $$("#btnclave").css('display','none');
                    if(consulta.apellidos!=null){apellido=consulta.apellidos.toLowerCase()}
                    $$("#nomusuario").html("Bienvenido: "+consulta.nombre+" "+apellido);
                    listarcarros(); // Aqui lista los carros y sale correctamente
                }
            }
        },
        error: function(XMLHttpRequesttextStatuserrorThrown) {
                    myApp.hidePreloader();
                    myApp.alert("No es posible conectar con el servidor, Error: "+textStatus,"MOVIL");
                }
    });

    --Soy nuevo en el foro y mi cuenta aun no está verificada y no me deja pasar links. Pueden agregarle http:// a cada url

    El servidor que uso es 66.240.210.107:8090

    Mi login: 66.240.210.107:8090/mobile/logeocliente.htm

    Mi listar carros: 66.240.210.107:8090/mobile/listacarro.htm  

    Pueden usar el usuario de pruebas que tengo y todas las peticiones son POST. Al logeocliente deben agregarle estos parametros:

    {
    "login":"wruiz",
    "clave":"wruiz"
    }

    Lo que observé fue que, en postman, cuando hago la peticion a listacarro recibo una lista vacia, sin embargo cuando hago la peticion de logeocliente con sus parametros  y luego vuelvo a hacer la peticion a listarcarro me devuelve la lista de carros del usuario wruiz (ya lo habia explicado, solo quiero aclararlo). Por ultimo, cuando pasa un tiempo (15min prox) y vuelvo a listar los carros me vuelve a mostrar vacio, indicandome que la sesión tiene un limite de tiempo.  Por esta razon pensé que iba a ser suficiente con solo hacer la peticion a logeocliente para luego listar los carros, pero no es asi. No tengo mucha experiencia en servicios webs, anteriormente solo habia hecho un crud basico pero me parece que es de mala practica recibir los datos mediante POST, pero es lo que tengo y mi objetivo solo es consumir dicha informacion.

    Espero haber sido mucho mas claro ahora. Como dicen, necesito ese "algo" que devuelve mi API de login pero no se como obtenerlo. Al menos ahora tengo mis ideas mas claras. Muchas gracias. Estaré pendiente del hilo. Si logro solucionarlo les informaré. 

    lunes, 6 de enero de 2020 16:29
  • hola

    >>Este aplicativo hecho en cordova, segun me explicaron, es una pagina web html y lo convierte en un aplicativo movil.

    bien, pero tu no deberias usar ese htm para autenticarte

    deberias analizar el codigo que la app cordova y ver a que servicio invoca en la autenticacion

    >>Mi login: 66.240.210.107:8090/mobile/logeocliente.htm

    eso no es un login, es una pagina htm

    >>No tengo mucha experiencia en servicios webs

    y no la necesitas porque no estas usando ningun servicio web

    esto es un servicio web api

     How to Create Web API in ASP.Net MVC

    no es ni remotamente parecido a lo que estas realizando

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    lunes, 6 de enero de 2020 19:57
  • Gracias por aclararme algunas dudas. Hasta el momento yo consideraba servicio web como API pero ya veo que no son los mismos. Asi mismo, continuando con ese "algo" que debia obtener creo haber encontrado que es.

    Investigando me encontré que lo mas posible es que mi API usa las cookies para identificarse. Este es un comentario que encontre en otro foro. 

    >>Básicamente: Si usas una cookie tan solo se podrá autenticar quien envie la cookie. Si tu único cliente es una aplicación web, que está en el mismo origen, entonces no tendrás problema. Pero si tu cliente NO es un navegador (p. ej. es una app móvil) entonces este cliente no enviará la cookie a no ser que el cliente ponga código específico para ello.<<

    Ahora lo que estoy intentando hacer es extraer la cookie de mi cabecera  de mi metodo Ingreso() que es este:

    Headers = {Set-Cookie: JSESSIONID=24EA5D3797423E30EFC33530FA6F3B96; Path=/mobile; HttpOnly
    Transfer-Encoding: chunked
    Date: Mon, 06 Jan 2020 17:44:19 GMT
    }

    Dentro de mi metodo ObtenerCarro() obtengo otra cookie con diferente JSESSIONID. Ahora veo la forma de autenticar mi lista de carros con JSESSIONID obtenido anteriormente.

    Si voy por un mal camino, me avisan. Gracias por sus respuestas.

    Editado

    Fuente:

    https://social.msdn.microsoft.com/Forums/es-ES/c419dd5a-28a6-4e15-a106-045324eecc56/respuesta-de-servicio-rest-muestra-lista-vacia?forum=vcses


    • Editado iiFranz martes, 7 de enero de 2020 14:25
    martes, 7 de enero de 2020 0:24
  • Después de tanto, ese "algo" que el API tenia que devolverme eran las cookies y dichas cookies los usaría para identificar a mi usuario cada vez que quiera listar mi listarcarros. Les dejó mi codigo terminado. Gracias por la ayuda.

    // Aqui almacenaré la cookie que está en el Headers pero
    // lo ideal seria usar una variable de session pero estoy
    // usando la app de consola. 
    string cookieSession;
    public async void Ingreso(string url)
            {
            var client = new HttpClient();
            var uri = new Uri(string.Format(url+"/logeocliente.htm"string.Empty));
            string jsonData = @"{""usuario"" : ""admin""""clave"" : ""admin""}";
            var contentPOST = new StringContent(jsonDataEncoding.UTF8"application/json");
            var response = client.PostAsync(uricontentPOST).Result;
            //Guardo mi cookie en la siguiente variable
            cookieSession = response.Headers.GetValues("Set-Cookie").First().Substring(11);
            response.EnsureSuccessStatusCode(); 
        }
    public async Task<ObservableCollection<Carro>> ObtenerCarro(string url)
        {
            var client = new HttpClient();
            HttpMethod method = HttpMethod.Post;            
            var uri = new Uri(string.Format(url+"/mobile/listacarro.htm"string.Empty));
            var request = new HttpRequestMessage(methoduri);
            //Establezco mi cookie en mi headers
            request.Headers.TryAddWithoutValidation("Cookie""JSESSIONID=" + cookieSession);
            string jsonData = @"";
            request.Content = new StringContent(jsonDataEncoding.UTF8"application/json");
            var response = client.SendAsync(request).Result;
            var resultado = await response.Content.ReadAsStringAsync();
            var items = JsonConvert.DeserializeObject<ObservableCollection<Carro>>(resultado);
            return items;
        }


    • Marcado como respuesta iiFranz martes, 7 de enero de 2020 21:39
    • Editado iiFranz martes, 7 de enero de 2020 21:41 Error de palabra
    martes, 7 de enero de 2020 21:32