0

次の 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}" } }
4

1 に答える 1

0

この行が原因であることが判明しました。

exManager.Process(() => wimDAL.Execute_NonQueryNoReturn(sc), "TestPolicy");

ExceptionManager の Process メソッドを使用する代わりに、潜在的な例外が予想されるコマンドを実行するだけです。

wimDAL.Execute_NonQueryNoReturn(sc);

これは、「Microsoft Enterprise Library-Preview.pdf の開発者ガイド」の内容に従っていませんが、ドキュメントはまだ作成中の作業であると思います。これが他の誰かに役立つことを願っています。

于 2013-05-13T17:17:42.440 に答える