Come evitare processContents = "lax" in WCF WSDL dalle classi che implementano IXmlSerializable?

StackOverflow https://stackoverflow.com/questions/1619448

  •  06-07-2019
  •  | 
  •  

Domanda

Ho un servizio di wcf scritto in modo contrattuale. Poiché alcuni degli elementi nello schema utilizzano attributi, ho dovuto creare una serializzazione personalizzata per questo (utilizzando IXmlSerializable ). Di seguito è riportato un frammento dello schema e delle classi, nonché dello schema dall'output wsdl.

Il mio problema è che anche se eseguo il rendering di xsd per le mie classi IXmlSerializable, lo schema non è incluso in wsdl. Sono appena referenziati con processContents = " lax " . Questo sembra essere un problema per i consumatori dei miei servizi, in quanto non possono usare i loro maghi per creare clienti.

Qualcuno ha riscontrato questo problema? C'è comunque modo di controllare l'output di wsdl per evitarlo. Provo lo stesso comportamento utilizzando sia i contratti di messaggistica sia i contratti di dati.

Lo schema per la raccolta e l'elemento:

<xs:element name="TelephoneList">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="Telephone" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="Telephone">
        <xs:complexType>
            <xs:simpleContent>
                <xs:extension base="xs:string">
                    <xs:attribute name="Type">
                        <xs:simpleType>
                            <xs:restriction base="xs:NMTOKEN">
                                <xs:enumeration value="Preferred"/>
                                <xs:enumeration value="Office"/>
                                <xs:enumeration value="Mobile"/>
                                <xs:enumeration value="Home"/>
                                <xs:enumeration value="MobilePhoneFromExternalPartner"/>
                                <xs:enumeration value="HomePhoneFromExternalPartner"/>
                            </xs:restriction>
                        </xs:simpleType>
                    </xs:attribute>
                </xs:extension>
            </xs:simpleContent>
        </xs:complexType>
      </xs:element>

La classe di raccolta:

[CollectionDataContract(ItemName = "Telephone", Name = "TelephoneList", Namespace = Schema.WorkOrderNamespace)]
public class TelephoneSet : SetBase<Telephone>
{    }

La classe di elementi:

    [XmlSchemaProvider("GetSchemaFile")]
    public class Telephone : CustomSerializedEntity //The base class implements IXmlSerializable
    {
        public virtual TelephoneType? Type { get; set; }
        public virtual string Number { get; set; }

        /// <remarks>This method is referenced in the <seealso cref="XmlSchemaProviderAttribute"/> decoration.</remarks>
        public static XmlSchemaComplexType GetSchemaFile(XmlSchemaSet xs)
        {
            return CreateSchema(xs, "Telephone");
        }

        public override void ReadXml(XmlReader reader)
        {
            Type = ReadEnumAttribute<TelephoneType?>(reader, "Type");
            reader.MoveToElement();
            Number = reader.Value;
        }

        public override void WriteXml(XmlWriter writer)
        {
            WriteAttribute(writer, "Type", Type);
            if (!string.IsNullOrEmpty(Number))
            {
                writer.WriteValue(Number);
            }
        }
    }

La xsd renderizzata dal servizio:

<xs:complexType name="TelephoneList">
      <xs:sequence>
         <xs:element minOccurs="0" maxOccurs="unbounded" name="Telephone" nillable="true">
            <xs:complexType>
               <xs:sequence>
                  <xs:any minOccurs="0" processContents="lax"/>
               </xs:sequence>
            </xs:complexType>
         </xs:element>
      </xs:sequence>
   </xs:complexType>
   <xs:element name="TelephoneList" nillable="true" type="tns:TelephoneList"/>
È stato utile?

Soluzione

Stai restituendo un XmlSchemaComplexType dal tuo metodo GetSchemaFile, ma il contratto del metodo per XmlSchemaProviderAttribute impone che devi restituire XmlQualifiedName. Dalla sezione osservazioni della documentazione MSDN per XmlSchemaProviderAttribute :

  

La proprietà MethodName restituisce il nome di un metodo statico tramite reflection. Il metodo, che deve essere implementato, deve accettare un singolo parametro, un oggetto XmlSchemaSet, che il metodo popola con un oggetto XmlSchema. Il metodo deve inoltre restituire un oggetto XmlQualifiedName che identifica il tipo di dati.

Il motivo è semplice: immagina di avere diversi tipi nel tuo schema, come potrebbe sapere quale rappresenta la classe che sta riflettendo? Quindi restituendo un XmlQualifiedName stai effettivamente dicendo che questa classe è mappata a questo tipo in questo schema.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top