Как избежать processContents = & # 8220; lax & # 8221; в WCF WSDL из классов, реализующих IXmlSerializable?
-
06-07-2019 - |
Вопрос
У меня есть служба wcf, написанная по контракту. Поскольку некоторые элементы в схеме используют атрибуты, мне пришлось создать для этого настраиваемую сериализацию (используя IXmlSerializable
). Ниже приведен фрагмент схемы и классов, а также схемы из вывода wsdl.
Моя проблема в том, что, хотя я отображаю xsd для своих классов IXmlSerializable, схема не включается в wsdl. На них просто ссылается processContents = " lax "
. Это кажется проблемой для потребителей моих услуг, поскольку они не могут использовать свои мастера для создания клиентов.
Кто-нибудь сталкивался с этой проблемой? В любом случае, чтобы контролировать вывод wsdl, чтобы избежать этого. Я испытываю одинаковое поведение при использовании как контрактов сообщений, так и контрактов данных.
Схема для коллекции и элемента:
<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>
Класс коллекции:
[CollectionDataContract(ItemName = "Telephone", Name = "TelephoneList", Namespace = Schema.WorkOrderNamespace)]
public class TelephoneSet : SetBase<Telephone>
{ }
Класс товара:
[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);
}
}
}
XSD, предоставляемый службой:
<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"/>
Решение
Вы возвращаете XmlSchemaComplexType из вашего метода GetSchemaFile, но контракт метода для XmlSchemaProviderAttribute требует, чтобы вы возвращали XmlQualifiedName. Из раздела примечаний документации MSDN для XmlSchemaProviderAttribute а>:
Свойство MethodName возвращает имя статического метода через отражение. Метод, который должен быть реализован, должен принимать один параметр - объект XmlSchemaSet, который метод заполняет объектом XmlSchema. Метод также должен возвращать объект XmlQualifiedName, который идентифицирует тип данных.
Причина этого проста: представьте, что у вас есть несколько типов в вашей схеме, как она узнает, какой класс представляет отражаемый класс? Таким образом, возвращая XmlQualifiedName, вы фактически говорите, что этот класс соответствует этому типу в этой схеме.