我确实有一个数据对象,客户可以在其中附加文件。当客户单击保存按钮时,我会延迟加载文件(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异常,该文件仍被另一个应用程序锁定。

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

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

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


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

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

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

环境:


.net 4.0与VS 2010
具有Protobuf网络序列化的CompressionMessageEncoderFactory


调用栈(部分):


  mscorlib.dll!System.IO .__ Error.WinIOError(int errorCode = -2147024864,字符串mayFullPath =“ C:\ XXX.xls”)+ 0x321字节
      mscorlib.dll!System.IO.FileStream.Init(字符串路径,System.IO.FileMode模式,System.IO.FileAccess访问权限=读取,int权限,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 c = {System.Runtime.Serialization.StreamingContext})第123行+ 0x43字节C#
      [轻量功能]
      ....
      System.Runtime.Serialization.dll!System.Runtime.Serialization.XmlObjectSerializer.WriteObject(System.Xml.XmlDictionaryWriter writer,对象图)+ 0x2d字节
      ....
      System.ServiceModel.dll!System.ServiceModel.Channels.BinaryMessageEncoderFactory.BinaryMessageEncoder.WriteMessage(System.ServiceModel.Channels.Message消息= {System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage},int maxMessageSize = 2147483647,System.ServiceModel.Channels。 BufferManager bufferManager = {System.ServiceModel.Channels.BufferManager.WrappingBufferManager},int messageOffset = 5)+ 0x452字节
      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字节
      AB.XYZ.WCF.Client.dll!AB.XYZ.WCF.Client.WCFDataStore.Save.AnonymousMethod__0()第28行+ 0x94字节C#

最佳答案

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


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

如果您不希望出现这种情况,请在打开wcf客户端通道之前将excel文件加载到内存中。


  我什至尝试了FaultContract,但无济于事


这是因为WCF故障合同是用于处理服务器端错误的。


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


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


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


您的运营合同实际上是什么样的?它是否公开类型为object的参数?如果是这样,这不是WCF的目的。如果您需要一个可以按字面处理任何类型的通用服务操作,则最好使用using messages directly

09-25 17:48
查看更多