Como evitar processContents = “negligente” em WCF WSDL de classes que implementam IXmlSerializable?

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

  •  06-07-2019
  •  | 
  •  

Pergunta

Eu tenho um serviço WCF escrito de uma forma contrato de primeira. Como alguns dos elementos nos atributos usos de esquema, eu tive que criar uma serialização personalizada para isso (usando IXmlSerializable). Abaixo está um trecho do esquema, e as classes, bem como o esquema a partir da saída wsdl.

O meu problema é que mesmo que eu tornar o xsd para minhas aulas IXmlSerializable, o esquema não está incluído no WSDL. Eles estão apenas referenciada com processContents="lax". Este parece ser um problema para os consumidores de meus serviços, como eles não podem usar seus assistentes para criar clientes.

Alguém já encontrou este problema? Existe uma maneira de controlar a saída wsdl para evitar isso. I experimentar o mesmo comportamento usando ambos os contratos de mensagens e contratos de dados.

O esquema de coleta e artigo:

<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>

A classe de coleção:

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

A classe de item:

    [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);
            }
        }
    }

O xsd proferida pelo serviço:

<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"/>
Foi útil?

Solução

Você está retornando um XmlSchemaComplexType do seu método GetSchemaFile, mas o contrato do método para ditames XmlSchemaProviderAttribute que você deve retornar XmlQualifiedName. Na seção observações da documentação MSDN para XmlSchemaProviderAttribute :

A propriedade MethodName retorna o nome de um método estático através da reflexão. O método, que deve ser implementado, deve tomar um único parâmetro, um objeto XmlSchemaSet, que as povoa método com um objeto XmlSchema. O método também deve retornar um objeto XmlQualifiedName que identifica o tipo de dados.

A razão para isso é simples: imagine que você tinha vários tipos dentro do seu esquema, como seria saber qual a classe está refletindo representa? Então, retornando um XmlQualifiedName você está realmente dizendo isso mapas de classe a este tipo neste esquema.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top