今日、私はこれに出くわしました。解決策は、FaultContractでExceptionから継承しないオブジェクトを使用することでした。FaultExceptionとFaultContractのMSDNドキュメントを見ると、公式の例では、FaultException.DetailのExceptionを拡張するクラスではなく、プレーンクラス(DataContact属性を使用)が使用されていることがわかります。例外によってサービス参照の追加が失敗する理由はわかりませんが、カスタム例外の型情報のシリアル化または取得に関係していると思われます。実用的なアプローチを示すために、実装例の前後を含めました。
前(動作しませんでした):
[ServiceContract]
public interface IMyService
{
[OperationContract]
[FaultContract(typeof(MyException))]
MyResults MyServiceOperation(string myParameter);
}
[Serializable]
public class MyException : Exception
{
public string CustomData { get; set; }
}
[ErrorHandlerBehavior(typeof(MyErrorHandler))]
public class MyService : IMyService
{
public MyResults MyServiceOperation(string myParameter)
{
...
throw new MyModelException { CustomData = "42" };
...
}
}
public class MyErrorHandler : IErrorHandler
{
public bool HandleError(Exception error) { return false; }
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
try { throw error; }
catch (MyModelException ex)
{
var faultEx = new FaultException<MyException>(new MyException { CustomData = ex.CustomData });
fault = Message.CreateMessage(version, faultEx.CreateMessageFault(), faultEx.Action);
}
catch { /* Supress all others */ }
}
}
後(働いた):
[ServiceContract]
public interface IMyService
{
[OperationContract]
[FaultContract(typeof(MyFault))]
MyResults MyServiceOperation(string myParameter);
}
[DataContract]
public class MyFault
{
[DataMember]
public string CustomData { get; set; }
}
[ErrorHandlerBehavior(typeof(MyErrorHandler))]
public class MyService : IMyService
{
public MyResults MyServiceOperation(string myParameter)
{
...
throw new MyModelException { CustomData = "42" };
...
}
}
public class MyErrorHandler : IErrorHandler
{
public bool HandleError(Exception error) { return false; }
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
try { throw error; }
catch (MyModelException ex)
{
var faultEx = new FaultException<MyFault>(new MyFault { CustomData = ex.CustomData });
fault = Message.CreateMessage(version, faultEx.CreateMessageFault(), faultEx.Action);
}
catch { /* Supress all others */ }
}
}
出典:Max Striniは、彼のコードを使用し、この問題の解決策を見つけるのに役立ちました。