Сериализация IDictionary<string, object> в WCF
У нас есть приложение, для которого один из наших объектов DTO имеет свойство, типизированное как IDictionary<string, object>
,
Я сейчас пытаюсь выставить этот объект через службу WCF. Это работает в некоторых случаях, но не в общем случае. Чтобы продемонстрировать проблему, рассмотрим следующие два метода:
[OperationContract]
public IDictionary<string, object> Test1()
{
return new Dictionary<string, object>
{
{ "testkey1", "newstringvalue"},
};
}
[OperationContract]
public IDictionary<string, object> Test2()
{
return new Dictionary<string, object>
{
{ "testkey1", "newstringvalue"},
{ "testkey2", new object [] { "one" , "two", "three", } }
};
}
Метод Test1() работает как положено, но когда я вызываю Test2(), я получаю странную ошибку времени выполнения на клиенте:
Время ожидания канала запроса в ожидании ответа после 00:01:00. Увеличьте значение тайм-аута, передаваемое вызову Request, или увеличьте значение SendTimeout в Binding. Время, выделенное для этой операции, могло быть частью более длительного времени ожидания.
Внутреннее исключение: удаленный сервер возвратил ошибку: (504) Время ожидания шлюза.
И это несмотря на то, что исключение было выдано мгновенно, т.е. На самом деле мне не пришлось ждать ни минуты для этого ответа. Ошибка не отображается на сервере.
Я подозреваю, что это связано с тем, что сериализатор не может сериализовать объект [], но это не то, что указано в ошибке.
Итак, мои вопросы:
- Что здесь происходит?
- Как мне обойти это, чтобы я мог правильно сериализовать свои объекты?
Благодарю.
2 ответа
Поскольку ни я, ни кто-либо из моих коллег не могли придумать, как заставить эту сериализацию работать напрямую, мы в конце концов решили эту проблему, обернув наш объект в пользовательский объект, который преобразует Dictionary<string, object>
к Dictionary<string, string>
, который имеет специальный случай сериализации, определенный для строковых массивов. Затем мы изменили приложение, чтобы знать об этом. Не особенно элегантно, но достаточно просто и, кажется, работает.
Я думаю, что вам нужно добавить object[] к известным типам с помощью KnownTypeAttribute, чтобы второй вариант работал, так как это то, что вы помещаете в словарь.
В любом случае, чтобы увидеть реальную ошибку на сервере, вам нужно включить трассировку WCF (или запустить отладчик в режиме, в котором он останавливается на каждом исключении, даже если оно перехвачено)