none
API que consulta otra API RRS feed

  • Pregunta

  • Buen día, en esta oportunidad presento la siguiente inquietud, estoy desarrollando una aplicación ASP.Net Core 3.0 Web Api, para autenticación y consulta. Lo de la autenticación todo bien sin problemas. El inconveniente que presento que la conexión a la base de datos se realizar por api's y necesito crear un controlador que me permitar leer X cantidad de variables construir la consulta url, realizarla al servidor correspondiente, tomar el resultado y devolverla por la misma api, es mas o menos una especie de puente entre api's. tengo un procedimiento similar pero en web forms pero para este caso le estoy colocando seguridad por token. Les dejo el codigo del web forms en caso de haberme explicado bien. Gracias de antemano cualquier colaboración.

    Nota el código se encuentra en VB.net y quiero llevarlo a C pero para Web Api.

    Imports System.Net
    Imports System.IO
    Public Class JSON
        Inherits System.Web.UI.Page
    
        Public UserActivo As List(Of String)
    
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            Try
                UserActivo = DisplayName(User.Identity.Name)
            Catch ex As Exception
                Response.Redirect(FormsAuthentication.LoginUrl, False)
            End Try
            Dim JSONURL As String
            Dim text_url As String = Request.QueryString("url")
            Dim text_program As String = Request.QueryString("programa")
    
            text_url = text_url.Replace("https:", "http:")
    
            JSONURL = text_url + text_program + "?"
    
            For Each itm In Request.QueryString()
                If Not (itm = "url" Or itm = "programa") Then
                    JSONURL &= itm + "=" + Request.QueryString(itm) + "&"
                End If
            Next
    
    
            Dim reader As StreamReader
            Dim xRequest As HttpWebRequest = CType(WebRequest.Create(JSONURL), HttpWebRequest)
            Dim xResponse As HttpWebResponse = CType(xRequest.GetResponse(), HttpWebResponse)
    
            reader = New StreamReader(xResponse.GetResponseStream())
    
            Dim jsonStr As String = reader.ReadToEnd()
            Response.Clear()
            Response.ContentType = "application/json; charset=utf-8"
            Response.Write(jsonStr)
            Response.End()
    
        End Sub
    
    End Class


    José Antonio Gómez Linarez Técnico Superior en Informática

    sábado, 11 de julio de 2020 22:21

Respuestas

  • Saludos Andres y Leandro. Este fue el código que a la final cumplió lo que necesitaba puede ser que no sea muy elegante pero me es funcional, todo esto va a funcionar detrás de una autenticación validada por token. Cualquier sugerencia o critica es bien recibida.

    // GET api/<QueryController>/1
    [HttpGet("{cia}")]
    public ActionResult Get(int Cia)
    {
        HttpRequest xRequest = this.Request;
        QueryString xQueryString = xRequest.QueryString;
        int Query_broker = 0;
        string Query_url = "";
        string Query_json = "";
    
        if (xQueryString.Value.Length != 0)
        {
            var ListVar = xQueryString.Value.Substring(1).Split("&");
            Dictionary<string, string> DictVar = new Dictionary<string, string>();
            foreach (var item in ListVar)
            {
                DictVar.Add(item.Split("=")[0], item.Split("=")[1]);
            };
    
            JSONReadWrite readWrite = new JSONReadWrite();
            IEnumerable<CiasModel> File_Cias = JsonConvert.DeserializeObject<IEnumerable<CiasModel>>(readWrite.Read("Cias.json", "DomoJson"));
    
            CiasModel DatosCia = File_Cias.FirstOrDefault(x => x.Cia == Cia);
            Query_broker = DatosCia.BrokerInformation;
                    
            IEnumerable<BrokerModel> File_Brokers = JsonConvert.DeserializeObject<IEnumerable<BrokerModel>>(readWrite.Read("Brokers.json", "DomoJson"));
            ErrorBroker:
            BrokerModel DatosBroker = File_Brokers.FirstOrDefault(x => x.ID == Query_broker);
    
            if (DatosBroker != null)
            {
                Query_url = "http://" + DatosBroker.ServerIP;
                if (DatosBroker.ServerPort != "")
                {
                    Query_url += ":" + DatosBroker.ServerPort;
                }
                Query_url += "/scripts/cgiip.exe/WService=" + DatosBroker.Broker + "/";
    
                var TestBroker = Query_url + "webutil/ping.p";
                var ResultTest = new WebClient().DownloadString(TestBroker);
                if (!ResultTest.Contains("WebSpeed Transaction Server successfully accessed."))
                {
                    if(Query_broker != DatosCia.BrokerBackup)
                    {
                        Query_broker = DatosCia.BrokerBackup;
                        goto ErrorBroker;
                    }
                    else
                    {
                        return Ok(ResultTest);
                    }
                }
                Query_url += DictVar["program"] + ".p?cia=" + Cia;
    
                foreach (var item in DictVar)
                {
                    if (item.Key != "program")
                    {
                        Query_url += "&" + item.Key + "=" + item.Value;
                    }
                }
                Query_json = new WebClient().DownloadString(Query_url);
    
                return Ok(Query_json);
            }                
        }
        return Ok();
    }



    José Antonio Gómez Linarez Técnico Superior en Informática

    martes, 14 de julio de 2020 19:11

Todas las respuestas

  • hola

    >>el código se encuentra en VB.net y quiero llevarlo a C pero para Web Api.

    Pero cual es el codigo que intentaste implementar en la web api con c# ? mas que nada para entender cuanto conoces sobre las webapi

    por ejemplo sobre que verbo http vas a trabajar? ser un GET, POST, etc

    los valores que veo alli los tomas del querystring, pero vas a querer pasar estos por parametros de la url o como piensas enviarlos

    cuando armas una webapi en net core 3.1 ya no usas el WebRequest, debes cambiarlo a HttpClient

    Consuming a web API using a typed HttpClient — .NET Core

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    lunes, 13 de julio de 2020 1:01
  • Buen día Leandro, gracias por tu respuesta. Disculpa sino me explique bien, te presento mi escenario. En la empresa en donde trabajo utilizan Progress de OpenEdge en su versión 10.2B, y cuenta con un servicio web llamado WebSpeed, en donde se crean programas tipo API por GET, dichos programas realizan las consultas a la base de datos y me retorman XML o JSON dependiendo del desarrollo de los programas en WebSpeed. La cuestión es mas que todo por seguridad, estos servicios están disponibles en la Intranet de la empresa. Y se esta apuntando a aplicaciones que estén disponibles en Internet y quiero proteger las consultas detrás de una Web API segura, pero quiero crear una API en C# que sea un puente al WebSpeed. Y así pueda yo armar mi consulta con los datos proporcionados, ejecutarla de forma segura en mi servidor a la Intranet y devolver los datos al cliente.

    En el código de VB.NET, que agregue en el Post inicial recibo 2 valores claves que son la url del servicio WebSpeed a consultar y el programa. Y posteriormente los parámetros a incluir para pasar la consulta GET al WebSpeed, tomo ese resultado y lo devuelvo tal cual.

    De todos modos estoy abierto a cualquier otra sugerencia. Desde mi perspectiva lo veo como una solución como he explicado, trate de conectarme por ODBC a la base de datos de Progress OpenEdge y aun no lo he logrado, pero así seria mas engorroso porque tendría que diseñar nuevamente todas las consultas ya creadas en WebSpeed.

    En verdad perdona sino fui muy claro, y en verdad espero me ayudes, la Web Api Segura por Token ya la tengo desarrollada y funciona bien, solo me falta agregar esta sección para poder implementarla en los sistemas que se están desarrollando. De todos modos estoy leyendo el articulo que me enviaste.

    Gracias.

    De


    José Antonio Gómez Linarez Técnico Superior en Informática

    lunes, 13 de julio de 2020 12:34
  • Hola José Antonio Gómez Linarez, 

      

    Gracias por levantar tu consulta en los foros de MSDN. Con respecto a la misma, te comento que para que la comunidad de foros te pueda asesorar mejor, es necesario que formules una pregunta específica y clara.  Te dejo esta documentación oficial que te puede dar una guia de como hacer una web api en c# 

    string json = File.ReadAllText(Server.MapPath("~/files/myfile.json"));

     Andres Aguilar

     ____________________________ 

      

    Por favor recuerde "Marcar como respuesta" las respuestas que hayan resuelto su problema, es una forma común de reconocer a aquellos que han ayudado, y hace que sea más fácil para los otros visitantes encontrar la solución más tarde.  

    Microsoft ofrece este servicio de forma gratuita, con la finalidad de ayudar a los usuarios y la ampliación de la base de datos de conocimientos relacionados con los productos y tecnologías de Microsoft.   

    Este contenido es proporcionado "tal cual" y no implica ninguna responsabilidad de parte de Microsoft. 

    lunes, 13 de julio de 2020 17:01
  • Gracias Andrés, por los artículos. Logre el siguiente código:

    // GET: api/<QueryController>
     [HttpGet]
     public IEnumerable<QueryResult> Get()
     {
            HttpContext xContext = HttpContext;
            HttpRequest xRequest = xContext.Request;
            QueryString xQueryString = xRequest.QueryString;
            string[] ListVar;
            Dictionary<string, string> DictVar = new Dictionary<string, string>();
            List<QueryResult> xQueryResult = new List<QueryResult>();
            if (xQueryString.Value.Length != 0)
            {
                ListVar = xQueryString.Value.Substring(1).Split("&");
                foreach (var item in ListVar)
                {
                    DictVar.Add(item.Split("=")[0], item.Split("=")[1]);
                };
                var json = new WebClient().DownloadString("https://localhost:44326/weatherforecast");
                xQueryResult.Add(new QueryResult
                {
                    Cia = Int32.Parse(DictVar["cia"]),
                    Programa = DictVar["programa"],
                    Json = json
                });
            } 
    
            return xQueryResult;
    }
    
     public class QueryResult
     {
        [Required]
        public int Cia { get; set; }
        [Required]
        public string Programa { get; set; }
        public object Json { get; set; }
     }
    Pero obtengo este Json: 

    [
       {
          "cia": 1,
          "programa": "datospedido",
          "json": "[{\"date\":\"2020-07-14T19:38:30.5788281-04:00\",\"temperatureC\":22,\"temperatureF\":71,\"summary\":\"Warm\"},{\"date\":\"2020-07-15T19:38:30.5788388-04:00\",\"temperatureC\":49,\"temperatureF\":120,\"summary\":\"Bracing\"},{\"date\":\"2020-07-16T19:38:30.5788393-04:00\",\"temperatureC\":35,\"temperatureF\":94,\"summary\":\"Warm\"},{\"date\":\"2020-07-17T19:38:30.5788396-04:00\",\"temperatureC\":-16,\"temperatureF\":4,\"summary\":\"Cool\"},{\"date\":\"2020-07-18T19:38:30.5788398-04:00\",\"temperatureC\":-9,\"temperatureF\":16,\"summary\":\"Chilly\"}]"
       }
    ]

    Y necesito que en el campo "json" me devuelva el Json formateado como tal, ya que esta consulta es variable, con los valores de "cia", "programa" y las variables "ListVar", "DictVar" se va a construir distintas url's que se van a ejecutar dentro de esta api y el resultado se va a incluir en el campo "json". Claro aun no he programado el procedimiento para crear la url dinámica. Por lo momentos la tengo estática para las pruebas.


    José Antonio Gómez Linarez Técnico Superior en Informática


    lunes, 13 de julio de 2020 23:53
  • hola

    >>En el código de VB.NET, que agregue en el Post inicial recibo 2 valores claves que son la url del servicio WebSpeed a consultar y el programa

    No crees que si el programa que te esta invocando conoce la url a los servicio de WebSpeed no estarias vulnerando esta aplicacion poniendo un punto de posible hackeo ?

    Poner una url como parametro de una aplicacion interna no deberia ser posible, la url la configuras fija en la webapi que estes creando y armas la url con esta, pero no se pasa por ningun parametro

    deberias crear acciones individuales para cada operacion, no vayas por algo generico pasando url que conoce el cliente, eso no es encapsular ni aplicar ninguna seguridad

    >>trate de conectarme por ODBC a la base de datos de Progress OpenEdge y aun no lo he logrado

    habria que revisarlo con mas detalle

     OpenLink.Data.Virtuoso

    pero creo que si existe un proveedor de ado.net para esa db

     Provider for Progress

    aunque la verdad no se porque usan esa base de datos, no tiene ningun soporte de conectores

    Seguramente no puedas pero si fuera yo estaria pensando en cambiar la base de datos, porque por lo que mencionas esta es horrible

    todo bien con WebSpeed quizas e facilite algunas cosas, pero sino hay compatibilidad de integracion no sirve

    >>Y así pueda yo armar mi consulta con los datos proporcionados, ejecutarla de forma segura en mi servidor a la Intranet y devolver los datos al cliente

    ok pero estabas preguntando como invocar las webapi desde el cliente y para eso aplica lo que ya comente, usas el HttpClient

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    martes, 14 de julio de 2020 0:17
  • Gracias Leandro, 

    >> Poner una url como parametro de una aplicacion interna no deberia ser posible, la url la configuras fija en la webapi que estes creando y armas la url con esta, pero no se pasa por ningun parametro

    la url a consultar dentro de la api no pienso pasarla por parámetros, tengo archivos de configuración en json del lado del servidor que contienen esas rutas ya establecidas, los parámetros son necesarios para crear la consulta por ejemplo el parámetro "cia" tiene asociado en la configuración del servidor una url y el parámetro programa esta asociado al programa a ejecutar en WebSpeed, y por supuesto se incluirían más parámetros que acompañarían la consulta dentro de la api. El cliente nunca vera la url en WebSpeed, porque todo eso ocurriría en el servidor.

    >> aunque la verdad no se porque usan esa base de datos, no tiene ningun soporte de conectores

    En la empresa donde laboro utilizan esa base de datos desde hace años y tienen casi todas sus aplicaciones GUI desarrolladas en ella. Y por los momentos no se puede migrar a otra porque el 98% de sus sistemas están en ese lenguaje y base de datos. Y su gran mayoría fueron desarrollados en la empresa por programadores en nomina.

    Voy a documentarme con los enlaces que me proporcionaste. De todos modos no es mi primera opción el conectarme directamente a la base de datos desde Visual Studio, porque tendria que migrar todos los programas en Progress a C#. O bueno así lo veo. De todos modos arriba publique una respuesta con una idea más clara de lo que quiero lograr.


    José Antonio Gómez Linarez Técnico Superior en Informática

    martes, 14 de julio de 2020 14:02
  • Hola José Antonio Gómez Linarez, 

      

    Si para manipular el JSON te dejo este ejemplo con este puedes manipular el string y crear un url.

    Nota importante es que tienes que descargar la libreria newtonsoft

    Working With JSON String In C#

    Gracias por usar los foros de MSDN.   

     

     Andres Aguilar

     ____________________________ 


    martes, 14 de julio de 2020 16:56
  • Saludos Andres y Leandro. Este fue el código que a la final cumplió lo que necesitaba puede ser que no sea muy elegante pero me es funcional, todo esto va a funcionar detrás de una autenticación validada por token. Cualquier sugerencia o critica es bien recibida.

    // GET api/<QueryController>/1
    [HttpGet("{cia}")]
    public ActionResult Get(int Cia)
    {
        HttpRequest xRequest = this.Request;
        QueryString xQueryString = xRequest.QueryString;
        int Query_broker = 0;
        string Query_url = "";
        string Query_json = "";
    
        if (xQueryString.Value.Length != 0)
        {
            var ListVar = xQueryString.Value.Substring(1).Split("&");
            Dictionary<string, string> DictVar = new Dictionary<string, string>();
            foreach (var item in ListVar)
            {
                DictVar.Add(item.Split("=")[0], item.Split("=")[1]);
            };
    
            JSONReadWrite readWrite = new JSONReadWrite();
            IEnumerable<CiasModel> File_Cias = JsonConvert.DeserializeObject<IEnumerable<CiasModel>>(readWrite.Read("Cias.json", "DomoJson"));
    
            CiasModel DatosCia = File_Cias.FirstOrDefault(x => x.Cia == Cia);
            Query_broker = DatosCia.BrokerInformation;
                    
            IEnumerable<BrokerModel> File_Brokers = JsonConvert.DeserializeObject<IEnumerable<BrokerModel>>(readWrite.Read("Brokers.json", "DomoJson"));
            ErrorBroker:
            BrokerModel DatosBroker = File_Brokers.FirstOrDefault(x => x.ID == Query_broker);
    
            if (DatosBroker != null)
            {
                Query_url = "http://" + DatosBroker.ServerIP;
                if (DatosBroker.ServerPort != "")
                {
                    Query_url += ":" + DatosBroker.ServerPort;
                }
                Query_url += "/scripts/cgiip.exe/WService=" + DatosBroker.Broker + "/";
    
                var TestBroker = Query_url + "webutil/ping.p";
                var ResultTest = new WebClient().DownloadString(TestBroker);
                if (!ResultTest.Contains("WebSpeed Transaction Server successfully accessed."))
                {
                    if(Query_broker != DatosCia.BrokerBackup)
                    {
                        Query_broker = DatosCia.BrokerBackup;
                        goto ErrorBroker;
                    }
                    else
                    {
                        return Ok(ResultTest);
                    }
                }
                Query_url += DictVar["program"] + ".p?cia=" + Cia;
    
                foreach (var item in DictVar)
                {
                    if (item.Key != "program")
                    {
                        Query_url += "&" + item.Key + "=" + item.Value;
                    }
                }
                Query_json = new WebClient().DownloadString(Query_url);
    
                return Ok(Query_json);
            }                
        }
        return Ok();
    }



    José Antonio Gómez Linarez Técnico Superior en Informática

    martes, 14 de julio de 2020 19:11
  • Hola José Antonio Gómez Linarez

    Gracias por confirmar que se ha encontrado una solución a la consulta realizada. Debido a ello, este hilo será cerrado. 

    Si es necesario, por favor abra un nuevo hilo. 

    Cualquier duda referente a productos Microsoft, puedes consultarnos. Es un gusto informarte. 

    Gracias por usar los foros de MSDN. 

     

     Andres Aguilar

    ____________________________ 

      

    Por favor recuerde "Marcar como respuesta" las respuestas que hayan resuelto su problema, es una forma común de reconocer a aquellos que han ayudado, y hace que sea más fácil para los otros visitantes encontrar la solución más tarde.  

    Microsoft ofrece este servicio de forma gratuita, con la finalidad de ayudar a los usuarios y la ampliación de la base de datos de conocimientos relacionados con los productos y tecnologías de Microsoft.   

    Este contenido es proporcionado "tal cual" y no implica ninguna responsabilidad de parte de Microsoft. 

    martes, 14 de julio de 2020 19:55