0

WCF サービスと通信する Windows サービスがあります。WCF サービスはすべてフォールト シールドされており、カスタムの UserFaultContract と ServiceFaultContract を生成します。問題ありません。

Windows サービスでは、例外処理とログ記録に EntLib を使用しています。

フォールトのキャッチを試みたくない

try
{
}
catch (FaultException<UserFaultContract>)
{
}

EntLib を使いたい

try
{
}
catch (Exception ex)
{
var rethrow = ExceptionPolicy.HandleException(ex, "Transaction Policy");
if (rethrow) throw;
}

これも機能しますが、私の Tranasaction ポリシーでは、UserFaultContract の詳細をログに記録したいと考えています。これは私が接着されていないところです。そして、私は接着剤がばらばらになるのが嫌いです。障害はキャプチャされてログに記録されますが、障害の詳細を取得できません。

私の例外ポリシーは

  <add name="Transaction Policy">
    <exceptionTypes>
      <add type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        postHandlingAction="None" name="Exception">
        <exceptionHandlers>
          <add logCategory="General" eventId="200" severity="Error" title="Transaction Error"
            formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            priority="2" useDefaultLogger="true" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            name="Logging Handler" />
        </exceptionHandlers>
      </add>
      <add type="System.ServiceModel.FaultException, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        postHandlingAction="None" name="FaultException">
        <exceptionHandlers>
          <add logCategory="General" eventId="200" severity="Error" title="Service Fault"
            formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            priority="2" useDefaultLogger="true" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            name="Logging Handler" />
        </exceptionHandlers>
      </add>
    </exceptionTypes>
  </add>

ログに記録された例外は次のとおりです。

タイムスタンプ: 5/13/2010 14:53:40 メッセージ: HandlingInstanceID: e9038634-e16e-4d87-ab1e-92379431838b

タイプ 'System.ServiceModel.FaultException`1[[LCI.DispatchMaster.FaultContracts.ServiceFaultContract, LCI.DispatchMaster.FaultContracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' の例外が発生し、キャッチされました。

2010 年 5 月 13 日 10:53:40 タイプ: System.ServiceModel.FaultException`1[[LCI.DispatchMaster.FaultContracts.ServiceFaultContract、LCI.DispatchMaster.FaultContracts、バージョン = 1.0.0.0、カルチャ = ニュートラル、PublicKeyToken = null]] 、System.ServiceModel、Version=3.0.0.0、Culture=neutral、PublicKeyToken=b77a5c561934e089 メッセージ : DispatchMaster サービスで内部エラーが発生しました。ソース: mscorlib ヘルプ リンク: 詳細: LCI.DispatchMaster.FaultContracts.ServiceFaultContract アクション: http://LCI.DispatchMaster.LogicalChoices.com/ITruckMasterService/MergeScenarioServiceFaultContractFault コード: System.ServiceModel.FaultCode 理由: DispatchMaster サービスで内部エラーが発生しました。データ: System.Collections.ListDictionaryInternal TargetSite: Void HandleReturnMessage(System.Runtime.Remoting.Messaging.IMessage, System.Runtime.Remoting.Messaging.IMessage) スタック トレース:

障害連絡先には、ID とメッセージがあります。ご覧のとおり、ID とメッセージが EntLib によってログに記録されるようにします。

障害の詳細を抽出するためにカスタム ハンドラーを作成する必要があると想定していますが、そのタスクを回避するのに役立つ可能性がある EntLib に何かが欠けているかどうかを尋ねたいと思いました。

喜んで助けてくれる人に感謝します。

4

2 に答える 2

0

私は実際、WCF障害とEABを適切に処理する方法について、非常によく似た調査を行っています。この記事はあなたにとって非常に役立つかもしれないと思います。私はそれを試していませんが、それはあまりにも厳しく見えません。

于 2010-05-13T16:09:10.150 に答える
0

WCF サービスですべてが正しく構成されていることが確実な場合は、サービス側で入力したメッセージを取得できるはずです。

次のコードは、クライアント側で完全な例外の詳細を表示する必要があります。

private void CalculateDivision(decimal numerator, decimal denominator)
{
    try
    {
        // Create an instance of service client.
        ICalculatorService svc = new CalculatorServiceClient();
        // Call service method.
        Console.WriteLine("Result is: {0}", svc.Divide(numerator, denominator));
    }
    catch (Exception ex)
    {
        // Show details of the exception returned to the calling code.  
        ShowExceptionDetails(ex);
        // Show details of the fault contract returned from the WCF service.  
        ShowFaultContract(ex);
    }
}


public void ShowExceptionDetails(Exception ex)
{
    Console.WriteLine("Exception type {0} was thrown.", ex.GetType().ToString());
    Console.WriteLine("Message: '{0}'", ex.Message);
    Console.WriteLine("Source: '{0}'", ex.Source);
    if (null == ex.InnerException)
    {
        Console.WriteLine("No Inner Exception");
    }
    else
    {
        Console.WriteLine();
        Console.WriteLine("Inner Exception: {0}", ex.InnerException.ToString());
    }
    Console.WriteLine();
}

private static void ShowFaultContract(Exception ex)
{
    var faultContract = ex as FaultException<CalculatorFault>;
    if (faultContract != null)
    {
        CalculatorFault calculatorFault = faultContract.Detail;
        Console.WriteLine("Fault contract detail: ");
        Console.WriteLine("Fault ID: {0}", calculatorFault.FaultID);
        Console.WriteLine("Message: {0}", calculatorFault.FaultMessage);
    }
}

それでもうまくいかない場合は、サービス側に問題があることは確かです。上で定義した特定のクライアントのサービス コードがどのようになるかを見てみましょう。

[ServiceContract]
public interface ICalculatorService
{
    [OperationContract]
    [FaultContract(typeof(CalculatorFault))]
    decimal Divide(decimal num1, decimal num2);
}

[DataContract]
public class CalculatorFault
{
    [DataMember]
    public Guid FaultID { get; set; }

    [DataMember]
    public string FaultMessage { get; set; }
}

[ExceptionShielding("CalculatorServicePolicy")]
public class CalculatorService : ICalculatorService
{
    public decimal Divide(decimal num1, decimal num2)
    {
      Calculator calc = new Calculator();
      return calc.Divide(num1, num2);
    }
}

//Call the following function in Application_Start function of your Global.asax file
private void ConfigureExceptionHandlingBlock()
{
    var policies = new List<ExceptionPolicyDefinition>();

    var mappings = new NameValueCollection();
    mappings.Add("FaultID", "{Guid}");
    mappings.Add("FaultMessage", "{Message}");

    var calculatorServicePolicy = new List<ExceptionPolicyEntry>
        {
            new ExceptionPolicyEntry(typeof(Exception),
                PostHandlingAction.ThrowNewException,
                new IExceptionHandler[]
                {
                    new FaultContractExceptionHandler(typeof(CalculatorFault), "Some internal service Error. Check service logs.", mappings)
                })
        };
    policies.Add(new ExceptionPolicyDefinition("CalculatorServicePolicy", calculatorServicePolicy));
    ExceptionManager exManager = new ExceptionManager(policies);
    ExceptionPolicy.SetExceptionManager(exManager);
}
于 2014-11-04T10:30:46.730 に答える