Groups > Borland > Dellphi web services soap > Re: De-Serializing TRemotable problems




De-Serializing TRemotable problems

De-Serializing TRemotable problems
Thu, 07 Feb 2008 14:02:47 +110
Hi,

I'm using CodeGear Rad Studio 2007 (Delphi Win32 2007) as a web services 
consumer and Visual Studio 2003 (C#), .Net 1.1 as the web services server.

I can use the web service fine using Delphi, however I'd like to be able 
to serialize/de-serialize some of the TRemotable based classes. The 
current method that I'm using (basically the SoapToObject and 
ObjectToSoap methods) doesn't seem to de-serialize properly. I've 
serialized and then had a look at the xml and this seems ok, however I'm 
having troubles loading this back into an object. I've described the 
problem below with some code to explain.

If anyone can think of a better way for me to serialize/de-serialize 
TRemotable classes, can you please share? Thanks

The problem code is the last procedure in this email (TForm3.Button2Click)

********* This code is the one imported from WSDL importer *************

   BaseType = class(TRemotable)
   private
   published
   end;

   MonetaryItemType = class(BaseType)
   private
     FValue: TXSDecimal;
   public
     destructor Destroy; override;
   published
     property Value: TXSDecimal  read FValue write FValue;
   end;


   TMyBankingType = class(TRemotable)
   private
     FGrossInterestAmt: MonetaryItemType;
     FGrossInterestAmt_Specified: boolean;
     FApportionedInterestAmt: MonetaryItemType;
     FApportionedInterestAmt_Specified: boolean;
     procedure SetGrossInterestAmt(Index: Integer; const 
AMonetaryItemType: MonetaryItemType);
     function  GrossInterestAmt_Specified(Index: Integer): boolean;
     procedure SetApportionedInterestAmt(Index: Integer; const 
AMonetaryItemType: MonetaryItemType);
     function  ApportionedInterestAmt_Specified(Index: Integer): boolean;
   public
     destructor Destroy; override;
   published
     property GrossInterestAmt:       MonetaryItemType  Index (IS_OPTN) 
read FGrossInterestAmt write SetGrossInterestAmt stored 
GrossInterestAmt_Specified;
     property ApportionedInterestAmt: MonetaryItemType  Index (IS_OPTN) 
read FApportionedInterestAmt write SetApportionedInterestAmt stored 
ApportionedInterestAmt_Specified;
   end;

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

********* This is my code serializing and deserializing ****************

//xml document is a TXMLDocument put on the form, uses default //properties
//OpToSoapDomConvert1 is a TOpToSoapDomConvert on the form, uses default 
//properties
//this procedure works fine, it gets the data that i want
//from the webservice and serializes the objects in an xml node
procedure TForm3.Button1Click(Sender: TObject);
var
   soapService: MySoapService;
   req: SoapRequest;
   resp: SoapResponse;
   errorMessage: WideString;
   ARootNode, NewNode: IXMLNode;
   RefId: WideString;
   bankingData: TMyBankingType;
begin
   XMLDocument1.Active := True;
   soapService := GetMySoapService();
   FillRequest(req);
   try
     try
       resp := soapService.GetData(req, errorMessage);
       ARootNode := XMLDocument1.CreateNode('MyRemotable');

       bankingData := resp.BankingData;
       newNode := bankingData.ObjectToSOAP(ARootNode,
         ARootNode, OPToSoapDomConvert1, 'Test', 'Test',[], RefId);

       XMLDocument1.DocumentElement := ARootNode;
       Memo1.Lines.Clear;
       Memo1.Lines.Add(XMLDocument1.XML.Text);
     except
       on E: Exception do
         ShowMessage(E.Message);
     end;
   finally
     FreeAndNil(req);
     FreeAndNil(resp);
   end;
end;

//this procedure is the problem, it seems to serialize the object but 
//always returns a nil value for the value property of TMyBankingType
procedure TForm3.Button2Click(Sender: TObject);
var
   data: TMyBankingType;
begin
   XMLDocument1.XML.Text := Memo1.Text;
   XMLDocument1.Active := True;
   data := TMyBankingType.Create();
   try
     data.SOAPToObject(XMLDocument1.DocumentElement,
       XMLDocument1.DocumentElement.ChildNodes[0], OPToSoapDomConvert1);
     //access violation because Value is always nil!
     ShowMessage(data.Value.DecimalString);
   finally
     FreeAndNil(data);
   end;
end;


Post Reply
Re: De-Serializing TRemotable problems
Thu, 7 Feb 2008 17:23:28 -0800
Hello,

Here's a sample code that illustrates how you could serialize an object to
and from XML:


const
  sROOT_NODE = 'Root';
  sROOT_NS = 'urn:TestNamespace';

function ObjToXML(const AObject: TRemotable; const ObjConverter:
IObjConverter): WideString;
  var
  Xdoc: IXMLDocument;
  Root: IXmlNode;
  RefId: WideString;
  Namespace, TypeName: WideString;
  IsScalar: Boolean;
begin
  Xdoc := NewXMLDocument;
  Root := Xdoc.AddChild(sROOT_NODE, sROOT_NS);
  Root.DeclareNamespace(SXMLSchemaNameSpacePre, XMLSchemaNameSpace);
  Root.DeclareNamespace(SXMLSchemaInstNameSpace99Pre,
XMLSchemaInstNameSpace);

  RemClassRegistry.ClassToURI(AObject.ClassType, Namespace, TypeName,
IsScalar);
  AObject.ObjectToSOAP(Root, Root, ObjConverter,
                       TypeName, Namespace, [], RefId);
  Result := FormatXMLData(Xdoc.Node.XML);
end;

function XMLToObj(const XML: WideString; const ObjConverter: IObjConverter;
var AObject: TRemotable): Boolean;
  var
  Xdoc: IXMLDocument;
  Root, Node: IXmlNode;
begin
  Xdoc := LoadXMLdata(XML);
  Root := Xdoc.ChildNodes.FindNode(sROOT_NODE, sROOT_NS);
  Node := Root.ChildNodes[0];
  AObject.SOAPToObject(Root, Node, ObjConverter);
  Result := True;
end;


I'm copying the above from some testing code that we have. It may not be
exactly that you're after but should give you an idea. There's some
unnecessary code above (like formatting) that you'll probably want to
remove. Also, we create a fake root node. Typically that's some element
within the body (or header) of a SOAP envelope.

The one issue that I'm aware of is that you often have to clone a converter
because the API does not allow you (public) access to the method to reset
the converter. Really just the Convert Options are relevant in that case. So
we have some code to handle that too:

function CloneConverter(const Convert: TOPToSoapDomConvert): IObjConverter;
var
  NewConv: TOPToSoapDomConvert;
begin
  NewConv := TOPToSoapDomConvert.Create(nil);
  Result := NewConv;
  NewConv.Options := Convert.Options;
end;

function CloneConverter(const RIO: THTTPRIO): IObjConverter;
begin
  Result := CloneConverter(RIO.Converter);
end;


Please let me know if the above does not answer your question and I'll
investigate some.

Cheers,

Bruneau.

Post Reply
Re: De-Serializing TRemotable problems
Mon, 11 Feb 2008 16:17:16 +110
Hi,

I tried your code but it still doesn't seem to instantiate the "value"

property of the MonetaryItemType class (from my original example code).

I've also noticed that this is only if it happens to be of TXSDateTime 
or TXSDecimal etc (basically any type that has TXS in front of it). If I 
have string or int types of properties then it works fine!


Jean-Marie Babet wrote:
> Hello,
> 
> Here's a sample code that illustrates how you could serialize an object to
> and from XML:
> 
> 
> const
>   sROOT_NODE = 'Root';
>   sROOT_NS = 'urn:TestNamespace';
> 
> function ObjToXML(const AObject: TRemotable; const ObjConverter:
> IObjConverter): WideString;
>   var
>   Xdoc: IXMLDocument;
>   Root: IXmlNode;
>   RefId: WideString;
>   Namespace, TypeName: WideString;
>   IsScalar: Boolean;
> begin
>   Xdoc := NewXMLDocument;
>   Root := Xdoc.AddChild(sROOT_NODE, sROOT_NS);
>   Root.DeclareNamespace(SXMLSchemaNameSpacePre, XMLSchemaNameSpace);
>   Root.DeclareNamespace(SXMLSchemaInstNameSpace99Pre,
> XMLSchemaInstNameSpace);
> 
>   RemClassRegistry.ClassToURI(AObject.ClassType, Namespace, TypeName,
> IsScalar);
>   AObject.ObjectToSOAP(Root, Root, ObjConverter,
>                        TypeName, Namespace, [], RefId);
>   Result := FormatXMLData(Xdoc.Node.XML);
> end;
> 
> function XMLToObj(const XML: WideString; const ObjConverter:
IObjConverter;
> var AObject: TRemotable): Boolean;
>   var
>   Xdoc: IXMLDocument;
>   Root, Node: IXmlNode;
> begin
>   Xdoc := LoadXMLdata(XML);
>   Root := Xdoc.ChildNodes.FindNode(sROOT_NODE, sROOT_NS);
>   Node := Root.ChildNodes[0];
>   AObject.SOAPToObject(Root, Node, ObjConverter);
>   Result := True;
> end;
> 
> 
> I'm copying the above from some testing code that we have. It may not be
> exactly that you're after but should give you an idea. There's some
> unnecessary code above (like formatting) that you'll probably want to
> remove. Also, we create a fake root node. Typically that's some element
> within the body (or header) of a SOAP envelope.
> 
> The one issue that I'm aware of is that you often have to clone a
converter
> because the API does not allow you (public) access to the method to reset
> the converter. Really just the Convert Options are relevant in that case.
So
> we have some code to handle that too:
> 
> function CloneConverter(const Convert: TOPToSoapDomConvert):
IObjConverter;
> var
>   NewConv: TOPToSoapDomConvert;
> begin
>   NewConv := TOPToSoapDomConvert.Create(nil);
>   Result := NewConv;
>   NewConv.Options := Convert.Options;
> end;
> 
> function CloneConverter(const RIO: THTTPRIO): IObjConverter;
> begin
>   Result := CloneConverter(RIO.Converter);
> end;
> 
> 
> Please let me know if the above does not answer your question and I'll
> investigate some.
> 
> Cheers,
> 
> Bruneau.
> 
Post Reply
Re: De-Serializing TRemotable problems
Mon, 18 Feb 2008 11:45:07 +110
Hi,

Any word on why this is happening? Anybody have any alternatives to 
serializing/deserializing classes to xml?

Jaweed wrote:
> Hi,
> 
> I tried your code but it still doesn't seem to instantiate the
"value" 
> property of the MonetaryItemType class (from my original example code).
> 
> I've also noticed that this is only if it happens to be of TXSDateTime 
> or TXSDecimal etc (basically any type that has TXS in front of it). If I 
> have string or int types of properties then it works fine!
> 
> 
> Jean-Marie Babet wrote:
>> Hello,
>>
>> Here's a sample code that illustrates how you could serialize an 
>> object to
>> and from XML:
>>
>>
>> const
>>   sROOT_NODE = 'Root';
>>   sROOT_NS = 'urn:TestNamespace';
>>
>> function ObjToXML(const AObject: TRemotable; const ObjConverter:
>> IObjConverter): WideString;
>>   var
>>   Xdoc: IXMLDocument;
>>   Root: IXmlNode;
>>   RefId: WideString;
>>   Namespace, TypeName: WideString;
>>   IsScalar: Boolean;
>> begin
>>   Xdoc := NewXMLDocument;
>>   Root := Xdoc.AddChild(sROOT_NODE, sROOT_NS);
>>   Root.DeclareNamespace(SXMLSchemaNameSpacePre, XMLSchemaNameSpace);
>>   Root.DeclareNamespace(SXMLSchemaInstNameSpace99Pre,
>> XMLSchemaInstNameSpace);
>>
>>   RemClassRegistry.ClassToURI(AObject.ClassType, Namespace, TypeName,
>> IsScalar);
>>   AObject.ObjectToSOAP(Root, Root, ObjConverter,
>>                        TypeName, Namespace, [], RefId);
>>   Result := FormatXMLData(Xdoc.Node.XML);
>> end;
>>
>> function XMLToObj(const XML: WideString; const ObjConverter: 
>> IObjConverter;
>> var AObject: TRemotable): Boolean;
>>   var
>>   Xdoc: IXMLDocument;
>>   Root, Node: IXmlNode;
>> begin
>>   Xdoc := LoadXMLdata(XML);
>>   Root := Xdoc.ChildNodes.FindNode(sROOT_NODE, sROOT_NS);
>>   Node := Root.ChildNodes[0];
>>   AObject.SOAPToObject(Root, Node, ObjConverter);
>>   Result := True;
>> end;
>>
>>
>> I'm copying the above from some testing code that we have. It may not
be
>> exactly that you're after but should give you an idea. There's some
>> unnecessary code above (like formatting) that you'll probably want to
>> remove. Also, we create a fake root node. Typically that's some
element
>> within the body (or header) of a SOAP envelope.
>>
>> The one issue that I'm aware of is that you often have to clone a 
>> converter
>> because the API does not allow you (public) access to the method to
reset
>> the converter. Really just the Convert Options are relevant in that 
>> case. So
>> we have some code to handle that too:
>>
>> function CloneConverter(const Convert: TOPToSoapDomConvert): 
>> IObjConverter;
>> var
>>   NewConv: TOPToSoapDomConvert;
>> begin
>>   NewConv := TOPToSoapDomConvert.Create(nil);
>>   Result := NewConv;
>>   NewConv.Options := Convert.Options;
>> end;
>>
>> function CloneConverter(const RIO: THTTPRIO): IObjConverter;
>> begin
>>   Result := CloneConverter(RIO.Converter);
>> end;
>>
>>
>> Please let me know if the above does not answer your question and I'll
>> investigate some.
>>
>> Cheers,
>>
>> Bruneau.
>>
Post Reply
Re: De-Serializing TRemotable problems
Tue, 26 Feb 2008 10:07:57 -080
Hello,

My apologies for the delay. I've been away from the newsgroup (dealing with
a cold) for several days. I'll try to post something later today.

Cheers,

Bruneau.

Post Reply
<< Previous 1 2 Next >>
( Page 1 of 2 )
about | contact