У меня есть объект данных, где клиенты могут прикреплять файлы. Когда клиент нажимает кнопку сохранения, я лениво загружаю содержимое файла (File.ReadAllBytes(path)
) и отправляю его из клиентского приложения в серверное приложение.Как бороться с исключениями при сериализации в вызове WCF
[Browsable(false)]
[ProtoMember(4)]
public byte[] BinaryData
{
get
{
if (_binaryData == null && !string.IsNullOrEmpty(FilePath))
{
_binaryData = File.ReadAllBytes(FilePath);
}
return _binaryData;
}
private set
{
_binaryData = value;
}
}
Предположим, что файл является файлом Excel, и клиент все еще открыт. Затем вызывается исключение IO, которое файл по-прежнему заблокирован другим приложением.
Это приводит к поломке моего канала - что совершенно неприемлемо.
Есть ли способ обойти это? Я даже попробовал FaultContract, но безрезультатно. Этого следовало ожидать, потому что я даже не получаю от клиента сервер.
[OperationContract]
[FaultContract(typeof(ExceptionDetail))]
T Save(T dataObject, Guid clientGuid);
Конечно, я могу поймать это исключение, отправьте сообщение на сервер и бросить FaultException на стороне сервера - но мне не нравится эта идея.
Я также могу проверить объект данных на стороне клиента перед отправкой, но мне тоже не нравится эта идея.
Есть ли возможность отменить сообщение, не приводя к неисправности канала?
Окружающая среда:
- .net 4.0 с VS 2010
- CompressionMessageEncoderFactory с Protobuf внутрисетевые сериализации
CallStack (части):
mscorlib.dll! System.IO .__ Error.WinIOError (int errorCode = -2147024864, строка MaybeFullPath = "C: \ XXX.xls") + 0x321 байт
mscorlib.dll! System.IO.FileStream.Init (строковый путь, режим System.IO.FileMode, System.IO.FileAccess access = чтение, int rights, bool useRights = false, общий доступ к System.IO.FileShare, int bufferSize = 4096, параметры System.IO.FileOptions, Microsoft.Win32.Win32Native.SECURITY_ATTRIBUTES secAttrs, строка msgPath, bool bFromProxy, bool useLongPath) + 0x477 байт
mscorlib.dll! System.IO.FileStream.FileStream (строка пути, System. Режим IO.FileMode, доступ к System.IO.FileAccess, общий доступ к System.IO.FileShare) + 0x54 байта mscorlib.dll! System.IO.File.ReadAllBytes (строка) + 0x3b байтов
AB.XYZ.DataModel.dll ! AB.XYZ.DataModel.FileContent.BinaryData.get() Строка 83 + 0x19 байт C# AB.XYZ.DataModel.dll! AB.XYZ.DataModel.FileContent.OnSerializing (System.Runtime.Serialization. StreamingContext с = {System.Runtime.Serialization.StreamingContext}) Строка 123 + 0x43 байт C# [Lightweight Функция]
.... System.Runtime.Serialization.dll! System.Runtime.Serialization.XmlObjectSerializer.WriteObject (System .Xml.XmlDictionaryWriter writer, object graph) + 0x2d байты .... System.ServiceModel.dll! System.ServiceModel.Channels.BinaryMessageEncoderFactory.BinaryMessageEncoder.WriteMessage (System.ServiceModel.Channels.Message message = {System.ServiceModel. Dispatcher.OperationFormatter.OperationFormatterMessage}, int maxMessageSize = 2147483647, System.ServiceModel.Channels.BufferManager bufferManager = {System.ServiceModel.Channels.BufferManager.WrappingBufferManager}, int messageOffset = 5) + 0x452 bytes
AB.XYZ.WCF.Common.dll! AB.XYZ.WCF.Common.dll! AB.XYZ.WCF.Common.Encoder.CompressionMessageEncoderFactory.CompressionMessageEncoder.WriteMessage (System.ServiceModel.Channels.Message message = {System .ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage}, int maxMessageSize = 2147483647, System.ServiceModel.Channels.BufferManager bufferManager = {System.ServiceModel.Channels.BufferManager.WrappingBufferManager}, int messageOffset = 6) Строка 236 + 0x2b байтов C# .. .. mscorlib.dll! System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke (ref System.Runtime.Remoting.Proxies.MessageData msgData, int type = 1) + 0xee bytes
AB.XYZ.WCF.Client.dll ! AB.XYZ.WCF.Client.WCFDataStore.Save.AnonymousMethod__0() Строка 28 + 0x94 байт C#
Вы в конечном итоге решили эту проблему? –
@TomRedfern: не совсем. Я изменил поведение. Поэтому, когда выбран файл, я получаю его содержимое немедленно (и сохраняю его в памяти). Не то, что я имел в виду, но его работа и была наименее инвазивным способом. – toATwork
Спасибо за ответ. Если вы прочитаете первые строки моего ответа ниже, это именно то, что я рекомендовал - * Если вы не хотите этого поведения, загрузите файл excel в память, прежде чем открывать клиентский канал wcf. * –