WebService con VFP 6 Devuelva JSON

537 views
Skip to first unread message

Juan Carlos M

unread,
Aug 23, 2022, 1:48:02 PM8/23/22
to Comunidad de Visual Foxpro en Español
Saludos Compañeros

De antemano agradezco su apoyo y colaboración, alguno de ustedes ha trabajado con 
VFP 6 para realizar un WebService que devuelva un JSON  ?.

He leido Temas en este Grupo y he visto que es posible realizarlo en VFP 9, sin embargo por el momento nos es imposible migrar de VFP6  a VFP9.

Si contaran con algún ejemplo, código o referencia es Bienvenido.

Mil Gracias !!!.

Dsan

unread,
Aug 23, 2022, 3:09:09 PM8/23/22
to publice...@googlegroups.com
Hola, si buscas en el grupo hay ejemplos como consumir un servicio web con vfp Y MsXML en el grupo, pero me llama la atención, tu pregunta.
VFP 6 para realizar un WebService que devuelva un JSON  ?. con vfp no podras hacerlo o realizarlo desde cero. solo consumirlo
El ws lo podes hacer en otro lenguaje y mandarlo a llamar por desde vfp, pero quien te va enviar los datos JSon, es tu servicio web, aca hay 4 clases que trabajan con JSon igual creo que linkeadas en el grupo...
nfJson de Marcos Plaza
jsonfox de Irwin Rodriguez

Con eso puede trabajar con json, algunas te permiten pasar json to cursor o cursor to json para regresarlo en un POST.





--
Blog de la Comunidad Visual FoxPro en Español: http://comunidadvfp.blogspot.com
---
Has recibido este mensaje porque estás suscrito al grupo "Comunidad de Visual Foxpro en Español" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a publicesvfoxp...@googlegroups.com.
Para ver esta conversación en el sitio web, visita https://groups.google.com/d/msgid/publicesvfoxpro/35428f34-3bd9-41f4-9e59-046cbb0d6ef1n%40googlegroups.com.

Hendell Mora

unread,
Aug 23, 2022, 3:46:18 PM8/23/22
to publice...@googlegroups.com

Marco Plaza

unread,
Aug 23, 2022, 7:31:08 PM8/23/22
to Comunidad de Visual Foxpro en Español
Hola Juan Carlos.. casualmente acabo de compartir en foxite un ejemplo de como hacer un 
micro servicio con winsock  pero en vfp9!

Para adaptarlo usa otra librería compatible con vfp6 para generar el json ( no sé hay alguna ) o creando tu mismo el json, 
y usa el winsock desde una clase visual.

Aquí está el codigo fuente:

*************************************************
* Marco Plaza, 2022
* @nfoxdev
* winsock demo servidor simple 
* sin manejo de errores etc..
*************************************************

set path to "\vfpx\nfjson\nfjson" additive
clear
public ows,dmse

ows  = createobject('MSWINSOCK.WINSOCK.1')
with ows
    .protocol    = 0
    .localport    = 2224
    .listen()
endwith

dmse = newobject("DMSEVENTS")

eventhandler(ows,m.dmse)

set procedure to (sys(16))
on key label SHIFT+F9 do stop


text to welcome noshow

Your first VFP rest api server is running!

use SHIFT+F9 para detener servicio

click Ok para continuar el test

endtext


messagebox(m.welcome,0,'nFoxdev')

with createobject('hyperlink')

messagebox('click ok para buscar pavarotti...')
.navigateto('http://localhost:2224/pavarotti')

messagebox('click ok para buscar simpson...')
.navigateto('http://localhost:2224/simpson')


messagebox('click ok para ver todos los clientes.')
.navigateto('http://localhost:2224')

endwith



*---------------------------------
function STOP
*---------------------------------
OWS.CLOSE()
eventhandler(ows,M.dmse,.T.)
release OWS,DMSE
messagebox('SERVER STOPPED',0)
on key label SHIFT+F9



*************************************************
define class dmsevents as session olepublic
*************************************************

    implements dmswinsockcontrolevents in "c:\windows\syswow64\mswinsck.ocx" && case sensitive!

*----------------------------------------------------------------------------------------
    procedure dmswinsockcontrolevents_dataarrival(bytestotal as number) as void
*----------------------------------------------------------------------------------------
    local lcdata,csearch4
   
    lcdata  = ''

    with ows

        .getdata(@lcdata)
       
        ? "*----------------------------------------------------------------------------------------"
        ? lcdata
        ? "*----------------------------------------------------------------------------------------"

        cSearch4 = lower(alltrim(getwordnum(m.lcdata,2),1,'/',' '))

        lcresponse = getCustomers( m.csearch4 )
       
        .senddata( m.lcresponse )

    endwith

*----------------------------------------------------------------------------------------
    procedure dmswinsockcontrolevents_connectionrequest(requestid as number) as void
*----------------------------------------------------------------------------------------
    ows.close()
    ows.accept(m.requestid)

*----------------------------------------------------------------------------------------
    procedure dmswinsockcontrolevents_sendcomplete() as void
*----------------------------------------------------------------------------------------
        ows.close()
        ows.listen()

*----------------------------------------------------------------------------------------
    procedure dmswinsockcontrolevents_error(number as integer, description as string, scode as number, source as string, helpfile as string, helpcontext as number, canceldisplay as logical) as void
    procedure dmswinsockcontrolevents_connect() as void
    procedure dmswinsockcontrolevents_close() as void
    procedure dmswinsockcontrolevents_sendprogress(bytessent as number, bytesremaining as number) as void;

*********************************************************
enddefine
*********************************************************

*---------------------------------------------
function getCustomers(cSearch)
*---------------------------------------------
local httpresponse,cJson


select * ;
from home()+'samples\northwind\customers' ;
where m.cSearch $ lower(contactName) or empty(m.cSearch);
into cursor response

* nfcursorToJson(returnArray,arrayofValues,includestruct,formattedOutput):
* play with nfJson options..

cJson = strconv(nfcursorToJson(.f.,.f.,.f.,.t.),9)

use
set textmerge delimiters to "{{","}}"

text TO HTTPRESPONSE textmerge noshow
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: {{len(m.cJson)}}

{{m.cJson}}
endtext

return m.httpresponse


Victor Espina

unread,
Aug 24, 2022, 8:27:27 AM8/24/22
to Comunidad de Visual Foxpro en Español
Como que no?  Yo tengo VARIOS webservices en produccion hechos con VFP (usando ActiveVFP + IIS como intermediarios).  De hecho, Marco Plaza acaba de publicar un ejemplo en Foxite sobre como crear un microservice en VFP usando solo WinSocket.

Victor Espina

Marco Plaza

unread,
Aug 24, 2022, 10:03:36 AM8/24/22
to Comunidad de Visual Foxpro en Español

Hola Victor.. ciertamente.. hay opciones.. desde active vfp, web connection, hasta el mismo Foxisapi 
que siempre ha estado disponible  ( "http applications using vfp" de strahl es muy buena referencia )
 pero la configuración  de IIS  + COM no es muy rápida, y trabajar sobre el ecosistema de MS 
hay que estar pendiente siempre de si algo cambia.

Acerca del código del servicio -que está aquí arriba también - por favor parchar la línea de la respuesta:

        .senddata( m.lcresponse )

debe ser:

        .senddata( m.lcresponse + chr(13)+chr(10) )

Saludos.

Juan Carlos M

unread,
Aug 24, 2022, 1:38:57 PM8/24/22
to Comunidad de Visual Foxpro en Español
Excelentes Aportaciones 

Mil Gracias Voy aprobar los códigos.


HernanCano

unread,
Aug 24, 2022, 2:29:50 PM8/24/22
to Comunidad de Visual Foxpro en Español
¿Cómo lo pruebo?
borrable1.png

HernanCano

unread,
Aug 24, 2022, 3:56:33 PM8/24/22
to Comunidad de Visual Foxpro en Español
borrable1.png

borrable2.png

borrable3.png

HernanCano

unread,
Aug 24, 2022, 4:11:10 PM8/24/22
to Comunidad de Visual Foxpro en Español
Mientras escribía el anterior mensaje terminó, pero salió error que no encontraba la librería njJson.....

borrable4.png

borrable5.png

borrable6.png
borrable7.png

Victor Espina

unread,
Aug 24, 2022, 4:31:39 PM8/24/22
to Comunidad de Visual Foxpro en Español
No, si me encanta la idea de lo servidores standalone... de hecho, este año me toco hacer uno para un proyecto de un cliente, usando ChilKat.  La pregunta clave aqui es: como haces en un servidor web VFP para manejar multiples conexiones simultáneas?  Porque en el caso de ActriveVFP, se usa IIS justamente para lograr eso.

Victor Espina

HernanCano

unread,
Aug 24, 2022, 5:58:00 PM8/24/22
to Comunidad de Visual Foxpro en Español
Listo.
Ya funciona.

Luego de arreglar la ruta que mostré para el OCX, y poner el path del nfJSON de mi computador, ejecuta normal.

Desafortunadamente tuve que habilitar el Apache; yo uso WampServer v3.2.3 .

Chévere.
Ahora sí: a probar !!!!!!!!!!

Gracias por compartir.

PD: por favor mejora la documentación o la explicación de la forma de uso: por ninguna parte dice que hay que tener activado el Apache. Y me parece que la idea era ésa... pero bueno.... procedamos.....

Gerardo Cagnola

unread,
Aug 24, 2022, 6:15:04 PM8/24/22
to Comunidad de Visual Foxpro en Español
pero el wamp es apache...

--
Blog de la Comunidad Visual FoxPro en Español: http://comunidadvfp.blogspot.com
---
Has recibido este mensaje porque estás suscrito al grupo "Comunidad de Visual Foxpro en Español" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a publicesvfoxp...@googlegroups.com.

HernanCano

unread,
Aug 24, 2022, 6:20:56 PM8/24/22
to Comunidad de Visual Foxpro en Español
Eso es lo q dije.
Por eso es que lo compartido por Marco funciona, de lo contrario no.

Obligatoriamente hay que tener Apache activado-subido-funcionando.

Dsan

unread,
Aug 24, 2022, 7:08:26 PM8/24/22
to publice...@googlegroups.com

Hola HernanCano, buen tip voy a probar...
El OCX Winsock usa el motor Apache si es así, excelente prefiero este que IIS, en particular.

Saludos

DS

--
Blog de la Comunidad Visual FoxPro en Español: http://comunidadvfp.blogspot.com
---
Has recibido este mensaje porque estás suscrito al grupo "Comunidad de Visual Foxpro en Español" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a publicesvfoxp...@googlegroups.com.

Dsan

unread,
Aug 24, 2022, 7:11:21 PM8/24/22
to publice...@googlegroups.com

Muy claro Maestro Victor... cuando dije y lo sostengo casi imposible es hacerlo a puro codigo...
necesitamos de otras hierbas aromáticas como winsock el cual tengo entendido lo descontinuaron por bug de seguridad...
pero se resuelve y como decimos en mi país, el que no tiene a su mamá, con su abuelita se conforma....sacan de clavo en apuro mientras se buscan alternativas más fuertes...

Saludos

DSAN

HernanCano

unread,
Aug 24, 2022, 8:35:44 PM8/24/22
to Comunidad de Visual Foxpro en Español
Gracias, colega.

Me queda difícil certificar/confirmar/aseverar esta frase: "El Winsock.OCX usa el motor Apache".

Pero sí me queda claro que lo compartido por Marco funciona sólo si Apache está levantado (haciendo el ajuste de la ruta/ubicación del Winsock.OCX). No he probado si funciona con "IIS levantado", pero si sólo funcionara con IIS, ya sólo por éso lo descartaría lo compartido.


El miércoles, 24 de agosto de 2022 a la(s) 18:08:26 UTC-5, DSánchez escribió:

Hola HernanCano, buen tip voy a probar...
El OCX Winsock usa el motor Apache si es así, excelente prefiero este que IIS, en particular.

Saludos

DS

Marco Plaza

unread,
Aug 24, 2022, 8:44:32 PM8/24/22
to Comunidad de Visual Foxpro en Español

Hola.. winsock es un activex de comunicaciones de Microsoft que vfp instala como parte del producto.

No necesitas tener ningún servidor instalado.. Apache ni IIS tienen nada que ver.
Sólo el control registrado en tu pc. - y ciertamente omití decir que necesitabas nfJson!

Victor en relación a la escalabilidad, si necesitas https y mayor capacidad de respuesta,
la forma mas simple es levantando tantas copias de tu servicio como necesites ya sea en el mismo 
servidor ( si su cpu y ram lo soportan ) o en otros servidores en un rango de puertos ej: 2204-2205-2206 y
 luego los instalas detrás de un load balancer como nginx que los puede invocar en base a la configuración que escojas,
por ejemplo round robin. Tambien puedes conectarlos detrás de nodeJs por ejemplo y empezar poco a poco a tocar otros 
entornos, paso a paso.

Esto puede servir para cosas puntuales ( ejemplo servir listas de precios.. cotizaciones.. lectores de precio, devolver reportes etc ) 
Pero para desarrollo web, se necesita un framework que maneje seguridad, tolerancia a fallos, conexión a base de datos , páginas activas etc.

Para eso pronto voy a liberar una suite de herramientas ( nfTools )  y un servidor de aplicaciones full MVC ( nFox ) que 
traerá a VFP un ambiente de desarrollo bastante parecido a ASP.MVC y permitirá escribir componentes web al estilo vue.Js,
programación de servicios con cola de eventos, depuración de controladores en el cliente y mucho mas.

nFox permite servir ( en pruebas de estrés ) hasta 450-500 transacciones por segundo en mi FX-8120.

Saludos.













Dsan

unread,
Aug 24, 2022, 9:59:50 PM8/24/22
to publice...@googlegroups.com
Muy Claro su explicación, Maestro.

Ahora que lo mencionas el apache seguro abre el puerto que usa winsock y de ahí si lo pudo levantar Hernancano, supongo.

Saludos

DS



HernanCano

unread,
Aug 24, 2022, 10:01:02 PM8/24/22
to Comunidad de Visual Foxpro en Español
Huy, Marco....

Parece que tienes razón.
La primera vez me funcionó sólo después de habilitar Apache, pero luego de tu mensaje lo quité y también funcionó tus comandos compartidos.

Mirando lo más interno.............

Marco Plaza

unread,
Aug 25, 2022, 1:29:08 AM8/25/22
to Comunidad de Visual Foxpro en Español
Aquí dejo una última revisión de este servicio, que solventa el cierre de conexiones inactivas -algo que ocurre cuando consultamos el servicio desde un navegador, ya que estos después de terminar la consulta vuelven a abrir otra conexión para 'tenerla disponible', aunque no hacen nada con ella.
Otra pequeña mejora es devolver un mensaje indicando "no encontrado" para las búsquedas que no den resultado.

Ya con esto y meterse un poco con HTTP se pueden implementar muchas cosas interesantes.

Saludos.



*************************************************
* Marco Plaza, 2022
* @nfoxdev
* winsock simple server demo
* no error management etc..

*************************************************

set path to "\vfpx\nfjson\nfjson" additive
clear
public ows,dmse

ows  = createobject('MSWINSOCK.WINSOCK.1')
with ows
    .protocol    = 0
    .localport    = 2224
    .listen()
endwith

dmse = newobject("DMSEVENTS")

eventhandler(ows,m.dmse)

set procedure to (sys(16))
on key label shift+f9 do stop



text to welcome noshow

Your first VFP rest api server is running!

use SHIFT+F9 to stop

click Ok to continue with test


ENDTEXT



messagebox(m.welcome,0,'nFoxdev')

with createobject('hyperlink')

    messagebox('click ok to search for "simpson" ')

    .navigateto('http://localhost:2224/simpson')

endwith



*---------------------------------
function stop
*---------------------------------
ows.close()
eventhandler(ows,M.dmse,.t.)
release ows,dmse
messagebox('SERVER STOPPED',0)
on key label shift+f9



*************************************************
define class dmsevents as custom olepublic
*************************************************
add object closeIdle as timer with interval = 2000 , enabled = .f.


implements dmswinsockcontrolevents in "c:\windows\syswow64\mswinsck.ocx"


*----------------------------------
function closeIdle.timer
*----------------------------------
    this.enabled = .f.
    ows.close()
    ows.listen()
    ? 'idle connection closed!'


*----------------------------------------------------------------------------------------
    procedure dmswinsockcontrolevents_dataarrival(bytestotal as number) as void
*----------------------------------------------------------------------------------------

    this.closeIdle.enabled = .f.


    local lcdata,csearch4

    lcdata  = ''

    with ows

        .getdata(@lcdata)

        ? "*----------------------------------------------------------------------------------------"
        ? lcdata
        ? "*----------------------------------------------------------------------------------------"

        csearch4 = lower(alltrim(getwordnum(m.lcdata,2),1,'/',' '))

        lcresponse = getcustomers( m.csearch4 )


        .senddata( m.lcresponse + chr(13)+chr(10) )

    endwith

*----------------------------------------------------------------------------------------
    procedure dmswinsockcontrolevents_connectionrequest(requestid as number) as void
*----------------------------------------------------------------------------------------
    ows.close()
    ows.accept(m.requestid)
    this.closeIdle.enabled = .t.


*----------------------------------------------------------------------------------------
    procedure dmswinsockcontrolevents_sendcomplete() as void
*----------------------------------------------------------------------------------------
    ows.close()
    ows.listen()

*----------------------------------------------------------------------------------------
    procedure dmswinsockcontrolevents_error(number as integer, description as string, scode as number, source as string, helpfile as string, helpcontext as number, canceldisplay as logical) as void
    procedure dmswinsockcontrolevents_connect() as void
    procedure dmswinsockcontrolevents_close() as void
    procedure dmswinsockcontrolevents_sendprogress(bytessent as number, bytesremaining as number) as void;

*********************************************************
enddefine
*********************************************************

*---------------------------------------------
function getcustomers(csearch)
*---------------------------------------------
local httpresponse,cjson



select * ;
    from home()+'samples\northwind\customers' ;
    where m.csearch $ lower(contactname) or empty(m.csearch);

    into cursor response

* nfcursorToJson(returnArray,arrayofValues,includestruct,formattedOutput):
* play with nfJson options..

cjson = strconv(nfcursortojson(.t.,.f.,.f.,.t.),9)


use

set textmerge delimiters to "{{","}}"

if _tally > 0


    text TO HTTPRESPONSE textmerge noshow
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: {{len(m.cJson)}}

{{m.cJson}}
    ENDTEXT

else

cres = "No records found for "+m.cSearch


    text TO HTTPRESPONSE textmerge noshow
HTTP/1.1 200 Ok
Content-Type: text/html
Content-Length: {{len(m.cRes)}}

{{m.cres}}
    ENDTEXT

endif

set textmerge delimiters to

return m.httpresponse

*----------------------------------------------------------------------



Eric Zbrun

unread,
Aug 25, 2022, 11:45:53 AM8/25/22
to Comunidad de Visual Foxpro en Español
Hola Juan!!
Hece unos meses arme una programa para hacer lo que estás pidiendo.  Te paso los links el tema que todo trabaja con VFP9 y lo que necesitas que trabaje con VFP6 podrias usar la parte de C# que es solo un EXE que pasa de JSON a XML y luego con las rutinas de West Wind XML Converter 4.50  del Maestro Rick Strahl podes convertir de XML a DBF en VFP6.
Ahora para ejecutarla consulta podes usar la CURL.EXE > TXT  (CURL https://tuapi.... > file.json) (CURL se supone que esta enlas ultimas versiones de 10 instalado sino se que se puede bajar).


+sitio
+fuentes

West Wind XML Converter 4.50


Ejemplo seria


ejecutar ConvertJson2XML.exe

luego tomar Tmpfile.xml

y usar la rutinas de West Wind XML Converter 4.50 claro que tenes que armar el DBF antes por lo que vi a primera vista.

oXML = CREATE("wwXML")
oXML.XMLToCursor( 'Tmpfile.xml ","miCursor")
 

Saludos.
Eric!
Reply all
Reply to author
Forward
0 new messages