Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

SOAP 1.2 Delphi 2010

828 views
Skip to first unread message

Esoj

unread,
Feb 23, 2010, 12:59:01 PM2/23/10
to
Hi, I made a Web service in .Net wich implements MTOM, but when i try
to use in Delphi 2010 i receive the error "Unsupporte Media Type
(415)", i know the error is because MTOM send a binary and delphi is
expecting a XML, What's need to do to enabled MTOM in Delphi 2010,
Thanks, i hope someone could help me.
Regards.

radi...@gmail.com

unread,
Feb 24, 2016, 8:43:35 AM2/24/16
to
Hi. May be someone helped my solution for read MTOM.

1. Need add new class. It's only find binary data and add Content-Length in Stream, because in XE version will be find attachment by Content-Length. Don't forget add "System.Classes" in uses.

TMTOMSOAP = class(THTTPRIO)
public
constructor Create(AOwner: TComponent); override;

procedure HTTPRIO2AfterExecute(const MethodName: String; SOAPResponse: TStream);
end;

{ TMTOMSOAP }

constructor TMTOMSOAP.Create(AOwner: TComponent);
begin
inherited;

OnAfterExecute := HTTPRIO2AfterExecute;
end;

procedure TMTOMSOAP.HTTPRIO2AfterExecute(const MethodName: String;
SOAPResponse: TStream);
var
iPosStart, iPosEnd: Integer;
Str: AnsiString;

procedure SetContentLength(Eof: AnsiString);
var
iLength: Integer;
sCL: AnsiString;
begin
iPosEnd := Pos(Eof+'--' +WebNode.MimeBoundary +'--',Str,iPosStart+1);
if iPosEnd > 0 then begin
sCL := Eof+'Content-Length: '+IntToStr(iPosEnd -(iPosStart+Length(Eof)*2));
iLength := Length(sCL);
SetLength(Str,Length(Str)+iLength);
Move(Str[iPosStart],Str[iPosStart+iLength],Length(Str)-iPosStart);
Move(sCL[1],Str[iPosStart],iLength);
SOAPResponse.Position := 0;
SOAPResponse.Write(Str[1], Length(Str));
end;
end;

begin
if SOAPResponse is TMemoryStream then begin
SetLength(Str,SOAPResponse.Size);
SOAPResponse.Position := 0;
SOAPResponse.Read(Str[1], SOAPResponse.Size);

iPosStart := Pos('--'+WebNode.MimeBoundary,Str);
if iPosStart > 0 then begin
iPosStart := Pos('--'+WebNode.MimeBoundary,Str,iPosStart+1);
if iPosStart > 0 then begin
iPosStart := Pos(#13#10#13#10,Str,iPosStart+1); //Windows(CRLF)
if iPosStart > 0 then
SetContentLength(#13#10)
else begin
iPosStart := Pos(#10#10,Str,iPosStart+1); //Unix(LF)
if iPosStart > 0 then
SetContentLength(#10);
end;
end;
end;
end;
end;

2. Add class for data and change it for needs elements in generating WSDL file. Just like in first message. Don't forget add "Xml.XMLIntf" in uses.

TMTOMFile = class(TRemotable)
private
public
MemorySterams: array of TMemoryStream;

destructor Destroy; override;

procedure SOAPToObject(const RootNode: IXMLNode; const Node: IXMLNode;
const ObjConverter: IObjConverter); override;

published
end;

{ TMTOMFile }

destructor TMTOMFile.Destroy;
var
iI: Integer;
begin
for iI := 0 to High(MemorySterams) do
MemorySterams[iI].Free;
inherited;
end;

procedure TMTOMFile.SOAPToObject(const RootNode, Node: IXMLNode;
const ObjConverter: IObjConverter);
var
Attachment: TSOAPAttachment;
iI: Integer;
iLength: Integer;
IncludeNode: IXMLNode;
begin
inherited;
if Node.HasChildNodes then begin
IncludeNode := Node.ChildNodes.First;
while Assigned(IncludeNode) do begin
if (IncludeNode.NamespaceURI = 'http://www.w3.org/2004/08/xop/include') and (IncludeNode.LocalName = 'Include') then begin
Attachment := ObjConverter.FindAttachment('thismessage:/' +IncludeNode.Attributes['href']);
if Assigned(Attachment) then begin
iLength := Length(MemorySterams);
SetLength(MemorySterams,iLength+1);
MemorySterams[iLength] := TMemoryStream.Create;
Attachment.SaveToStream(MemorySterams[iLength]);
end;
end;
IncludeNode := IncludeNode.NextSibling;
end;
end;
end;

3. Next you need change "THTTPRIO" to "TMTOMSOAP" in Port function.
For progress download you can add in arguments Port function "TReceivingDataEvent".
Don't forget add "Soap.SOAPHTTPTrans" in uses.
For sample look this function:

function GetSharedStoragePort(UseWSDL: Boolean; Addr: string; OnEvent: TReceivingDataEvent; HTTPRIO: TMTOMSOAP): SharedStoragePort;
const
defWSDL = 'SharedStorage.wsdl';
defURL = '';
defSvc = 'SharedStorage';
defPrt = 'SharedStorage';
var
RIO: TMTOMSOAP;
begin
Result := nil;
if (Addr = '') then
begin
if UseWSDL then
Addr := defWSDL
else
Addr := defURL;
end;
if HTTPRIO = nil then
RIO := TMTOMSOAP.Create(nil) //!!!
else
RIO := HTTPRIO;
try
RIO.HTTPWebNode.OnReceivingData := OnEvent; //!!!
Result := (RIO as SharedStoragePort);
if UseWSDL then
begin
RIO.WSDLLocation := Addr;
RIO.Service := defSvc;
RIO.Port := defPrt;
end else
RIO.URL := Addr;
finally
if (Result = nil) and (HTTPRIO = nil) then
RIO.Free;
end;
end;

4. Call Port and call download file function. Then you can get file like this:

jlp := GetSharedStoragePort(False,sAddr,onEvent); //call port
if Assigned(jlp) then begin
rezDownloed := jlp.DownloadFile(sFileName); //download file
rezDownloed.FileData.MemorySterams[0].SaveToFile('C:\test.db'); //save file
0 new messages