繁体   English   中英

WCF故障合同的企业库异常处理-客户端

[英]Enterprise Library Exception Handling for WCF Fault Contracts - CLIENT SIDE

我有一个与WCF服务通信的Windows服务。 WCF服务均受故障保护,并生成自定义UserFaultContracts和ServiceFaultContracts。 那里没有问题。

在Windows服务中,我使用EntLib进行异常处理和日志记录。

我不想尝试发现错误

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

我想使用EntLib

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

但是,这在我的事务处理策略中也有效,我想记录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,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]] ,System.ServiceModel,版本= 3.0.0.0,区域性=中性,PublicKeyToken = b77a5c561934e089消息:DispatchMaster服务出现内部错误。 源:mscorlib帮助链接:详细信息:LCI.DispatchMaster.FaultContracts.ServiceFaultContract操作: http : //LCI.DispatchMaster.LogicalChoices.com/ITruckMasterService/MergeScenarioServiceFaultContractFault代码:System.ServiceModel.FaultCode原因:DispatchMaster服务存在内部故障。 数据:System.Collections.ListDictionaryInternal TargetSite:无效HandleReturnMessage(System.Runtime.Remoting.Messaging.IMessage,System.Runtime.Remoting.Messaging.IMessage)堆栈跟踪:

在故障联系人中,有一个ID和一条消息。 如您所见,我希望EntLib记录ID和消息。

我假设我将不得不编写一个自定义处理程序来吸引故障详细信息,但是我想问一下是否在EntLib中缺少某些内容,这可能有助于我避免执行该任务。

感谢任何愿意提供帮助的人。

如果确定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);
}

实际上,我现在正在就如何正确处理WCF Faults和EAB进行非常相似的研究。 我认为这篇文章可能对您非常有用。 我还没有尝试过,但是看起来没有那么沉闷。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM