Question

I'm trying to pass objects of type Exception (or one of it's subclasses) over a NamedPipe.

ServiceContract:

[ServiceContract]
public interface IWCFCallback
{
    [OperationContract]
    void sendException(Exception e);
}

it works fine when i use it like this:

_pipeproxy.sendException(new Exception("bla bla 99"));

but as soon as I pass a subclass:

_pipeproxy.sendException(new ArgumentException("fridgemaster 3000"));

I get a Exception, saying deserialisation failed.

I already read about the KnownTypes Attribute, but i can't figure out how to use it for classes not implemented by myself.

Can someone give me a hint here?

Was it helpful?

Solution

One of the "Best practices" over WCF, is Do not serialize Exception.
If your ServiceHost is throwing exception, then you are suppose to use FaultException.
One of the reason why exception is not safe to transfer, is that Exception itself is serializable, but you can derive from it, and who guarantee that your custom derived exception will be serialable.

You could pass a Data contract object with the exception stack as string and type as enum, as a work-around.

OTHER TIPS

This may not be according to the best practices but you can create a DataContract that represents the Exception - something like this:

/// <summary>
/// Represents errors that occur during application execution.
/// </summary>
[DataContract]
public class ExceptionInfo
{
    /// <summary>
    /// Gets the type of the exception.
    /// </summary>
    [DataMember]
    public string ExceptionType
    {
        get;
        set;
    }

    /// <summary>
    /// Gets a message that describes the current exception.
    /// </summary>
    /// <returns>
    /// The error message that explains the reason for the exception, or an empty string("").
    /// </returns>
    [DataMember]
    public string Message
    {
        get;
        set;
    }

    /// <summary>
    /// Gets the <see cref="T:System.Exception"/> instance that caused the current exception.
    /// </summary>
    /// <returns>
    /// An instance of Exception that describes the error that caused the current exception. The InnerException property returns the same value as was passed into the constructor, or a null reference (Nothing in Visual Basic) if the inner exception value was not supplied to the constructor. This property is read-only.
    /// </returns>
    [DataMember]
    public ExceptionInfo InnerException
    {
        get;
        set;
    }

    /// <summary>
    /// Gets a string representation of the immediate frames on the call stack.
    /// </summary>
    /// <returns>
    /// A string that describes the immediate frames of the call stack.
    /// </returns>
    [DataMember]
    public string StackTrace
    {
        get;
        set;
    }

    /// <summary>
    /// Gets or sets a link to the help file associated with this exception.
    /// </summary>
    /// <returns>
    /// The Uniform Resource Name (URN) or Uniform Resource Locator (URL).
    /// </returns>
    [DataMember]
    public string HelpLink
    {
        get;
        set;
    }

    /// <summary>
    /// Gets or sets the name of the application or the object that causes the error.
    /// </summary>
    [DataMember]
    public string Source
    {
        get;
        set;
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="ExceptionInfo"/> class.
    /// </summary>
    /// <param name="exception">The exception.</param>
    /// <exception cref="ArgumentNullException">exception</exception>
    public ExceptionInfo(Exception exception)
    {
        if(exception == null)
            throw new ArgumentNullException("exception");

        ExceptionType = exception.GetType().FullName;
        HelpLink = exception.HelpLink;
        Message = exception.Message;
        Source = exception.Source;
        StackTrace = exception.StackTrace;

        if(exception.InnerException != null)
        {
            InnerException = new ExceptionInfo(exception.InnerException);
        }
    }
}

Service Contract:

[ServiceContract]
public interface IWCFCallback
{
    [OperationContract]
    void sendException(ExceptionInfo e);
}

Usage:

try
{
    // .....
}
catch (Exception ex)
{
    var info = new ExceptionInfo(ex);

    // do something....
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top