Произошла ошибка при попытке сериализовать параметр

#c# #wcf #serialization

#c# #wcf #сериализация

Вопрос:

У меня есть служба WCF, и я хочу передать некоторые файлы с сервера на клиент.

У меня это срабатывало, когда я жестко кодировал имя файла для потоковой передачи в код.

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

Я получаю следующее исключение на стороне клиента при попытке вызвать метод GetStream: Произошла ошибка при получении HTTP-ответа наhttp://localhost:8082 /. Это может быть связано с тем, что привязка конечной точки службы не использует протокол HTTP. Это также могло быть связано с тем, что контекст HTTP-запроса был прерван сервером (возможно, из-за завершения работы службы). Смотрите журналы сервера для получения более подробной информации.

После изучения этого в сети, похоже, что это ложное исключение, поэтому я включил трассировку, и это сообщение об исключении из журнала трассировки:

Произошла ошибка при попытке сериализовать параметр http://tempuri.org/:GetStreamResult . Сообщение InnerException было ‘Введите ‘System.IO.FileStream’ с именем контракта данных ‘FileStream: http://schemas.datacontract.org/2004/07/ Система.Ввод-вывод’ не ожидается. Рассмотрите возможность использования DataContractResolver или добавьте любые типы, неизвестные статически, в список известных типов — например, с помощью атрибута KnownTypeAttribute или добавив их в список известных типов, переданных DataContractSerializer.’. Пожалуйста, смотрите InnerException для получения более подробной информации.

Вот код на стороне сервера:

 public Dictionary<String, Stream> GetStream()
    {
        Dictionary<String, Stream> retDic = new Dictionary<string, Stream>();          

        string[] fileEntries = Directory.GetFiles(@"C:UsersAshDesktopFrontendPluginsServer");
        foreach (string fileName in fileEntries)
        {
             //do something with fileName
            retDic.Add(fileName, File.OpenRead(fileName));
        }
        //return File.OpenRead(@"C:UsersAshDesktopFrontendPluginsServerOptekImporterFrontend.dll");

        return retDic;
    }
  

Вот код на стороне клиента:

 ModuleDownloader.ModuleDownloaderClient moo = new ModuleDownloader.ModuleDownloaderClient();
        Dictionary<String, Stream> dic = moo.GetStream();

        foreach (String key in dic.Keys)
        {
            using (Stream file = File.OpenWrite(@"C:UsersAshDesktopFrontEndPluginsClient"   key)) { CopyStream(dic[key], file); }
        }
  

Пожалуйста, дайте мне знать, если вам понадобится дополнительная информация.

С уважением

Ash

Комментарии:

1. есть какое-нибудь окончательное решение с полным исходным кодом?

Ответ №1:

Вы никак не можете этого сделать.

  • FileStream не поддается сериализации. Причина, по которой он пытается сериализовать его, заключается в том, что он не соответствует соглашениям о потоковой передаче WCF.
  • Ограничения WCF на потоковую передачу определяют, что у вас должен быть один Stream в сигнатуре метода и ничего больше, если вы хотите использовать потоковую передачу WCF.

В любой момент вы можете отправить только один поток.

Подробнее здесь.

Комментарии:

1. Спасибо за это. Полагаю, я могу сделать то, что хотел, выполнив вызов server, чтобы вернуть список существующих имен файлов, а затем вызвать GetStream, чтобы вернуть один поток для этого файла? Или вы можете придумать лучший способ сделать это?

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