如何在 WCF 调用中的序列化期间处理异常

本文关键字:序列化 处理 异常 WCF 调用 | 更新日期: 2024-11-07 09:32:49

我确实有一个数据对象,客户可以在其中附加文件。当客户单击保存按钮时,我延迟加载文件的内容(File.ReadAllBytes(path))并将其从客户端应用程序发送到服务器应用程序。

    [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 异常,指出该文件仍被另一个应用程序锁定。

这会导致我的频道出现故障 - 这是完全不可接受的。

有什么办法可以解决这个问题吗?我什至尝试了错误合同,但无济于事。这是意料之中的,因为我什至没有从客户端到服务器。

    [OperationContract]
    [FaultContract(typeof(ExceptionDetail))]
    T Save(T dataObject, Guid clientGuid);

当然,我可以捕获该异常,将消息发送到服务器并在服务器端抛出 FaultException - 但我不喜欢这个想法。

我还可以在发送之前在客户端验证数据对象,但我也不喜欢这个想法。

是否有可能在不导致通道故障的情况下取消消息?

环境:

  • .net 4.0 与 VS 2010
  • CompressionMessageEncoderFactory with protobuf-net serialization

调用堆栈(其中的一部分):

姆科利布.dll!System.IO.__Error.WinIOError(int errorCode = -2147024864, string maybeFullPath = "C:''XXX.xls") + 0x321 字节
姆科利布.dll!System.IO.FileStream.Init(string path, System.IO.FileMode mode, System.IO.FileAccess access = Read, int rights, bool useRights = false, System.IO.FileShare share, int bufferSize = 4096, System.IO.FileOptions options, Microsoft.Win32.Win32Native.SECURITY_ATTRIBUTES secAttrs, string msgPath, bool bFromProxy, bool useLongPath) + 0x477 字节
姆科利布.dll!System.IO.FileStream.FileStream(字符串路径、System.IO.FileMode 模式、System.IO.FileAccess access、System.IO.文件共享共享) + 0x54 字节 姆科利布.dll!System.IO.File.ReadAllBytes(字符串路径) + 0x3b 字节
血型。XYZ。数据模型.dll!血型。XYZ。DataModel.FileContent.BinaryData.get() 第 83 行 + 0x19 字节 C# 血型。XYZ。数据模型.dll!血型。XYZ。DataModel.FileContent.OnSerializing(System.Runtime.Serialization.StreamingContext c = {System.Runtime.Serialization.StreamingContext}) 第 123 行 + 0x43 字节 C# [轻量级功能]
.... System.Runtime.Serialization.dll!System.Runtime.Serialization.XmlObjectSerializer.WriteObject(System.Xml.XmlDictionaryWriter writer, object graph) + 0x2d 字节 .... 系统.服务模式.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 字节
血型。XYZ。周转基金。普通.dll!血型。XYZ。周转基金。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# .... 姆科利布.dll!System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(ref System.Runtime.Remoting.Proxies.MessageData msgData, int type = 1) + 0xee 字节
血型。XYZ。周转基金。客户.dll!血型。XYZ。周转基金。Client.WCFDataStore.Save.AnonymousMethod__0() 第 28 行 + 0x94 字节 C#

如何在 WCF 调用中的序列化期间处理异常

这会导致我的频道出现故障 - 这是完全不可接受的。

如果您无法接受,请停止这样做。

如果不希望此行为,请在打开 wcf 客户端通道之前将 excel 文件加载到内存中。

我什至尝试了错误合同,但无济于事

这是因为 WCF 错误协定用于处理服务器端错误。

我还可以在发送之前在客户端验证数据对象,但是 我也不喜欢这个想法。

如果您编写的代码可以创建处于无效状态的数据,因此在序列化期间失败,并且您不愿意验证数据的状态,那么期望框架具有某种内置方法来处理这种情况表明您不了解框架。

我的数据对象的结构是动态的 - 客户可以 配置它。从理论上讲,任何属性都可以引发异常

您的运营合同实际上是什么样子的?它是否公开对象类型的参数?如果是这样,这不是 WCF 的用途。如果你需要一个通用的服务操作,它可以处理你传递的任何类型的操作,那么你最好直接使用消息。