Страница 1 из 1

soap, передача массива =)

Добавлено: 19 дек 2006, 14:07
asterix20
вобщем вот...
нада, чтоб от клиента на сервер передавалось 2 массива и 1на строчка...
массивы составляются из 3х эдитов, того, что в них вводится, в каждом эдите - отдельный элемент массива...
wdsl importer дает вот :

ArrayOfParameters = class(TRemotable)
public
arrkeys: array of variant;
arrvalues: array of variant;
private
published
end;


ReportGeneratorPortType = interface(IInvokable)
['{51BA4853-4A59-DAC7-7303-682FC35751C6}']
function getReportPdf(const report: String; const keys: ArrayOfParameters; const values: ArrayOfParameters): TByteDynArray; stdcall;
end;


объявлен класс массив параметров, как я понял и им нада передавать эти массивы..
как это нормально описать в клиенте? :)

по простому функция передачи же

(HTTPRIO1 as ReportGeneratorPortType).getReportPdf(reportEdit.Text, , );

так будет, да? =)
а как передать массивы? или загнать в массивы?
а то вообще чета никак :(

Re: soap, передача массива =)

Добавлено: 19 дек 2006, 20:46
asterix20
даже поправочка
не
ArrayOfParameters = class(TRemotable)
public
arrkeys: array of variant;
arrvalues: array of variant;
private
published
end;

а вот так все :


ArrayOfParameters = class(TRemotable)
public
private
published
end;


что делать? :(

Re: soap, передача массива =)

Добавлено: 24 дек 2006, 03:17
asterix20
help pls... =(
есть же кто, кто работает с soap или направьте, где почитать про IInvokable классы..
а? и их использование

Re: soap, передача массива =)

Добавлено: 25 дек 2006, 09:21
Popov_PV
У меня так реализовано. может поможет (Все. конечно урезано :) )

на сервере:

type
{ TIPLAT }
TIPLAT = class(TInvokableClass, IIPLAT)
public
function SEND_PLATEGI_OLE(const id_Shop : integer; var Plategi : DATA_TRANS): DATA_TRANS; stdcall; //получить пакет платежей
end;

function TIPLAT.SEND_PLATEGI_OLE(const id_Shop : integer; var Plategi : DATA_TRANS): DATA_TRANS; stdcall;


на клиенте:

DATA_TRANS = array of Variant; { "urn:IPLATIntf" }
IIPLAT = interface(IInvokable)
['{017FA4EB-9323-8E3A-CC60-5888CC00AA38}']
function SEND_PLATEGI_OLE(const id_Shop: Integer; var Plategi: DATA_TRANS): DATA_TRANS; stdcall;
end;

Вызов в клиенте:
PP_A : DATA_TRANS;
TR_A:=(RIO1 as IIPlat).SEND_PLATEGI_OLE(IdPointLoc,PP_A);

Надеюсь, чем-то помог :)

Re: soap, передача массива =)

Добавлено: 26 дек 2006, 20:19
asterix20
ммм...
примерно понятно, как у тебя сделано =)
у тебя передается 1н массив вариантов, да?

у меня надо послать 2 раздельных масива...
с сервера я тока интерфейс могу получить ..
он вот таким дается wsdl importer'ом :

unit ReportGenerator;

interface

uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns;

type

// ************************************************************************ //
// The following types, referred to in the WSDL document are not being represented
// in this file. They are either aliases[@] of other types represented or were referred
// to but never[!] declared in the document. The types from the latter category
// typically map to predefined/known XML or Borland types; however, they could also
// indicate incorrect WSDL documents that failed to declare or import a schema type.
// ************************************************************************ //
// !:String - "http://www.w3.org/2001/XMLSchema"
// !:base64Binary - "http://www.w3.org/2001/XMLSchema"

ArrayOfParameters = class; { "urn:ReportGenerator" }



// ************************************************************************ //
// Namespace : urn:ReportGenerator
// ************************************************************************ //
ArrayOfParameters = class(TRemotable)
public
private
published
end;


// ************************************************************************ //
// Namespace : urn:ReportGenerator
// soapAction: ReportGenerator#getReportPdf
// transport : http://schemas.xmlsoap.org/soap/http
// style : rpc
// binding : ReportGeneratorBinding
// service : ReportGenerator
// port : ReportGeneratorPort
// URL : http://172.18.2.16/testws/ReportGenerator.php
// ************************************************************************ //
ReportGeneratorPortType = interface(IInvokable)
['{51BA4853-4A59-DAC7-7303-682FC35751C6}']
function getReportPdf(const report: String; const keys: ArrayOfParameters; const values: ArrayOfParameters): TByteDynArray; stdcall;
end;

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

если я объявляю переменную, как ArrayOfParameters , то постоянно выползает ошибка о несовместимости типов =(
это нада описать класс сам ArrayOfParameters ? или как? =)

Re: soap, передача массива =)

Добавлено: 27 дек 2006, 13:13
Popov_PV
Приведу тебе кусок из моего кода оплаты платежей одного из операторов)
Сервер находится у него на сайте. у меня как раз толко клиент:

Объявления:

type
PaymentConfirmAns = class;
PaymentRequestAns = class;

WSTerminalProcResult = (error_authtorization_cashier_blocked, error_authtorization_unknown_cashier, error_authtorization_unknown_terminal,
error_exception, error_unknown, success);

PaymentRequestAns = class(TRemotable)
private
FRESULT: Integer;
FSTRINFO: WideString;
FOPCODE: Integer;
FACCNO: WideString;
FOPTRANSID: WideString;
FTID: Int64;
FCID: Int64;
published
property RESULT: Integer read FRESULT write FRESULT;
property STRINFO: WideString read FSTRINFO write FSTRINFO;
property OPCODE: Integer read FOPCODE write FOPCODE;
property ACCNO: WideString read FACCNO write FACCNO;
property OPTRANSID: WideString read FOPTRANSID write FOPTRANSID;
property TID: Int64 read FTID write FTID;
property CID: Int64 read FCID write FCID;
end;

paydeskwsSoap = interface(IInvokable)
['{5EBDEDE3-6F88-39F9-9EF9-7D0F3D4A1560}']
procedure MobilePaymentRequest(const CASH_LOGIN: WideString; const CASH_PASSWORD: WideString; const P_DATE: WideString;
const P_PHONE: WideString; const P_OPCODE: WideString; const P_CURCODE: WideString; const P_AMOUNT: WideString;
const paymentRequestAns1: PaymentRequestAns; const sessCookie1: WideString; out MobilePaymentRequestResult: WSTerminalProcResult;
out paymentRequestAns: PaymentRequestAns; out sessCookie: WideString); stdcall;
end;

initialization
InvRegistry.RegisterInterface(TypeInfo(paydeskwsSoap), 'http://xxx.ru/', 'utf-8');
InvRegistry.RegisterDefaultSOAPAction(TypeInfo(paydeskwsSoap), 'http://xxx.ru/%operationName%');
InvRegistry.RegisterInvokeOptions(TypeInfo(paydeskwsSoap), ioDocument);
RemClassRegistry.RegisterXSInfo(TypeInfo(WSTerminalProcResult), 'http://xxx.ru/', 'WSTerminalProcResult');
RemClassRegistry.RegisterXSClass(PaymentRequestAns, 'http://xxx.org/', 'PaymentRequestAns');


Вызов

var
P_IN,P_SESS : WideString;
PP_IN,PP_OUT : PaymentRequestAns;
T_RESULT : WSTerminalProcResult;
begin
HTTPRIO1.Create(nil);
(HTTPRIO1 as dtpaydeskwsSoap).MobilePaymentRequest('',',DATE,NOMER,Operator,'',SUMMAR,PP_IN,P_IN,T_RESULT,PP_OUT,P_SESS);
end

Re: soap, передача массива =)

Добавлено: 27 дек 2006, 18:28
asterix20
мм...
а вот такой еще вопрос появился

если я описал так:
procedure runrep(const report: String; const keys: Array Of variant; const values: Array Of variant);
var
data1, data2:ArrayOfParameters;
vararr1, vararr2: PVarData;
begin
vararr1.VArray:=@keys;
vararr2.VArray:=@values;
data1.DataContext.AddVariantToClear(vararr1);
data2.DataContext.AddVariantToClear(vararr2);
(Form1.HTTPRIO1 as ReportGeneratorPortType).getReportPdf(report, data1, data2 );
end;

или даже так (так даже ошибка вылетает не при присвоении data1 а позже =) ):

procedure runrep(const report: String; const keys: Array Of variant; const values: Array Of variant);
var
data1, data2:ArrayOfParameters;
vararr1, vararr2: pVarData;
begin
vararr1:=@keys;
vararr2:=@values;
data1.DataContext.AddVariantToClear(vararr1);
data2.DataContext.AddVariantToClear(vararr2); //строчка"ы"
(Form1.HTTPRIO1 as ReportGeneratorPortType).getReportPdf(report, data1, data2 );
end;
когда по шагам иду, то почемут на строчке"ы" вылетает ошибка, потом перескакивает на runrep, поять ошибка, пару скачков туда-сюда, без ошибки и все ... о_0
procedure TForm1.Button1Click(Sender: TObject);
begin
runrep(reportEdit.Text, [keyEdit1.Text, keyEdit2.Text, keyEdit3.Text],
[parEdit1.Text, parEdit2.Text, parEdit3.Text]);

end;

то в переменных data1 и data2 будут содержаться keys и values ? или указатели на них?
как я понял, DataContext помещает (если так можно сказать :) ) в переменную значение передаваемых указателей, да?
и еще, если это правильно, то как потом из переменных вынуть значения? =) чета никак не могу найти/понять, как это делается ((


и еще
а можно в самом интерфейсе описать класс?
ArrayOfParameters = class(TRemotable)
public
private
published
end;

или должно быть одинаково и на клиенте и на сервере?

Re: soap, передача массива =)

Добавлено: 28 дек 2006, 08:47
Popov_PV
Не понятно, а почему ты сразу не можешь отсылать массивы?

TArrV = Array of variant;
PArrV = ^TArrV;

procedure runrep(const report: String; const keys: TArrV; const values: TArrV);
begin
(Form1.HTTPRIO1 as ReportGeneratorPortType).getReportPdf(report, Keys, Values );
end;

или так
procedure runrep(const report: String; const keys: TArrV; const values: TArrV);
var
vararr1, vararr2: PArrV;
begin
// если же надо передать указатель, то так
vararr1:=@keys;
vararr2:=@values;
(Form1.HTTPRIO1 as ReportGeneratorPortType).getReportPdf(report, vararr1, vararr2 );
или
(Form1.HTTPRIO1 as ReportGeneratorPortType).getReportPdf(report, @keys, @values );
end;



procedure TForm1.Button1Click(Sender: TObject);
var
A1,A2 : TArrV;
begin
SetLength(A1,N);
SetLength(A2,N);
// заполняем N эл-ми
runrep('test', A1,A2);
end;

но тогда надо и на сервере объявить такие же типы TArrV и в проц-ах вызова. Грамотнее всегда объявлять типы через собственные идентификаторы. Глюков меньше. Если ты решишь сменить тип, то менять придется только одну строчку определения типа, а не все процы и переменные :) И вообще, зачем тебе Указатели? У тебя на серевере принимается указатель что ли?

Re: soap, передача массива =)

Добавлено: 29 дек 2006, 15:20
asterix20
на сервере принимаются не указатели :) а сами массиви..
должны...
я бы рад поменять на сервере, чтоб были не ArrayOfParameters , а массивы =), но это немного не от меня зависит +(((
вся сложность вроде заключается именно в
function getReportPdf(const report: String; const keys: ArrayOfParameters; const values: ArrayOfParameters): TByteDynArray; stdcall;
т.к. компилятор постоянно ругается на несовместимость типов ...
а как задать в этот ArrayOfParameters то, что нужно - это не понятно...
поэтому пытался воспользоваться свойством DataContext ..
но как-то не так похоже =\