我做了一个简单的.NET WCF wsDualHttpBinding,它回调客户端。现在我正在尝试创建一个实现我的wcf服务的简单delphi控制台应用程序。这是wsdl soap 1.2在delphi中为我生成的代码
我认为我需要做的就是这样,但无法理解Delphi对OnMessageAdded的期望
Listener := MessageService.GetIMessage(true);
Listener.Subscribe(MessageService.Subscribe.Create);
Listener.OnMessageAdded :=
Sender := MessageService.GetIMessage(true);
Sender.Subscribe(MessageService.Subscribe.Create);
这是WSDL http://pastebin.com/H4mJmjS4
以下是delphi xe2
生成的代码// ************************************************************************ //
// The types declared in this file were generated from data read from the
// WSDL File described below:
// WSDL : http://localhost:8700/Design_Time_Addresses/WCFCallbacks/Message/?wsdl
// >Import : http://localhost:8700/Design_Time_Addresses/WCFCallbacks/Message/?wsdl>0
// >Import : http://localhost:8700/Design_Time_Addresses/WCFCallbacks/Message/?xsd=xsd0
// >Import : http://localhost:8700/Design_Time_Addresses/WCFCallbacks/Message/?xsd=xsd1
// Encoding : utf-8
// Codegen : [wfForceSOAP12+]
// Version : 1.0
// (06/15/2012 2:43:02 PM - - $Rev: 45757 $)
// ************************************************************************ //
unit MessageService;
interface
uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns;
const
IS_OPTN = $0001;
IS_NLBL = $0004;
IS_REF = $0080;
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 Embarcadero 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"[Gbl]
// !:dateTime - "http://www.w3.org/2001/XMLSchema"[Gbl]
// !:boolean - "http://www.w3.org/2001/XMLSchema"[Gbl]
Subscribe = class; { "http://tempuri.org/"[Lit][GblElm] }
AddMessageResponse = class; { "http://tempuri.org/"[Lit][GblElm] }
AddMessage = class; { "http://tempuri.org/"[Lit][GblElm] }
OnMessageAdded = class; { "http://tempuri.org/"[Lit][GblElm] }
UnsubscribeResponse = class; { "http://tempuri.org/"[Lit][GblElm] }
SubscribeResponse = class; { "http://tempuri.org/"[Lit][GblElm] }
Unsubscribe = class; { "http://tempuri.org/"[Lit][GblElm] }
// ************************************************************************ //
// XML : Subscribe, global, <element>
// Namespace : http://tempuri.org/
// Serializtn: [xoLiteralParam]
// Info : Wrapper
// ************************************************************************ //
Subscribe = class(TRemotable)
private
public
constructor Create; override;
published
end;
// ************************************************************************ //
// XML : AddMessageResponse, global, <element>
// Namespace : http://tempuri.org/
// Serializtn: [xoLiteralParam]
// Info : Wrapper
// ************************************************************************ //
AddMessageResponse = class(TRemotable)
private
public
constructor Create; override;
published
end;
// ************************************************************************ //
// XML : AddMessage, global, <element>
// Namespace : http://tempuri.org/
// Serializtn: [xoLiteralParam]
// Info : Wrapper
// ************************************************************************ //
AddMessage = class(TRemotable)
private
Fmessage_: string;
Fmessage__Specified: boolean;
procedure Setmessage_(Index: Integer; const Astring: string);
function message__Specified(Index: Integer): boolean;
public
constructor Create; override;
published
property message_: string Index (IS_OPTN or IS_NLBL) read Fmessage_ write Setmessage_ stored message__Specified;
end;
// ************************************************************************ //
// XML : OnMessageAdded, global, <element>
// Namespace : http://tempuri.org/
// Serializtn: [xoLiteralParam]
// Info : Wrapper
// ************************************************************************ //
OnMessageAdded = class(TRemotable)
private
Fmessage_: string;
Fmessage__Specified: boolean;
Ftimestamp: TXSDateTime;
Ftimestamp_Specified: boolean;
procedure Setmessage_(Index: Integer; const Astring: string);
function message__Specified(Index: Integer): boolean;
procedure Settimestamp(Index: Integer; const ATXSDateTime: TXSDateTime);
function timestamp_Specified(Index: Integer): boolean;
public
constructor Create; override;
destructor Destroy; override;
published
property message_: string Index (IS_OPTN or IS_NLBL) read Fmessage_ write Setmessage_ stored message__Specified;
property timestamp: TXSDateTime Index (IS_OPTN) read Ftimestamp write Settimestamp stored timestamp_Specified;
end;
// ************************************************************************ //
// XML : UnsubscribeResponse, global, <element>
// Namespace : http://tempuri.org/
// Serializtn: [xoLiteralParam]
// Info : Wrapper
// ************************************************************************ //
UnsubscribeResponse = class(TRemotable)
private
FUnsubscribeResult: Boolean;
FUnsubscribeResult_Specified: boolean;
procedure SetUnsubscribeResult(Index: Integer; const ABoolean: Boolean);
function UnsubscribeResult_Specified(Index: Integer): boolean;
public
constructor Create; override;
published
property UnsubscribeResult: Boolean Index (IS_OPTN) read FUnsubscribeResult write SetUnsubscribeResult stored UnsubscribeResult_Specified;
end;
// ************************************************************************ //
// XML : SubscribeResponse, global, <element>
// Namespace : http://tempuri.org/
// Serializtn: [xoLiteralParam]
// Info : Wrapper
// ************************************************************************ //
SubscribeResponse = class(TRemotable)
private
FSubscribeResult: Boolean;
FSubscribeResult_Specified: boolean;
procedure SetSubscribeResult(Index: Integer; const ABoolean: Boolean);
function SubscribeResult_Specified(Index: Integer): boolean;
public
constructor Create; override;
published
property SubscribeResult: Boolean Index (IS_OPTN) read FSubscribeResult write SetSubscribeResult stored SubscribeResult_Specified;
end;
// ************************************************************************ //
// XML : Unsubscribe, global, <element>
// Namespace : http://tempuri.org/
// Serializtn: [xoLiteralParam]
// Info : Wrapper
// ************************************************************************ //
Unsubscribe = class(TRemotable)
private
public
constructor Create; override;
published
end;
// ************************************************************************ //
// Namespace : http://tempuri.org/
// soapAction: http://tempuri.org/IMessage/%operationName%
// transport : http://schemas.xmlsoap.org/soap/http
// style : document
// use : literal
// binding : WSDualHttpBinding_IMessage
// service : MessageService
// port : WSDualHttpBinding_IMessage
// URL : http://localhost:8700/Design_Time_Addresses/WCFCallbacks/Message/
// ************************************************************************ //
IMessage = interface(IInvokable)
['{8AE9E38B-51D7-6EB7-5470-5B197F54CF0A}']
function AddMessage(const parameters: AddMessage): AddMessageResponse; stdcall;
function Subscribe(const parameters: Subscribe): SubscribeResponse; stdcall;
function Unsubscribe(const parameters: Unsubscribe): UnsubscribeResponse; stdcall;
// Cannot unwrap:
// - More than one strictly out element was found
function OnMessageAdded: OnMessageAdded; stdcall;
end;
function GetIMessage(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil): IMessage;
implementation
uses SysUtils;
function GetIMessage(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): IMessage;
const
defWSDL = 'http://localhost:8700/Design_Time_Addresses/WCFCallbacks/Message/?wsdl';
defURL = 'http://localhost:8700/Design_Time_Addresses/WCFCallbacks/Message/';
defSvc = 'MessageService';
defPrt = 'WSDualHttpBinding_IMessage';
var
RIO: THTTPRIO;
begin
Result := nil;
if (Addr = '') then
begin
if UseWSDL then
Addr := defWSDL
else
Addr := defURL;
end;
if HTTPRIO = nil then
RIO := THTTPRIO.Create(nil)
else
RIO := HTTPRIO;
try
Result := (RIO as IMessage);
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;
constructor Subscribe.Create;
begin
inherited Create;
FSerializationOptions := [xoLiteralParam];
end;
constructor AddMessageResponse.Create;
begin
inherited Create;
FSerializationOptions := [xoLiteralParam];
end;
constructor AddMessage.Create;
begin
inherited Create;
FSerializationOptions := [xoLiteralParam];
end;
procedure AddMessage.Setmessage_(Index: Integer; const Astring: string);
begin
Fmessage_ := Astring;
Fmessage__Specified := True;
end;
function AddMessage.message__Specified(Index: Integer): boolean;
begin
Result := Fmessage__Specified;
end;
constructor OnMessageAdded.Create;
begin
inherited Create;
FSerializationOptions := [xoLiteralParam];
end;
destructor OnMessageAdded.Destroy;
begin
SysUtils.FreeAndNil(Ftimestamp);
inherited Destroy;
end;
procedure OnMessageAdded.Setmessage_(Index: Integer; const Astring: string);
begin
Fmessage_ := Astring;
Fmessage__Specified := True;
end;
function OnMessageAdded.message__Specified(Index: Integer): boolean;
begin
Result := Fmessage__Specified;
end;
procedure OnMessageAdded.Settimestamp(Index: Integer; const ATXSDateTime: TXSDateTime);
begin
Ftimestamp := ATXSDateTime;
Ftimestamp_Specified := True;
end;
function OnMessageAdded.timestamp_Specified(Index: Integer): boolean;
begin
Result := Ftimestamp_Specified;
end;
constructor UnsubscribeResponse.Create;
begin
inherited Create;
FSerializationOptions := [xoLiteralParam];
end;
procedure UnsubscribeResponse.SetUnsubscribeResult(Index: Integer; const ABoolean: Boolean);
begin
FUnsubscribeResult := ABoolean;
FUnsubscribeResult_Specified := True;
end;
function UnsubscribeResponse.UnsubscribeResult_Specified(Index: Integer): boolean;
begin
Result := FUnsubscribeResult_Specified;
end;
constructor SubscribeResponse.Create;
begin
inherited Create;
FSerializationOptions := [xoLiteralParam];
end;
procedure SubscribeResponse.SetSubscribeResult(Index: Integer; const ABoolean: Boolean);
begin
FSubscribeResult := ABoolean;
FSubscribeResult_Specified := True;
end;
function SubscribeResponse.SubscribeResult_Specified(Index: Integer): boolean;
begin
Result := FSubscribeResult_Specified;
end;
constructor Unsubscribe.Create;
begin
inherited Create;
FSerializationOptions := [xoLiteralParam];
end;
initialization
{ IMessage }
InvRegistry.RegisterInterface(TypeInfo(IMessage), 'http://tempuri.org/', 'utf-8');
InvRegistry.RegisterDefaultSOAPAction(TypeInfo(IMessage), 'http://tempuri.org/IMessage/%operationName%');
InvRegistry.RegisterInvokeOptions(TypeInfo(IMessage), ioDocument);
InvRegistry.RegisterInvokeOptions(TypeInfo(IMessage), ioLiteral);
InvRegistry.RegisterInvokeOptions(TypeInfo(IMessage), ioSOAP12);
RemClassRegistry.RegisterXSClass(Subscribe, 'http://tempuri.org/', 'Subscribe');
RemClassRegistry.RegisterSerializeOptions(Subscribe, [xoLiteralParam]);
RemClassRegistry.RegisterXSClass(AddMessageResponse, 'http://tempuri.org/', 'AddMessageResponse');
RemClassRegistry.RegisterSerializeOptions(AddMessageResponse, [xoLiteralParam]);
RemClassRegistry.RegisterXSClass(AddMessage, 'http://tempuri.org/', 'AddMessage');
RemClassRegistry.RegisterExternalPropName(TypeInfo(AddMessage), 'message_', '[ExtName="message"]');
RemClassRegistry.RegisterSerializeOptions(AddMessage, [xoLiteralParam]);
RemClassRegistry.RegisterXSClass(OnMessageAdded, 'http://tempuri.org/', 'OnMessageAdded');
RemClassRegistry.RegisterExternalPropName(TypeInfo(OnMessageAdded), 'message_', '[ExtName="message"]');
RemClassRegistry.RegisterSerializeOptions(OnMessageAdded, [xoLiteralParam]);
RemClassRegistry.RegisterXSClass(UnsubscribeResponse, 'http://tempuri.org/', 'UnsubscribeResponse');
RemClassRegistry.RegisterSerializeOptions(UnsubscribeResponse, [xoLiteralParam]);
RemClassRegistry.RegisterXSClass(SubscribeResponse, 'http://tempuri.org/', 'SubscribeResponse');
RemClassRegistry.RegisterSerializeOptions(SubscribeResponse, [xoLiteralParam]);
RemClassRegistry.RegisterXSClass(Unsubscribe, 'http://tempuri.org/', 'Unsubscribe');
RemClassRegistry.RegisterSerializeOptions(Unsubscribe, [xoLiteralParam]);
end.
答案 0 :(得分:2)
使用wsDualHttpBinding,WCF端希望将响应作为HTTP请求异步发送到客户端。
所以实际上你的Delphi应用程序也需要提供一个接受WCF请求的HTTP服务器。
Delphis SOAP客户端实现中不包含异步操作支持 - 添加Delphi SOAP服务器(仅为回调操作提供匹配方法)将是一种解决方法。