&引用;属性未声明";Delphi生成的EWS SOAP请求中出错
这是在从Exchange Server检索WDSL后生成的调用ResolveNames的工作示例代码:&引用;属性未声明";Delphi生成的EWS SOAP请求中出错,delphi,soap,delphi-xe2,exchangewebservices,Delphi,Soap,Delphi Xe2,Exchangewebservices,这是在从Exchange Server检索WDSL后生成的调用ResolveNames的工作示例代码: <?xml version="1.0"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:mes="h
<?xml version="1.0"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:typ="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:mes="http://schemas.microsoft.com/exchange/services/2006/messages">
<soapenv:Header><typ:RequestServerVersion Version="Exchange2010"/></soapenv:Header>
<soapenv:Body>
<mes:ResolveNames ReturnFullContactData="1" SearchScope="ActiveDirectoryContacts">
<mes:UnresolvedEntry>deve</mes:UnresolvedEntry>
</mes:ResolveNames>
</soapenv:Body>
</soapenv:Envelope>
它产生:
<?xml version="1.0"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body xmlns:NS1="http://schemas.microsoft.com/exchange/services/2006/types">
<ResolveNames xmlns="http://schemas.microsoft.com/exchange/services/2006/messages" ReturnFullContactData="true" NS1:SearchScope="ActiveDirectoryContacts">
<UnresolvedEntry>deve</UnresolvedEntry>
</ResolveNames>
<MailboxCulture xsi:nil="true"/>
<ExchangeImpersonation xsi:nil="true"/>
<NS1:RequestServerVersion Version="Exchange2010"/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
德维
我得到的错误:请求架构验证失败:未声明“”属性 SearchScope是messages.xsd中定义的属性:
<!-- ResolveNames request -->
<xs:complexType name="ResolveNamesType">
<xs:complexContent>
<xs:extension base="m:BaseRequestType">
<xs:sequence>
<xs:element name="ParentFolderIds" type="t:NonEmptyArrayOfBaseFolderIdsType" minOccurs="0"/>
<xs:element name="UnresolvedEntry" type="t:NonEmptyStringType"/>
</xs:sequence>
<xs:attribute name="ReturnFullContactData" type="xs:boolean" use="required"/>
<xs:attribute name="SearchScope" type="t:ResolveNamesSearchScopeType" default="ActiveDirectoryContacts"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="ResolveNames" type="m:ResolveNamesType"/>
对于in-types.xsd:
<!-- ResolveNames request -->
<xs:simpleType name="ResolveNamesSearchScopeType">
<xs:restriction base="xs:string">
<xs:enumeration value="ActiveDirectory"/>
<xs:enumeration value="ActiveDirectoryContacts"/>
<xs:enumeration value="Contacts"/>
<xs:enumeration value="ContactsActiveDirectory"/>
</xs:restriction>
</xs:simpleType>
我认为NS1:SearchScope=“ActiveDirectoryContacts”不正确,但保留NS1:out会产生相同的错误。可能是将类型和消息的Exchange xmlns规范推迟到SOAP-ENV:Body中是导致错误的原因?
另外,NS1:RequestServerVersion=“Exchange2010”不在SOAP\u ENV:头中 看起来可疑 我已经看过了,但没法让它工作 基本上我的问题是:
如何在生成的代码中移动标记或xmlns属性,直到它工作为止,而不必自己构造整个SOAP?
如果这是不可能的,什么方法是最好的,这样我仍然可以从导入的类型库中获益?(比如?) 谢谢
Jan我决定不尝试修复特定的XML标记,而是完全控制即将发布的SOAP内容:
我只是在TStringStream中构建XML,然后在HTTPRIO.beforecute中,我将TStringStream内容放入SOAPStream中。
安装后,我可以导入WDSL,然后“手动”生成并测试所需的SOAP调用。完成这些后,我将它们移动到Delphi代码中。
这给了我一个优势,即仍然可以访问WDSL生成的代码来解析结果(无需深入研究返回的XML) 这是代码,它显示了旧方法(BtnConnectClick)和新方法(BtnAlternateClick)
unitutestews;
接口
使用
Winapi.Windows、Winapi.Messages、System.SysUtils、System.Variants、System.Classes、Vcl.Graphics、,
Vcl.控件、Vcl.窗体、Vcl.对话框、Vcl.StdCtrls、Vcl.ComCtrls、Vcl.ExtCtrls、TypInfo、WinAPI.WinInet、,
Soap.Rio、Soap.InvokeRegistry、Soap.SOAPHTTPClient、Soap.SOAPHTTPTrans、,
服务{=从WDSL生成的文件};
类型
TFrmTestEWS=类(TForm)
HTTPRIO:THTTPRIO;
小组1:TPanel;
MmoLog:TMemo;
电视:TTreeView;
结果:TMemo;
BTN连接:t按钮;
b可选:t按钮;
备忘录1:TMemo;
标签1:TLabel;
过程httpriobeforecute(const MethodName:string;
SOAPRequest:TStream);
过程HTTPRIOAfterExecute(const MethodName:string;
SOAPResponse:TStream);
过程BtnConnectClick(发送方:TObject);
程序HTTPRIO1HTTPWebNode1BeforePost(常量HTTPReqResp:THTTPReqResp;
数据:指针);
程序BtnAlternateClick(发送方:TObject);
过程表单创建(发送方:ToObject);
销毁程序表(发送方:TObject);
私有的
FSoapData:TStringStream;
程序Res(Msg:String);
程序初始化APDATA;
程序和数据;
公众的
结束;
变量
FrmTestEWS:TFrmTestEWS;
实施
{$R*.dfm}
过程TFrmTestEWS.BtnConnectClick(发送方:TObject);
变量
lESB:ExchangeServicePortType;
lResNames:解析名称;
lReqVersion:RequestServerVersion;
lResResult:ResolveNamesResponse;
lServerVer:ServerVersionInfo;
开始
lServerVer:=ServerVersionInfo.Create;
lResNames:=ResolveNames.Create;
lReqVersion:=RequestServerVersion.Create;
lResResult:=ResolveNamesResponse.Create;
尝试
尝试
// 1. 安装程序
(*替换为alternate,请参见BTNALTernate单击
lunsolved:=“deve”;
有爱尔兰人的名字吗
开始
ReturnFullContactData:=真;
SearchScope:=ResolveNamesSearchScopeType.ActiveDirectoryContacts;//作用域枚举已启用!
ParentFolderId:=nil;
unsolvedEntry:=lUnresolved;
结束;
lReqVersion.Version:=ExchangeVersionType.Exchange2010;
*)
// 2. 执行
lESB:=(HttpIO作为ExchangeServicePortType);
lESB.ResolveNames(lResNames,
无,//模拟
无,//MailboxCulture
lReqVersion,
勒斯雷苏尔,
lServerVer);
// 3. 报告
结果:清晰;
Res('服务器版本:');
用lserverdo
开始
Res('MajorVersion:'+IntToStr(MajorVersion));
Res('MinorVersion:'+IntToStr(MinorVersion));
Res('MajorBuildNumber:'+IntToStr(MajorBuildNumber));
Res('MinorBuildNumber:'+IntToStr(MinorBuildNumber));
Res(‘版本:’+版本);
结束;
//[剪下与本例无关的其余代码]
除了
在E上:异常结果。文本:=E.消息;
结束;
最后
// 4. 清理
lResResult.Free;
lServerVer.Free;
lReqVersion.Free;
lResNames.free;
LESB:=零;
结束;
结束;
过程TFrmTestEWS.FormCreate(发送方:TObject);
开始
FSoapData:=TStringStream.Create(“”,TEncoding.UTF8);
FSoapData.Position:=0;
结束;
程序TFrmTestEWS.FormDestroy(发送方:TObject);
开始
免费的;
结束;
过程TFrmTestEWS.HTTPRIOAfterExecute(const MethodName:string;
SOAPResponse:TStream);
变量
TS:TStringStream;
S:字符串;
开始
S:=MmoLog.Text+#13#10#13#10+'响应:'+#13#10#10;
TS:=TStringStream.Create;
TS.位置:=长度(S);
SOAPResponse.位置:=0;
TS.CopyFrom(SOAPResponse,SOAPResponse.Size);
TS.位置:=0;
MmoLog.Lines.LoadFromStream(TS);
<!-- ResolveNames request -->
<xs:simpleType name="ResolveNamesSearchScopeType">
<xs:restriction base="xs:string">
<xs:enumeration value="ActiveDirectory"/>
<xs:enumeration value="ActiveDirectoryContacts"/>
<xs:enumeration value="Contacts"/>
<xs:enumeration value="ContactsActiveDirectory"/>
</xs:restriction>
</xs:simpleType>
unit uTestEWS;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, Vcl.ExtCtrls,TypInfo, WinAPI.WinInet,
Soap.Rio, Soap.InvokeRegistry, Soap.SOAPHTTPClient, Soap.SOAPHTTPTrans,
services { = The file generated from the WDSL };
type
TFrmTestEWS = class(TForm)
HTTPRIO: THTTPRIO;
Panel1: TPanel;
MmoLog: TMemo;
TV: TTreeView;
MmoResult: TMemo;
BtnConnect: TButton;
BtnAlternate: TButton;
Memo1: TMemo;
Label1: TLabel;
procedure HTTPRIOBeforeExecute(const MethodName: string;
SOAPRequest: TStream);
procedure HTTPRIOAfterExecute(const MethodName: string;
SOAPResponse: TStream);
procedure BtnConnectClick(Sender: TObject);
procedure HTTPRIO1HTTPWebNode1BeforePost(const HTTPReqResp: THTTPReqResp;
Data: Pointer);
procedure BtnAlternateClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FSoapData: TStringStream;
procedure Res(Msg: String);
procedure InitializeSoapData;
procedure FinalizeSoapData;
public
end;
var
FrmTestEWS: TFrmTestEWS;
implementation
{$R *.dfm}
procedure TFrmTestEWS.BtnConnectClick(Sender: TObject);
var
lESB : ExchangeServicePortType;
lResNames : ResolveNames;
lReqVersion : RequestServerVersion;
lResResult : ResolveNamesResponse;
lServerVer : ServerVersionInfo;
begin
lServerVer := ServerVersionInfo.Create;
lResNames := ResolveNames.Create;
lReqVersion := RequestServerVersion.Create;
lResResult := ResolveNamesResponse.Create;
try
try
// 1. Setup
(* Replaced by alternate, see BtnAlternateClick
lUnresolved := 'deve';
with lResNames do
begin
ReturnFullContactData := true;
SearchScope := ResolveNamesSearchScopeType.ActiveDirectoryContacts; // Scoped enums is on!
ParentFolderIds := nil;
UnresolvedEntry := lUnresolved;
end;
lReqVersion.Version := ExchangeVersionType.Exchange2010;
*)
// 2. Execute
lESB := (HTTPRIO as ExchangeServicePortType);
lESB.ResolveNames(lResNames,
nil, // Impersonation
nil, // MailboxCulture
lReqVersion,
lResResult,
lServerVer);
// 3. Report
MmoResult.Clear;
Res('Server version:');
with lServerVer do
begin
Res(' MajorVersion: ' + IntToStr(MajorVersion));
Res(' MinorVersion: ' + IntToStr(MinorVersion));
Res(' MajorBuildNumber: ' + IntToStr(MajorBuildNumber));
Res(' MinorBuildNumber: ' + IntToStr(MinorBuildNumber));
Res(' Version: ' + Version);
end;
// [ snip rest of code not relevant for this example]
except
on E:Exception do MmoResult.Text := E.Message;
end;
finally
// 4. Clean up
lResResult.Free;
lServerVer.Free;
lReqVersion.Free;
lResNames.free;
LESB := nil;
end;
end;
procedure TFrmTestEWS.FormCreate(Sender: TObject);
begin
FSoapData := TStringStream.Create('',TEncoding.UTF8);
FSoapData.Position := 0;
end;
procedure TFrmTestEWS.FormDestroy(Sender: TObject);
begin
FSoapData.Free;
end;
procedure TFrmTestEWS.HTTPRIOAfterExecute(const MethodName: string;
SOAPResponse: TStream);
var
TS: TStringStream;
S : String;
begin
S := MmoLog.Text + #13#10#13#10 + 'Response:' + #13#10#13#10;
TS := TStringStream.Create(S);
TS.Position := Length(S);
SOAPResponse.Position := 0;
TS.CopyFrom(SOAPResponse,SOAPResponse.Size);
TS.Position := 0;
MmoLog.Lines.LoadFromStream(TS);
TS.Free;
end;
procedure TFrmTestEWS.HTTPRIOBeforeExecute(const MethodName: string;
SOAPRequest: TStream);
begin
// 1. Alternate approach
SOAPRequest.Position := 0;
FSoapData.Position := 0;
SOAPRequest.CopyFrom(FSoapData,FSoapData.Size);
SOAPRequest.Size := FSoapData.Size;
// 2. Logging
MmoLog.Clear;
MmoLog.Lines.Add('Request:' + #13#10#13#10);
FSoapData.Position := 0;
MmoLog.Lines.LoadFromStream(FSoapData);
end;
procedure TFrmTestEWS.InitializeSoapData;
begin
FSoapData.Clear;
FSoapData.WriteString('<soapenv:Envelope');
FSoapData.WriteString(' xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"');
FSoapData.WriteString(' xmlns:typ="http://schemas.microsoft.com/exchange/services/2006/types"');
FSoapData.WriteString(' xmlns:mes="http://schemas.microsoft.com/exchange/services/2006/messages">');
FSoapData.WriteString('<soapenv:Header><typ:RequestServerVersion Version="Exchange2010"/></soapenv:Header>');
FSoapData.WriteString('<soapenv:Body>');
end;
procedure TFrmTestEWS.FinalizeSoapData;
begin
FSoapData.WriteString('</soapenv:Body>');
FSoapData.WriteString('</soapenv:Envelope>');
end;
procedure TFrmTestEWS.BtnAlternateClick(Sender: TObject);
begin
InitializeSoapData;
FSoapData.WriteString(' <mes:ResolveNames ReturnFullContactData="1" SearchScope="ActiveDirectoryContacts">');
FSoapData.WriteString(' <mes:UnresolvedEntry>deve</mes:UnresolvedEntry>');
FSoapData.WriteString(' </mes:ResolveNames>');
FinalizeSoapData;
// Pick up from first attempt 'execute':
BtnConnectClick(Sender);
end;
procedure TFrmTestEWS.HTTPRIO1HTTPWebNode1BeforePost(
const HTTPReqResp: THTTPReqResp; Data: Pointer);
const
CONTENT_HEADER_EX2010 = 'Content-Type: text/xml; charset=utf-8';
begin
// http://forum.delphi-treff.de/archive/index.php/t-31817.html
// Need to exchange the Content-Type Header, because Exchange 2010 expects
// 'Content-Type: text/xml; charset=utf-8' instead of
// 'Content-Type: text/xml; charset="utf-8"' which is RFC conform and used by XE2
HttpAddRequestHeaders(Data, PChar(CONTENT_HEADER_EX2010), Length(CONTENT_HEADER_EX2010), HTTP_ADDREQ_FLAG_REPLACE);
end;
procedure TFrmTestEWS.Res(Msg: String);
begin
MmoResult.Lines.Add(Msg);
end;
end.