В прошлом я создавал Web-сервисы с Delphi, но большинство из них были довольно простыми, просто принимали несколько параметров и возвращали одно значение клиенту. Новая услуга, над которой я работаю, требует, чтобы я мог отправлять и получать сложные типы. Учтите, что в моем коде определены следующие типы:
TBaseRequest = Class(TRemotable)
private
FUsername: string;
FPassword: string;
published
Property Username: String read FUsername write FUsername;
Property Password: String read FPassword write FPassword;
End;
TBaseResponse = Class(TRemotable)
private
FStatusMessage: string;
FStatusCode: integer;
published
Property StatusMessage: string read FStatusMessage write FStatusMessage;
Property StatusCode: integer read FStatusCode write FStatusCode;
End;
TSepecialRequest = class(TBaseRequest)
private
FExtraParam: string;
published
Property ExtraParam: String read FExtraParam write FExtraParam;
end;
TSpecialResponse = class(TBaseResponse)
private
FExtraResult: string;
published
Property ExtraResult: String read FExtraResultwrite FExtraResult;
end;
Все эти классы зарегистрированы в RemClassRegistry.RegisterXSClass.
Теперь у меня также есть следующая функция, определенная в интерфейсе для этого веб-сервиса:
function SpecialMethod(request:TSepecialRequest): TSpecialResponse;
В сервисном коде я могу легко получить доступ к свойствам родительского класса, таким как Имя пользователя и Пароль, но если мы посмотрим на сгенерированный WSDL, то увидим, что члены класса TSpecialRequest и TSpecialResponse включены в раздел схемы.
<xs:complexType name="TSpecialRequest">
<xs:complexContent>
<xs:extension base="TBaseRequest">
<xs:sequence>
<xs:element name="ExtraParam" type="xs:string"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="TSpecialResponse">
<xs:complexContent>
<xs:extension base="TBaseResponse">
<xs:sequence>
<xs:element name="ExtraResult" type="xs:string"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
Этот фрагмент схемы в WSDL показывает, что TSpecials являются расширениями классов TBase, и все хорошо, за исключением того, что описание схемы TBase не включено в схему. Я ожидаю, что также будет такой раздел, но он отсутствует:
<xs:complexType name="TBaseRequest">
<xs:sequence>
<xs:element name="Username" type="xs:string"/>
<xs:element name="Password" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="TBaseResponse">
<xs:sequence>
<xs:element name="StatusMessage" type="xs:string"/>
<xs:element name="StatusCode" type="xs:int"/>
</xs:sequence>
</xs:complexType>
Однако этот фрагмент схемы отсутствует в сгенерированном WSDL. Это означает, что любой клиент, пытающийся использовать эту службу, не сможет правильно генерировать запросы или интерпретировать ответы. Например, если я попытаюсь загрузить сгенерированный WSDL в импортер WSDL в Delphi 2009, я получу следующие классы:
TSpecialRequest = class(TRemotable)
private
FExtraParam: WideString;
published
property ExtraParam: WideString read FExtraParam write FExtraParam;
end;
TSpecialResponse = class(TRemotable)
private
FStatusMessage: WideString;
FStatusCode: Integer;
published
property StatusMessag: WideString read FStatusMessage write FStatusMessage;
property StatusCode: Integer read FStatusCode write FStatusCode;
end;
В результате клиентский код не может выполнять такие действия, как установка имени пользователя и пароля, которые должны быть частью TSpecialRequest.
Кто-нибудь знает, почему это происходит или что я могу с этим сделать?