C# 如何将IParameterInspector与WCF服务一起正确使用,以便在异常情况下也记录web请求?

C# 如何将IParameterInspector与WCF服务一起正确使用,以便在异常情况下也记录web请求?,c#,.net,wcf,logging,exception-handling,C#,.net,Wcf,Logging,Exception Handling,我正在使用日志记录web请求数据。我需要它来计算请求持续时间,并记录输入和输出内容 只要没有异常发生,它就可以正常工作。在异常情况下,将永远不会执行AfterCall事件 发生异常时是否有机会执行后调用?还是我需要另一种方法 下面是我的代码的简化版本: using System; using System.ServiceModel.Dispatcher; namespace WcfService1 { public class LogOperationInspector : IPara

我正在使用日志记录web请求数据。我需要它来计算请求持续时间,并记录输入和输出内容

只要没有异常发生,它就可以正常工作。在异常情况下,将永远不会执行AfterCall事件

发生异常时是否有机会执行后调用?还是我需要另一种方法

下面是我的代码的简化版本:

using System;
using System.ServiceModel.Dispatcher;

namespace WcfService1
{
    public class LogOperationInspector : IParameterInspector
    {
        private string _serviceName;

        public LogOperationInspector(string serviceName)
        {
            this._serviceName = serviceName;
        }

        public object BeforeCall(string operationName, object[] inputs)
        {
            return LogCallModel.GetLogModel("MyTestOperation", inputs);
        }

        public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
        {
            var callModel = correlationState as LogCallModel;
            callModel.EndDate = DateTime.Now;

            // Log Start Date and End Date and calculate duration
        }
    }

    public class LogCallModel
    {
        public String OperationName { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }

        public static object GetLogModel(string operationName, object[] inputs)
        {
            var result = new LogCallModel();
            result.OperationName = operationName;
            result.StartDate = DateTime.Now;
            // Add some more properties for logging from the inputs field

            return result;
        }
    }
}

我建议使用标准的WCF方法,即使用事后调用,以获得成功的响应。在异常的情况下,您应该实现IErrorHandler,并让它的函数负责您的错误处理

public class LogOperationInspector : IParameterInspector
{
    public object BeforeCall(string operationName, object[] inputs)
    {
        // Before Call
    }

    public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
    {
        // Sucessful response 
    }
}

public class LogErrorInspector : IErrorHandler
{
    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        // Error Handling
    }

    public bool HandleError(Exception error)
    {
        // Error Handling
    }
}
剩下的唯一挑战是,您可能希望与这两种可能的场景共享调用前的状态。在事后调用中您通常可以使用相关状态执行该操作,但错误处理程序无法访问该状态。为了实现这一点并保持线程安全,可以使用.NET消息传递功能。通过使用此功能,可以在BeforeCallProvideFault之间共享请求上下文

public class LogOperationInspector : IParameterInspector
{
    public object BeforeCall(string operationName, object[] inputs)
    {
        CallContext.SetData("CallContext", CallObj);
    }

    public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
    {
        // Sucessful response 
    }
}

public class LogErrorInspector : IErrorHandler
{
    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        var CallObj = CallContext.GetData("CallContext");
    }

    public bool HandleError(Exception error)
    {
        // Error Handling
    }
}