processContents =“ lax”を回避する方法IXmlSerializableを実装するクラスからのWCF WSDLで?
-
06-07-2019 - |
質問
wcfサービスは、コントラクトファースト形式で記述されています。スキーマの一部の要素は属性を使用するため、このためにカスタムシリアル化を作成する必要がありました( IXmlSerializable
を使用)。以下は、スキーマのスニペット、クラス、およびwsdl出力のスキーマです。
問題は、IXmlSerializableクラスのxsdをレンダリングしても、スキーマが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"/>
解決
GetSchemaFileメソッドからXmlSchemaComplexTypeを返していますが、XmlSchemaProviderAttributeのメソッドのコントラクトでは、XmlQualifiedNameを返す必要があります。 XmlSchemaProviderAttribute のMSDNドキュメントの備考セクションからa>:
MethodNameプロパティは、リフレクションを通じて静的メソッドの名前を返します。実装する必要のあるメソッドは、XmlSchemaSetオブジェクトという単一のパラメーターを取る必要があります。このパラメーターには、XmlSchemaオブジェクトが設定されます。メソッドは、データ型を識別するXmlQualifiedNameオブジェクトも返す必要があります。
この理由は簡単です。スキーマ内にいくつかの型があると想像してください。それが反映しているクラスがどの型を表しているかをどのように知るのでしょうか?そのため、XmlQualifiedNameを返すことにより、このクラスはこのスキーマのこの型にマップされると実際に言っています。