WCF проблема прохождения сложных типов - PullRequest
1 голос
/ 16 сентября 2008

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

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

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

Подробнее:

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

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

Спасибо

Ответы [ 6 ]

2 голосов
/ 16 сентября 2008

NetDataContract работает, потому что NetDataContractSerializer содержит информацию о типе.

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

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

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

1 голос
/ 16 декабря 2008

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

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

1 голос
/ 17 сентября 2008

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

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

    [DataContract (Namespace = "http://Service.DataContracts", Name =" ServiceDataContractBase ")] открытый класс ServiceDataContract {

    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.

0 голосов
/ 17 сентября 2008

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

0 голосов
/ 16 сентября 2008

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

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

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

0 голосов
/ 16 сентября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...