Как использовать svcutil для создания прокси C # WCF из веб-службы, которая использует ограничения для скрытия элементов? - PullRequest
5 голосов
/ 22 октября 2011

Я создаю клиента для веб-службы, который более или менее находится вне моего контроля.Вот упрощенный образец схемы:

<xs:complexType name="A">
    <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="1" name="element1" type="xs:string" />
        <xs:element minOccurs="0" maxOccurs="1" name="element2" type="xs:string" />
    </xs:sequence>
</xs:complexType>

<xs:complexType name="B">
    <xs:complexContent>
        <xs:restriction base="A">
            <xs:sequence>
                <xs:element minOccurs="1" maxOccurs="1" name="element2" type="xs:string" />
            </xs:sequence>
        </xs:restriction>
    </xs:complexContent>
</xs:complexType>

Короче говоря, у нас есть объект A, который содержит все элементы.Служба имеет несколько типов, основанных на A, но с ограничениями, так что унаследованные типы обычно меньше базового типа - здесь показано типом B.

В средствах просмотра схемы, таких как в Visual Studio 2010, SoapUI,и т.д. это выглядит как ожидалось.A имеет 2 элемента, а B только 1 (= элемент 2).

Используя svcutil, я получаю полный набор элементов в обоих типах A и B, или когда я играю с опциями, я получаю сообщения об ошибках, такие как:

Ошибка: тип 'B' в пространстве имен 'http://tempuri.org/XMLSchema.xsd' не может быть импортирован.Сложные типы, полученные по ограничениям, не поддерживаются.Либо измените схему, чтобы типы могли сопоставляться с типами контрактов данных, либо используйте ImportXmlType, либо используйте другой сериализатор.

Скрытие полей / свойств в унаследованных типах - это не практика / дорога, которую я люблю путешествовать, ноесли я не могу заставить провайдера изменить WSDL, мне кажется, я должен сделать это таким образом.

Есть ли альтернативы svcutil, которые обрабатывают это правильно, или я должен вручную кодировать свои прокси?


Обновление 1

Как указал Джон Сондерс, я не показал результаты предложений svcutil.Это было отчасти для того, чтобы пост был коротким ... но вот так:

svcutil schema.xsd / importXmlTypes / datacontractonly приводит к:

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="A", Namespace="http://tempuri.org/XMLSchema.xsd")]
public partial class A : object, System.Runtime.Serialization.IExtensibleDataObject
{

    private System.Runtime.Serialization.ExtensionDataObject extensionDataField;

    private string element1Field;

    private string element2Field;

    public System.Runtime.Serialization.ExtensionDataObject ExtensionData
    {
        get
        {
            return this.extensionDataField;
        }
        set
        {
            this.extensionDataField = value;
        }
    }

    [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false)]
    public string element1
    {
        get
        {
            return this.element1Field;
        }
        set
        {
            this.element1Field = value;
        }
    }

    [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false)]
    public string element2
    {
        get
        {
            return this.element2Field;
        }
        set
        {
            this.element2Field = value;
        }
    }
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Xml.Serialization.XmlSchemaProviderAttribute("ExportSchema")]
[System.Xml.Serialization.XmlRootAttribute(IsNullable=false)]

public partial class B : object, System.Xml.Serialization.IXmlSerializable
{

    private System.Xml.XmlNode[] nodesField;

    private static System.Xml.XmlQualifiedName typeName = new System.Xml.XmlQualifiedName("B", "http://tempuri.org/XMLSchema.xsd");

    public System.Xml.XmlNode[] Nodes
    {
        get
        {
            return this.nodesField;
        }
        set
        {
            this.nodesField = value;
        }
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        this.nodesField = System.Runtime.Serialization.XmlSerializableServices.ReadNodes(reader);
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        System.Runtime.Serialization.XmlSerializableServices.WriteNodes(writer, this.Nodes);
    }

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public static System.Xml.XmlQualifiedName ExportSchema(System.Xml.Schema.XmlSchemaSet schemas)
    {
        System.Runtime.Serialization.XmlSerializableServices.AddDefaultSchema(schemas, typeName);
        return typeName;
    }
}

Работа надУровень XML не желателен и заставил бы нас написать обертку.Проще написать код прокси-сервера из getgo.

svcutil schema.xsd / serializer: XmlSerializer / datacontractonly Приводит ошибку ниже и является причиной, по которой я запрашиваю альтернативные инструменты.

svcutil schema.xsd / serializer: XmlSerializer / datacontractonly Ошибка: тип B в пространстве имен http://tempuri.org/XMLSchema.xsd' не может быть импортирован.Сложные типы, полученные по ограничениям, не поддерживаются.Измените схему, чтобы типы могли сопоставляться с типами контрактов данных, или используйте ImportXmlType, или используйте другой сериализатор.

Если вы используете параметр / dataContractOnly для импорта типов контрактов данных и получаете это сообщение об ошибке, рассмотрите возможностьиспользуя вместо этого xsd.exe.Типы, созданные xsd.exe, могут использоваться в Windows Communication Foundation после применения атрибута XmlSerializerFormatAttribute в контракте на обслуживание.В качестве альтернативы рассмотрите возможность использования параметра / importXmlTypes для импорта этих типов как типов XML для использования с атрибутом DataContractFormatAttribute в контракте на обслуживание.

Использование xsd schema.xsd / c дает типB, который наследует A без скрытия element1:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/XMLSchema.xsd")]
[System.Xml.Serialization.XmlRootAttribute("request", Namespace="http://tempuri.org/XMLSchema.xsd", IsNullable=false)]
public partial class B : A {
}

/// <remarks/>
[System.Xml.Serialization.XmlIncludeAttribute(typeof(B))]
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/XMLSchema.xsd")]
public partial class A {

    private string element1Field;

    private string element2Field;

    /// <remarks/>
    public string element1 {
        get {
            return this.element1Field;
        }
        set {
            this.element1Field = value;
        }
    }

    /// <remarks/>
    public string element2 {
        get {
            return this.element2Field;
        }
        set {
            this.element2Field = value;
        }
    }
}

1 Ответ

0 голосов
/ 22 октября 2011

В сообщении об ошибке указывается либо использовать переключатель /importXmlTypes, либо перейти на использование XmlSerializer. Из справки:

/ importXmlTypes - настроить контракт данных сериализатор для импорта типов не-Data Contract как IXmlSerializable типы.

и

/ serializer: XmlSerializer - генерирует типы данных, которые используют XmlSerializer для сериализации и десериализации

...