Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Internet (https://www.clubdelphi.com/foros/forumdisplay.php?f=3)
-   -   Ayuda con Webservice (https://www.clubdelphi.com/foros/showthread.php?t=91399)

gersojn 28-01-2017 00:41:07

Ayuda con Webservice
 
Hola foro,
Espero estén de lo mejor. Les comento que estoy iniciando con webservice en delphi y estoy fatal.
Detalles: El webservice utiliza soap con wsdl y esta ejecutandose en localhost. Windows 10. Delphi 10.1.

Intento llamar una función, que se genero de la importación, y que esta estructurada de la siguiente forma:
Código Delphi [-]
function  login(const user_auth: user_auth; const application_name: string; const name_value_list: name_value_list): entry_value; stdcall;

Mediante una acción en un boton, intento cargar el resultado en un memo

Código Delphi [-]
procedure TForm1.Button2Click(Sender: TObject);
begin
    Memo1.Text := login(user_auth,'','admin','clave');
end;

Sin embargo, me indica que el identificador login no esta declarado.
[dcc32 Error] Unit1.pas(49): E2003 Undeclared identifier: 'login'.
El unit generado de la importacion, lo incorporo en la clausula USES.

Intento hacer algo similar a esto:

Código:

$client=new SoapClient("http://localhost/sugarCRM/service/v4/soap.php?wsdl");
$response=$client->__soapCall("login",
        array("user_auth"=>
        array(
                'user_name'=>'admin',
                'password'=>md5('clave'),
                'version'=>"0.1",),
        "application_name"=>''));
$session_id=$response->id;
echo "Session ID".$session_id;

Esto lo realice en php y todo funciona sin problema.
Sin embargo en Delphi, no me ha funcionado.
Alguien me puede orientar, sobre que puedo estar haciendo mal.
Cualquier ayuda es bienvenida.
Saludos.

AgustinOrtu 28-01-2017 03:16:55

Copia el código completo de las dos Unit

gersojn 28-01-2017 03:28:22

Hola AgustinOrtu,
//al momento de enviar el unit recibo este mensaje en el foro
El texto que has ingresado es muy largo (53228 caracteres). Por favor acórtalo a 30000 caracteres de largo.
Lo adjuntare en dos mensajes.
Gracias, ahora agrego el código.

Hace un momento logre que compile sin errores, pero al generar la acción en el boton, la aplicación genera un error de "Access Violation at Address" . No se como recuperar la información.

Unit principal (VCL)

Código Delphi [-]
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, DBAccess, Uni, UniProvider,
  SQLServerUniProvider, Vcl.StdCtrls, Vcl.Grids, Vcl.DBGrids, MemDS,Soap;

type
  TForm1 = class(TForm)
    Button2: TButton;
    Memo1: TMemo;
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  ws:sugarsoapPortType;

implementation


{$R *.dfm}



procedure TForm1.Button2Click(Sender: TObject);
  var
    autenticacion:user_auth;
    usuario:name_value_list;
    resultado:entry_value;
begin
    resultado := ws.login(autenticacion,'',usuario);
end;

end.

gersojn 28-01-2017 03:33:26

Este el código del unit generado, tras la importación:
Lo adjunto en un txt, ya que no permite incluirlo en un mensaje, porque sobre pasa la cantidad de caracteres.

lo adjunto en el siguiente enlace de pastebin, ya que no logre subirlo al foro
http://pastebin.com/gsMqgKwh

Toda ayuda es bienvenida.
Saludos.

AgustinOrtu 28-01-2017 04:10:08

El codigo que publicaste en el primer mensaje es distinto al ultimo:

Código Delphi [-]
procedure TForm1.Button2Click(Sender: TObject);
begin
    Memo1.Text := login(user_auth,'','admin','clave');
end;

Código Delphi [-]
procedure TForm1.Button2Click(Sender: TObject);
  var
    autenticacion:user_auth;
    usuario:name_value_list;
    resultado:entry_value;
begin
    resultado := ws.login(autenticacion,'',usuario);
end;

Por otra parte, el codigo que publicaste en el segundo mensaje compila y no se da el error que comentas

AgustinOrtu 28-01-2017 04:23:53

Otra cosa importante es que no estas inicializando los objetos que estas usando

sugarsoapPortType es una interface, es decir, para poder usarla, debes primero asignar una referencia a un objeto que imlpemente esa interface a la variable. De no hacerlo, la referencia contiene el valor nil. Cualquier metodo que quieras ejecutar sobre una interface que vale nil, produce un error en tiempo de ejecucion EAccessViolation

El wizard te genera automaticamente una funcion para crear esta interface, GetsugarsoapPortType

Para usar la interface deberias hacer algo como esto:

Código Delphi [-]
procedure blabla;
var
  ws: sugarsoapPortType;
begin
  ws := GetsugarsoapPortType;
  // ws ahora no vale nil y podes invocar sus metodos
end:

Esta misma "regla", se cumple para todos los tipos involucrados. Debes inicializarlos (crearlos, ya sea con un constructor, o con una funcion) y luego utilizarlos. Es cierto que existen los llamados "tipos primitivos" (Integer, string, record, etc) que si bien no es necesario resulta importante inicializarlos para darles un valor que tenga sentido:

Este codigo no da error, pero que valor tiene la variable I? No hay forma de saberlo ya que I va a tener el valor que estaba almacenado en la direccion de memoria que le fue asignado. Se dice en la jerga que el valor de I es "residuo"

Código Delphi [-]
procedure blabla;
var
  I: Integer;
begin
  ShowMessage(IntToStr(I));
end;

Hago enfasis en esto porque del mismo modo que invocas metodos sobre una interface sin antes inicializarla, y tambien le pasas parametros que no son inicializados

Por ejemplo, user_auth es una clase:

Código Delphi [-]
  user_auth = class(TRemotable)
  private
    Fuser_name: string;
    Fpassword: string;
  published
    property user_name: string  read Fuser_name write Fuser_name;
    property password:  string  read Fpassword write Fpassword;
  end;

Osea que debes inicializar una variable y luego tambien darle valores a sus propiedades internas (user_name y password, sino quedan como string vacios y quiza no tenga sentido, lo ideal seria darle valores concretos)

gersojn 28-01-2017 17:42:18

Hola,
Gracias por la ayuda.
Realice la siguiente modificacion sobre el procedimiento:
Código Delphi [-]
procedure TForm1.Button2Click(Sender: TObject);
  var
    autenticacion:user_auth;
    usuario:name_value_list;
    ws:sugarsoapPortType;
begin
    ws := GetsugarsoapPortType;
    autenticacion.user_name:='admin';
    autenticacion.password:='clave';
    ws.login(autenticacion,'',usuario);
end;

Al momento de invocar la función, obtengo el siguiente error: Conversion from class TForm1 to SOAP is not supported - SOAP classses must derive from TRemotable

No consigo comprender la forma correcta de crear una instancia , para utilizar la función de Login.
Toda ayuda, es bienvenida.
Saludos.

AgustinOrtu 28-01-2017 18:05:17

La verdad es que nunca use SOAP. Yo primero leería la documentación

Luego una guía de un hola mundo está bien para no ir tan a tientas, por ejemplo, esta. En la primer parte crea el servidor también en Delphi, eso te lo podes saltear e ir directo a la parte del cliente

iuqrul 31-01-2017 13:21:13

Usa la función que genera el importador
 
El importador genera una función que devuelve la interfaz a usar, por ejemplo en un importador tengo:

Código Delphi [-]
preventaPortType = interface(IInvokable)
  ['{3004DABE-FF4B-4C0C-BA43-953418C01030}']
    function  download(const xml: string): string; stdcall;
    function  upload(const xml: string): string; stdcall;
end;

function GetpreventaPortType(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil): preventaPortType;

Yo llamo a GetpreventaPortType, y guardo la interfaz del tipo preventaPortType (este es el nombre de mi caso) en una variable, y luego la uso para acceder a los dos métodos download y upload de dicha interfaz, cuando acabas la igualas a nil y se libera.

gersojn 02-03-2017 03:22:34

Gracias a todos
 
Hola, gracias por la ayuda.
Ya tengo un mes y esto no me funciona para nada.
He estado practicando algo sobre WS en Delphi, tanto creando clientes y servidores y todo va perfecto.
Pero, en cuanto a el ws antes mencionado siento muy complejo abordarlo desde Delphi.
Continué el desarrollo en Php.
Saludos.


La franja horaria es GMT +2. Ahora son las 15:40:06.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi