|
| 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
|
|
|