#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. Я не могу придумать лучшего способа. Я бы сделал точно так же, как вы сказали.