1

这是我观察到的

我需要从服务向客户端抛出一个自定义异常子类型。(列为FaultContract 上的具体操作)。我在 CustomException 上有某些字段,应该由客户端接收。

[Serializable]
class MyCustomException : Exception
{
    public string From { get; private set; }

    public MyCustomException(string where)
    {
        From = where;
    }

}

}

我发现即使在 FaultException 实例中存在异常,该字段也没有被反序列化。我尝试通过覆盖 GetObjectData 和序列化 ctor 来实现 ISerializable,但没有骰子。我能理解它的唯一方法是将 MyCustomException 更改为 DataContract,而不是从 Exception 派生。

[DataContract]
class MyCustomException
{
    [DataMember]
    public string From { get; private set; }

    public MyCustomException(string where)
    {
        From = where;
    }
}

这行得通。但是,它不能再从 Exception 派生了。因为 Exception 被标记为 Serializable 属性,并且您不能在一个类型上同时具有 Serializable 和 DataContract 。(确认:运行时抛出异常)

所以我的问题是:在 WCF 中传播自定义异常子类型的字段的正确方法是什么?

4

2 回答 2

2

...你不能在一个类型上同时拥有 Serializable 和 DataContract 。(确认:运行时抛出异常)

首先,你可以拥有DataContractSerializable在一起。事实上,如果没有这个,我现在正在处理的网站将无法运行,因为我的 WCF 服务是通过$.ajax. SO 线程将为您提供正式的详细信息。

接下来,我强​​烈建议不要从Exception. 原因是您已经有一个FaultException<TDetail>内置类,TDetail您的自定义错误在哪里。您可以阅读MSDN 文章以了解实现细节 - 请记住在部署时关闭客户端的“异常详细信息”。

catch (FaultException<MyFault> e)
{
    //e is the full exception (with StackTrace et al.) when 'exception details' is on
    //e.Detail is your custom fault which is always available
}
于 2012-07-18T13:23:13.223 回答
1

这就是我如何让它工作..不确定它是否是正确的方法。我找不到任何明确的指导方针,说明您不应该使用 Exception 子类型作为FaultException<TDetail>.

我尝试抛出一个FaultException<FileNotFoundException>并发现文件名字段实际上是正确传播的。

那么 FileNotFoundException 和 MyCustomException 之间的差异是什么?

由于基本异常实现了 ISerializable,我不得不重写服务器端的方法。

    protected MyCustomException(SerializationInfo info, StreamingContext context) :
        base(info, context)
    {
        this.From = info.GetString("From");
    }
    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        base.GetObjectData(info, context);
        info.AddValue("From", this.From);
    }

然后我使用 svcutil 生成客户端代理类。我发现 FileNotFoundException 没有生成(因为它是一个内置类型),但 MyCustomException 是。但是它没有任何字段,只有一个空的反序列化 ctor。

我之前没有深入研究 ISerializable,因为当我在代理类 ctor 中设置断点时,它没有被击中。我错误地中止了那条调查线(未能看到类上的 DebuggerStepThrough 属性和 GeneratedCode 属性;由 svcutil 添加)。

因此,我然后手动编辑自动生成的类以添加该字段并将其设置在 ctor 中,如下所示..

[System.SerializableAttribute()]
    public partial class MyCustomException : System.Exception
    {
        public string From { get; private set; } // manual edit

        public MyCustomException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) :
            base(info, context)
        {
             this.From = info.GetString("From");  // manual edit
        }
    }

现在它按预期工作;现场数据完好无损。

这就提出了另一个问题:为什么代理生成步骤不自动执行此操作?

于 2012-07-19T09:56:23.423 回答