2010-06-04 1 views
1

필자는 과거에 델파이로 웹 서비스를 만들었지 만, 대부분 매개 변수를 사용하여 클라이언트에 단일 값을 반환하는 매우 간단했다. 새로운 서비스로는 복잡한 유형의 송수신이 가능합니다. 다음과 같은 유형이 내 코드에 정의되어 고려 : TRemotable Descendant 델파이 웹 서비스에 의해 생성 된 WSDL에는 부모 멤버가 포함되어 있지 않다.

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 클래스의 ENT 버튼을 누르면 DVR이 스키마에 포함되지 않은 것을 제외하고 잘 보여줍니다. 이와 같은 섹션도있을 것으로 예상되지만 누락되었습니다.

<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에서 누락되었습니다. 즉,이 서비스를 사용하려는 클라이언트는 요청을 올바르게 생성하거나 응답을 해석 할 수 없습니다. 예를 들어, 델파이 2009 년 WSDL의 수입에 geneated WSDL을로드하려고하면, 나는 다음과 같은 클래스를 얻을 :

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에 속해야하는 멤버.

누구에게 이런 일이 일어나는 지 또는 내가 그것에 대해 무엇을 할 수 있는지 실마리가 있습니까?

+0

어떻게 Delphi IDE를 사용하여 Delphi 클래스 소스 코드에서 WSDL을 만들 수 있습니까? 지금까지 델파이 2009 엔터 프라이즈 (어쩌면 나는 그것을 새로운 질문해야 만들어진 방법을 못 봤어 :) – mjn

+0

그 오프 주제와 새로운 질문이어야하지만, 기본적으로 SOAP 서버 응용 프로그램 프로젝트를 만들 때 TWSDLHTMLPublish 구성 요소가있는 데이터 모듈을 추가합니다. 이 구성 요소는 등록 된 인터페이스와 원격 가능 클래스를 거쳐 추가로 WSDL을 생성합니다. WSDL에 액세스하려면 프로젝트의 컴파일 된 DLL을 ISAPI 웹 서버 (예 : IIS)에로드 한 다음 http://server.com/project.dll과 같은 URL을 사용하여 서비스를 설명하는 HTML 페이지와 생성 된 WSDL에 대한 링크. 결과 : 델파이 코드에 정의 된 클래스에 기반한 WSDL. –

답변

1

나는 대답을 얻지 못할 것이라고 생각하지만 해결 방법을 찾았습니다. 나는 그걸로 만족하지는 못했지만 문제를 넘겼습니다. 위에서 설명한 현상은 상속 대신 Object Composition을 사용하여 피할 수 있습니다. 이 코드는 예상대로 작동하지만 사용하기가 쉽지 않습니다. 나는 내 구현에 어떤 종류의 메시지 공장을 생각해 내고 싶지만 주제를 벗어나고 싶다.

이 솔루션

는 다음 코드에 의해 설명 될 수있다 :

TBaseRequest = Class(TRemotable) 
    private 
    FUsername: string; 
    FPassword: string; 
    published 
    Property Username: String read FUsername write FUsername; 
    Property Password: String read FPassword write FPassword; 
end; 

TSepecialRequest = class(TRemotable) 
private 
    FExtraParam: string; 
    FBaseRequest: TBaseRequest; 
published 
    Property ExtraParam: String read FExtraParam write FExtraParam; 
    Property BaseRequest: TBaseRequest read FBaseRequest write FBaseRequest; 
end; 
1

델파이는 직접 웹 서비스의 인터페이스에서 참조하는 클래스에 대한 스키마를 생성합니다. 이상적으로 TRemotable에 기본 클래스를 포함해야하지만 그렇지 않습니다.

매개 변수 목록에 기본 클래스가있는 인터페이스에 더미 메서드를 추가하면 Delphi가 누락 된 정의를 생성합니다. 예를 들어 :

procedure BaseClasses(BaseRequest: TBaseRequest; BaseResponse: TBaseResponse); stdcall; 

이것은 확실히 해킹이며,이 같은 방법을 노출해야하는 성가신 조금,하지만 당신이 완료 원하는 것을 달성 않습니다.

나는이 반응이 약간 늦다는 것을 알고 있지만 길 아래 다른 누군가에게 유용 할 수 있습니다.

관련 문제