0

我将这三个包加载到我的 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 未被用户代码处理”异常,并且它具有我在“发生 SqlException”的策略中指定的消息。当我越过它时,我回到客户端并看到此错误:

CommunicationException was unhandled
服务器没有提供有意义的回复;这可能是由于合同不匹配、会话过早关闭或内部服务器错误造成的。

PS - 这是带有 WCF 的 Enterprise Library 6,我没有对 web.config 进行手动更改......是的,includeExceptionDetailInFaults 设置为 false。

我在这里想念什么?提前致谢。


更新
在实例化新的 ExceptionManager 之后,我似乎错过了这一行代码。

ExceptionPolicy.SetExceptionManager(exManager);

很高兴看到这一行代码不在 Enterprise Library 6 - April 2013.chm 中,但它在“Microsoft Enterprise Library-Preview.pdf 开发人员指南”(第 90 页,共 269 页)中。包括那一行后,我进入客户端上正确的 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 回答