Вопрос

У меня есть контракт службы, который определяет метод с параметром типа System.Object (xs:anyType в WSDL).Я хочу иметь возможность передавать в этом параметре как простые, так и сложные типы.Простые типы работают нормально, но когда я пытаюсь передать сложный тип, определенный в моем WSDL, я получаю следующую ошибку:

Элемент 'http://tempuri.org/:значение'содержит данные 'http://schemas.datacontract.org/2004/07/MyNamespace:MyClass'контракт данных.Десериализатор не знает ни одного типа, который соответствует этому контракту.Добавьте тип, соответствующий «MyClass», в список известных типов, например, используя атрибут KnownTypeAttribute или добавив его в список известных типов, переданных в DataContractSerializer.

Добавление его как известного типа не помогает, поскольку он уже есть в моем WSDL.Как передать объект сложного типа через параметр «xs:anyType»?

Больше информации:

Я считаю, что это работает при использовании NetDataContract, но я не могу это использовать, поскольку мой клиент — Silverlight.

Я видел ссылки на сложные типы, явно расширяющие xs:anyType, но понятия не имею, как заставить WCF генерировать WSDL, который делает это, и понятия не имею, поможет ли это вообще.

Спасибо

Это было полезно?

Решение 3

Я решил эту проблему, используя атрибут ServiceKnownType.Я просто добавляю свой сложный тип в качестве известного типа службы в свой контракт службы, и ошибка исчезает.Я не уверен, почему это не сработало, когда я пробовал это в прошлый раз.

Похоже, это никак не влияет на WSDL, поэтому я подозреваю, что сериализованный поток должен иметь некоторую разницу, сообщающую десериализатору, что объект может быть десериализован с использованием моего типа.

Другие советы

NetDataContract работает, поскольку NetDataContractSerializer включает информацию о типе.

Атрибут KnownType указывает DataContractSerializer, как десериализовать сообщение.Поскольку эта информация зависит от реализации, это дополнительная информация, определенная в публичном контракте и не принадлежащая WSDL.

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

Возможно, вы сможете получить известные типы во время выполнения, а не жестко запрограммировать их в DataContract.Взглянем здесь для образца.

Я надеюсь, что это поможет.Я видел, как мой коллега использовал этот код для отправки сложных типов данных, и для меня это довольно просто.Это использовалось с BasicHttpBinding и очень хорошо работает с MOSS BDC, а также с другими приложениями, использующими базовую привязку.

  1. Создайте контракт данных на основе универсального класса.
  2. Используйте контракт данных, когда информацию необходимо отправить.

    [DataContract(Пространство имен = "http://Service.DataContracts", Name =" ServiceAtacontractBase ")] открытый класс ServiceAtacontract {

    public ServiceDataContract() { }
    
    public ServiceDataContract(TValueType Value)
    {
        this.m_objValue = Value;
    }
    
    private TValueType m_objValue;
    
    [DataMember(IsRequired = true, Name = "Value", Order = 1)]
    public TValueType Value
    {
        get { return m_objValue; }
        set { m_objValue = value; }
    }
    

    }

Используйте этот контракт данных везде, где это необходимо, в функциях WCF, возвращающих сложный тип данных.Например:

public ServiceDataContract<string[]> GetStrings()
{
    string[] temp = new string[10];
    return new ServiceDataContract<string[]>(temp);
}

Обновлять:ServiceDataContract — это универсальный класс, использующий TValueType.Он не отображается из-за проблем с рендерингом HTML.

Попробуйте использовать суррогаты контракта данных для сопоставления неподдерживаемых объектов, специфичных для точечной сети или несовместимых типов.Видеть MSDN

На данный момент я решил эту проблему, создав новый тип контракта данных, который может обертывать либо другой тип контракта данных, либо простой тип.Вместо передачи типа Object теперь я передаю этот класс-оболочку.Это работает нормально, но мне все равно хотелось бы знать, есть ли решение исходной проблемы.

Я попытался добавить атрибут ServiceKnownType, указав тип, который пытаюсь передать, но все равно получаю ту же ошибку. Я также попытался добавить атрибут KnownType в свой контракт данных (что казалось глупым, поскольку он был того же типа, что и контракт данных).Я предполагаю, что добавление их во время выполнения не поможет, если добавление их во время компиляции не поможет.

Если бы я расширял другой сложный тип, мне кажется, что я бы хотел добавить атрибут KnownType к этому базовому типу.Но поскольку мой базовый тип — Object, я не вижу способа сделать это.

Что касается суррогатов, мне кажется, что они используются для типов-оберток, для которых не определен контракт.Однако в моем случае контракт определен.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top