DataContract包含Exception

时间:2011-09-09 13:55:35

标签: c# wcf exception

我有一个类(有属性和一些方法)

[DataContract]
public partial class AbstractApplicationCallDto
{
    [IgnoreDataMember]
    private Exception exception;

    [DataMember]
    private string exceptionString;

    [DataMember]
    private string sessionId = null;

    [DataMember]
    private MyType myType = null;
}

当我将IgnoreDataMember添加到具有Exception类型的字段时,我可以毫无问题地为客户端生成代码。但是如果添加DataMember,则不会生成任何内容。

为什么?如何将Exception类型添加到DataContract

2 个答案:

答案 0 :(得分:4)

这不是一个真正的答案,只是关于异常序列化的一些注释,我想要一些代码的额外空间......

您是否考虑过使用FaultContracts? http://msdn.microsoft.com/en-us/library/ms733721.aspx

尽管Exception类型是可序列化的,但通常在其_data字段中设置的任何类型都不可序列化,并且有时会导致序列化问题。 See here.解决方法是在序列化之前将_data字段设置为null:

        Exception ex = error;
        FieldInfo fieldInfo = typeof(Exception).GetField("_data", BindingFlags.Instance | BindingFlags.NonPublic);
        while (ex != null)
        {
            fieldInfo.SetValue(ex, null);
            ex = ex.InnerException;
        }

另一个问题是,通过向Exception添加DataContract类型,您只会涵盖实际Exception实例的情况:

AbstractApplicationCallDto.Exception = new Exception();

然而,Exception的任何衍生物都可以工作,例如:

AbstractApplicationCallDto.Exception = new NullReferenceException();

要完成这项工作,您必须在数据合同中添加[KnownType]属性,这样您最终会得到以下内容:

[DataContract]
[KnownType(typeof(NullReferenceException))]
[KnownType(typeof(InvalidOperationException))]
[KnownType(typeof(ApplicationException))]
[KnownType(typeof(...))] // add one for every type of exception you might need to serialize back, or that might be contained in Exception.InnerException
public partial class AbstractApplicationCallDto
{
    ...

回到原来的问题,我无法想到当合同中有Exception类型时,客户端生成工具无法生成任何内容的原因......是否会出错?它会生成任何代码吗?

答案 1 :(得分:1)

我也有这个问题;通过创建字段类型ExceptionDetail并使用它来包装Exception对象,我能够绕过它。例如:

[DataContract]
public class WebServiceFault
{
    public WebServiceFault(Exception ex)
    {
        Message = ex.Message;
        InnerException = new ExceptionDetail(ex);
    }

    [DataMember]
    public string Message
    {
        get;
        private set;
    }

    [DataMember]
    public ExceptionDetail InnerException
    {
        get;
        private set;
    }
}