次の 3 つのパッケージを WCF サービス プロジェクトにロードしました。
EnterpriseLibrary.Common バージョン 6.0.1304.0
EnterpriseLibrary.ExceptionHandling 6.0.1304.0
EnterpriseLibrary.ExceptionHandling.WCF バージョン 6.0.1304.0
サービス インターフェイスと MyTestFault DataContract は次のとおりです。
[ServiceContract]
public interface IRepairService
{
[OperationContract]
[FaultContract(typeof(MyTestFault))]
string SaveRepairCode(string failureCode, string description);
}
[DataContract]
public class MyTestFault
{
#region Member Fields
private string _message = "An unexpected error occured while executing the service method.";
#endregion
#region Properties
[DataMember]
public string Message
{
get { return _message; }
set { _message = value; }
}
#endregion
#region Constructor(s)
public MyTestFault() { }
#endregion
}
サービスの実装は次のとおりです。
[ExceptionShielding("TestPolicy")]
public class RepairService : IRepairService
{
#region Private members
private WimDAL wimDAL;
ExceptionManager exManager;
#endregion
#region Constructor(s)
public RepairService()
{
wimDAL = new WimDAL();
var testPolicy = new List<ExceptionPolicyEntry>
{
{
new ExceptionPolicyEntry(
typeof(SqlException),
PostHandlingAction.ThrowNewException,
new IExceptionHandler[]
{
new FaultContractExceptionHandler(
typeof(MyTestFault),
"SqlException Occurred.",
new NameValueCollection(){ { "Message", "Message" }})
})
},
{
new ExceptionPolicyEntry(
typeof(Exception),
PostHandlingAction.ThrowNewException,
new IExceptionHandler[]
{
new FaultContractExceptionHandler(
typeof(MyTestFault),
"Exception Occurred.",
new NameValueCollection(){ { "Message", "Message" }})
})
}
};
var policies = new List<ExceptionPolicyDefinition>();
policies.Add(new ExceptionPolicyDefinition(
"TestPolicy", testPolicy));
exManager = new ExceptionManager(policies);
}
#endregion
/// <summary>
/// Insert a new fail code with description into RPCODE.
/// Duplicate primary key will throw SqlException that should be processed by EHAB
/// </summary>
public string SaveRepairCode(string failureCode, string description)
{
using (TransactionScope txScope = new TransactionScope())
{
WimSQLCommand sc = new WimSQLCommand() { StoredProcedure = "Repair.RPCODE_Insert" };
sc.Parameters.Add(new SqlParameter("@FailureCode", failureCode));
sc.Parameters.Add(new SqlParameter("@Desc", description));
exManager.Process(() => wimDAL.Execute_NonQueryNoReturn(sc), "TestPolicy");
txScope.Complete();
return "<Save_Repair_Code></Save_Repair_Code>";
}
}
}
これで、プロジェクトへの参照とサービス参照を持つ同じプロジェクトの一部である TestClient コンソール アプリケーションができました。そこから SaveRepairCode() メソッドを呼び出し、次のように特定の障害例外をキャッチしようとします。
ServiceReference1.RepairServiceClient r = new ServiceReference1.RepairServiceClient();
Console.WriteLine("Enter a new repair code:");
string repairCode = Console.ReadLine();
Console.WriteLine("Enter description:");
string description = Console.ReadLine();
try
{
r.SaveRepairCode(repairCode, description);
}
catch (FaultException<MyTestFault> ex)
{
//do something
throw;
}
catch (FaultException fex)
{
//do something
throw;
}
最後に、コンソール アプリを実行して、重複した修復コードを保存しようとしました。これにより SqlException が発生することは、デバッグを通じてわかっています。SqlException をステップ オーバーした後、"FaultContractWrapperException was unhandled by user code" という例外が表示され、ポリシーで指定した "SqlException occured." というメッセージが表示されます。それをステップオーバーすると、クライアントに戻り、次のエラーが表示されます。
CommunicationException was unhandled
サーバーは意味のある応答を返しませんでした。これは、コントラクトの不一致、時期尚早のセッション シャットダウン、または内部サーバー エラーが原因である可能性があります。
PS - これは WCF を使用した Enterprise Library 6 であり、web.config に手動で変更を加えていません。はい、includeExceptionDetailInFaults は false に設定されています。
ここで何が欠けていますか?前もって感謝します。
UPDATE
新しいExceptionManagerをインスタンス化した後、この1行のコードが欠けていたようです。
ExceptionPolicy.SetExceptionManager(exManager);
この 1 行のコードは、Enterprise Library 6 - April 2013.chm には含まれていませんが、「Microsoft Enterprise Library-Preview.pdf の開発者向けガイド」の 90/269 ページには含まれています。その 1 行を含めた後、私はクライアントで適切な FaultException キャッチに入ります。
そうは言っても、クライアントで他の MyTestFault プロパティを取得することはまだできません。たとえば、パブリック文字列 StoredProcedureName を MyTestFault に追加し、それを SqlException の "Procedure" プロパティにマップすると、クライアントに常に null が表示されます。このためのポリシーの唯一の変更は、次のようにマッピングを追加することです。
new NameValueCollection(){ { "Message", "{Message}" }, { "StoredProcedureName", "{Procedure}" } }