toATwork
toATwork

Reputation: 1367

How to deal with Exceptions during serialization in a WCF call

I do have a data object where customers can attach files. When the customer clicks on the save button I lazy load the content of the file (File.ReadAllBytes(path)) and send it from the client application to the server application.

    [Browsable(false)]
    [ProtoMember(4)]
    public byte[] BinaryData
    {
        get
        {
            if (_binaryData == null && !string.IsNullOrEmpty(FilePath))
            {
                _binaryData = File.ReadAllBytes(FilePath);
            }
            return _binaryData;
        }
        private set
        {
            _binaryData = value;
        }
    }

Lets assume the file is an Excel file and the customer has the file still open. Then an IO Exception is thrown that the file is still locked by another application.

This causes my channel to fault - which is completely unacceptable.

Is there any way to get around that? I even tried a FaultContract but to no avail. That was to expect because I am not even getting from the client to the server.

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

Of course, I can catch that exception, send the message to the server and throw a FaultException on server side - but I don't like that idea.

I could also validate the dataobject on client side prior sending, but I don't like that idea either.

Is there any possibility to cancel a message without causing the channel to fault?

Environment:

Callstack (part of it):

mscorlib.dll!System.IO.__Error.WinIOError(int errorCode = -2147024864, string maybeFullPath = "C:\XXX.xls") + 0x321 bytes
mscorlib.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 bytes
mscorlib.dll!System.IO.FileStream.FileStream(string path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share) + 0x54 bytes mscorlib.dll!System.IO.File.ReadAllBytes(string path) + 0x3b bytes
AB.XYZ.DataModel.dll!AB.XYZ.DataModel.FileContent.BinaryData.get() Line 83 + 0x19 bytes C# AB.XYZ.DataModel.dll!AB.XYZ.DataModel.FileContent.OnSerializing(System.Runtime.Serialization.StreamingContext c = {System.Runtime.Serialization.StreamingContext}) Line 123 + 0x43 bytes C# [Lightweight Function]
.... System.Runtime.Serialization.dll!System.Runtime.Serialization.XmlObjectSerializer.WriteObject(System.Xml.XmlDictionaryWriter writer, object graph) + 0x2d bytes .... 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.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) Line 236 + 0x2b bytes 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() Line 28 + 0x94 bytes C#

Upvotes: 2

Views: 626

Answers (1)

tom redfern
tom redfern

Reputation: 31760

This causes my channel to fault - which is completely unacceptable.

If this is unacceptable to you then stop doing it.

If you don't want this behavior then load the excel file into memory before you open the wcf client channel.

I even tried a FaultContract but to no avail

That is because WCF fault contracts are for handling server side errors.

I could also validate the dataobject on client side prior sending, but I don't like that idea either.

If you write code which can create data which is in an invalid state and therefore fails during serialization, and you are unwilling to validate the state of the data, then expecting the framework to have some kind of built-in way to handle that is a sign that you don't understand the framework.

The structure of my dataobjects is dynamically - customer can configure it. Theoretically any property can throw an exception

What does your operation contract actually look like? Does it expose an argument of type object? If so this is not what WCF is for. If you need a generic service operation which can literally handle any type you pass it then you would be better off just using messages directly.

Upvotes: 1

Related Questions