Search code examples
delphisoapwsdl

TWSDLHTMLPublish generates wrong wsdl?


i'm using Delphi 10.4.2 and i'm writing an SOAP Server Application. For gerating the WSDL i'm using an TWSDLHTMLPublish Component dropped on my TWebModule Descendant. I got Problems exposing Attributes and Optional Elements into the wsdl file.

My Interface defines Objects like this:

// TRemotable Property Index constants.
// Quelle: http://www.codenewsfast.com/cnf/article/0/permalink.art-ng1920q2865
const
  IS_OPTN = $0001;   // This element is optional (minOccurs=0); Don't serialize it if its value was not explicitly set
  IS_UNBD = $0002;   // This array element is unbounded (The runtime serializes dyn arrays as either collection or unbounded elements)
  IS_NLBL = $0004;   // This element is nillable (xsi:nillable=true)
  IS_UNQL = $0008;   // This element is unqualified (see http://www.w3schools.com/schema/el_schema.asp) Runtime defaults to qualified otherwise
  IS_ATTR = $0010;   // This property is an attribute (otherwise the runtime serializes it as an element)
  IS_TEXT = $0020;   // This property is text (typically of the parent element) (see http://www.w3schools.com/schema/schema_complex_text.asp)
  IS_ANY  = $0040;   // This property represents an xsd:any element (not really used by runtime)
  IS_REF  = $0080;   // This property is a ref (i.e. ref=QName) element (see http://www.w3schools.com/schema/el_element.asp)
  IS_QUAL = $0100;   // This attribute is qualified (the runtime defaults to unqualified otherwise)

type
  OrderDirection    = (OrderNONE, OrderASC, OrderDESC);
  ProjektOrderField = (pofNONE, pofID, pofNummer, pofStatus);
  ProjektStatus     = (psAll, psAnfrage, psAuftrag, psAbgeschlossen);

ProjektFilterType = class(TRemotable)
  private
    FStatus               : ProjektStatus;
    FStatus_specified     : Boolean;
    FOrderField           : ProjektOrderField;
    FOrderField_specified : Boolean;
    FOrderDir             : OrderDirection;
    FOrderDir_specified   : Boolean;
    FTestAttribut         : string;
    Procedure SetStatus          (Index: Integer; const Value: ProjektStatus);
    Procedure SetOrderDir        (Index: Integer; const Value: OrderDirection);
    Procedure SetOrderField      (Index: Integer; const Value: ProjektOrderField);
  public
    Function Status_Specified    (Index: Integer) : Boolean;
    Function OrderDir_Specified  (Index: Integer) : Boolean;
    Function OrderField_Specified(Index: Integer) : Boolean;
  published
    property TestAttribut : string             Index (IS_UNQL OR IS_ATTR)  read FTestAttribut  write FTestAttribut;
    property Status       : ProjektStatus      Index (IS_UNQL OR IS_OPTN)  read FStatus        write SetStatus       stored Status_specified;
    property OrderField   : ProjektOrderField  Index (IS_UNQL OR IS_OPTN)  read FOrderField    write SetOrderField   stored OrderField_specified;
    property OrderDir     : OrderDirection     Index (IS_UNQL OR IS_OPTN)  read FOrderDir      write SetOrderDir     stored OrderDir_specified;
  end;
// ================================================================================
{$REGION '   ==================== ProjektFilterType ===================='}
Function ProjektFilterType.Status_Specified(Index: Integer) : Boolean;
begin
  Result := FStatus_Specified;
end;

Function ProjektFilterType.OrderDir_Specified(Index: Integer) : Boolean;
begin
  Result := FOrderDir_Specified;
end;

Function ProjektFilterType.OrderField_Specified(Index: Integer) : Boolean;
begin
  Result := FOrderField_Specified;
end;

Procedure ProjektFilterType.SetStatus(Index: Integer; const Value: ProjektStatus);
begin
  FStatus           := Value;
  FStatus_Specified := true;
end;

Procedure ProjektFilterType.SetOrderDir(Index: Integer; const Value: OrderDirection);
begin
  FOrderDir           := Value;
  FOrderDir_Specified := true;
end;

Procedure ProjektFilterType.SetOrderField(Index: Integer; const Value: ProjektOrderField);
begin
  FOrderField           := Value;
  FOrderField_Specified := true;
end;
{$ENDREGION}
// ================================================================================

the output wsdl file looks like this:

<xs:complexType name="ProjektFilterType">
  <sequence xmlns="http://www.w3.org/2001/XMLSchema">
    <xs:element name="TestAttribut" type="xs:string"/>
    <xs:element name="Status" type="ns1:ProjektStatus"/>
    <xs:element name="OrderField" type="ns1:ProjektOrderField"/>
    <xs:element name="OrderDir" type="ns1:OrderDirection"/>
  </sequence>
</xs:complexType>

Problem: IS_ATTR ist not working at all - output is xs:element instead of xs.attribute and the elements are missing the MinOccurs="0" and MaxOccurs="1" attributes.

what i'm doing wrong? Any RTTI Attributes i have to define other than the Property-Index?


Solution

  • Ok, I've found this in the Embarcaqdero sources:

    NOTE: Currently Serialization options are only for Client usage. i.e. They are used by the WSDL importer when creating types from a WSDL. Servers should NOT register any types with these options as the WSDL publishing logic will ignore all serialization options. IOW, these flags are here to adapt the language binding to constructs that don't easily map to a native type - like the example of an array with an attribute. Servers, don't need to resort to any of these flags since all of a server's needs can be mapped to SOAP without use of holder classes.

    So I will generate my wdsl by hand and use the wsdl-importer for generating the interface unit. I hoped there would be an easier way (for me :-)) but I can live with this...