Неожиданный тип - исключение сериализации - PullRequest
48 голосов
/ 27 мая 2011

У меня есть служба WCF.

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

Моя проблема в том, что когда я пытаюсь установить для переменной returnData заполненное XactException и пытаюсь отправить XactTaskIn обратно клиенту через обратный вызов, я получаю следующее исключение.

Исключение - "Тип" XactException "с именем контракта данных" XactException: http://schemas.datacontract.org/2004/07/' не ожидается. Рассмотрите возможность использования DataContractResolver или добавьте любые типы, которые не известны статически, в список известных типов - например,с помощью атрибута KnownTypeAttribute или путем добавления их в список известных типов, передаваемых в DataContractSerializer. "(System.Runtime.Serialization.SerializationException) Исключение Сообщение = "Тип 'XactException' с именем контракта данных 'XactException: http://schemas.datacontract.org/2004/07/' не ожидается. Рассмотрите возможность использования DataContractResolver или добавьте любые типы, которые не известны статически, в список известных типов - дляНапример, используя атрибут KnownTypeAttribute или добавляя их в список известных типов, передаваемых в DataContractSerializer. ", Exception Type =" System.Runtime.Serialization.SerializationException "

Вот класс XactTaskIn

[DataContract]
public class XactTaskIn
{
    [DataMember]
    public DateTime timeOut;
    [DataMember]
    public DateTime timeIn;
    [DataMember]
    public string name;
    [DataMember]
    public string responseTo;
    [DataMember]
    public String moduleFromName;
    [DataMember]
    public String moduleFromType;
    [DataMember]
    public String methodFromName;
    [DataMember]
    public object[] originalInputs;
    [DataMember]
    public String returnMethodToCall;
    [DataMember]
    public String returnModuleToCall;
    [DataMember]
    public object returnData;

    public XactTaskIn(DateTime timeOut, DateTime timeIn, string name, string responseTo, String moduleFromName, String moduleFromType, String methodFromName, object[] originalInputs, String returnMethodToCall, String returnModuleToCall, object returnData)
    {
        this.timeOut = timeOut;
        this.timeIn = timeIn;
        this.name = name;
        this.responseTo = responseTo;
        this.moduleFromName = moduleFromName;
        this.moduleFromType = moduleFromType;
        this.methodFromName = methodFromName;
        this.originalInputs = originalInputs;
        this.returnMethodToCall = returnMethodToCall;
        this.returnModuleToCall = returnModuleToCall;
        this.returnData = returnData;
    }
}

Вот класс XactException:

[DataContract]    
public class XactException
{
    [DataMember]
    string message;

    public XactException(string message)
    {
        this.message = message;
        // Add implementation.
    }
}

Обновление:

Хорошо, так что комментарий от Дэниела помог мне.

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

  • Поймано: "Средство форматирования выдало исключение во времяпри попытке десериализации сообщения: произошла ошибка при попытке десериализации параметра http://tempuri.org/:taskIn. Сообщение InnerException было «Ошибка в строке 1, позиция 960. Элемент 'http://schemas.datacontract.org/2004/07/:returnData' содержит данные из типа, сопоставленного с именем' http://schemas.datacontract.org/2004/07/:XactException'. Десериализатору неизвестно о каком-либо типе, сопоставленном с этим именем. Попробуйте использовать DataContractResolver или добавить тип, соответствующий «XactException», в список известных типов, например, с помощью атрибута KnownTypeAttribute или добавив его всписок известных типов, переданных в DataContractSerializer. '. Более подробную информацию смотрите в InnerException. "(System.ServiceModel.Dispatcher.NetDispatcherFaultException) Exception Message = "Форматировщик выдал исключение при попытке десериализации сообщения: при попытке десериализации параметра произошла ошибка http://tempuri.org/:taskIn. Сообщение InnerException было 'Ошибка в позиции строки 1960. Элемент 'http://schemas.datacontract.org/2004/07/:returnData' содержит данные из типа, который сопоставляется с именем' http://schemas.datacontract.org/2004/07/:XactException'. Десериализатору неизвестно о каком-либо типе, сопоставленном с этим именем. Рассмотрите возможность использования DataContractResolver или добавьте тип, соответствующий 'XactException', ксписок известных типов - например, с помощью атрибута KnownTypeAttribute или путем добавления его в список известных типов, передаваемых в DataContractSerializer. '. Дополнительные сведения см. в разделе InnerException. ", Exception Type =" System.ServiceModel.Dispatcher.NetDispatcherFaultException "

Ответы [ 3 ]

80 голосов
/ 27 мая 2011

В вашем классе

    [DataContract]
    public class XactTaskIn

у вас есть свойства, которые возвращают объекты:

        [DataMember]
        public object[] originalInputs;

        [DataMember]
        public object returnData;

WCF необходимо заранее знать, какие типы могут быть там, чтобы он мог сообщить клиенту (через WSDL), что это за типы. Для любых / всех не «нативных» типов (кроме int, string, DateTime и т. Д.) Вам нужно будет добавить атрибут [KnownType] для каждого возможного типа, который может быть передан обратно в свойства этого объекта, например:

    [KnownType(typeof(XactException))]
    [KnownType(typeof(...))]
    [KnownType(typeof(...))]
    [DataContract]
    public class XactTaskIn

Таким образом, когда WCF создает WSDL для службы, он будет знать, добавить ли XactException в список типов данных, а также сериализатор будет знать, что искать эти классы.


Боковая примечание; если ваш клиент был построен с использованием SrvUtil, Service Reference или каким-либо образом сгенерирован из WSDL, вам нужно будет перестроить клиент после добавления атрибутов [KnownType]!

0 голосов
/ 27 мая 2011

Исключения сериализации возникают, когда данные изменились, например, что-то столь же тривиальное, как изменение имени поля с awesomeString на awesomeSTring, что приведет к прерыванию сериализации. Причина этого в том, что новые данные больше не могут быть проверены на соответствие старым данным. Исправление для этого - использовать старую версию, которую ожидает сервер / клиент.

0 голосов
/ 27 мая 2011

Ваш клиент ожидает XactTaskIn, а не XactException.

Вам нужно изменить свой XactTaskIn, чтобы иметь возможность передавать объект исключения обратно вашему клиенту.

Удалите ваш datacontract и добавьте тип XactException в ваш класс XactTaskIn в качестве члена данных

...