【问题标题】:How to use IParameterInspector with WCF services correctly to log web requests also in an exception case?如何在异常情况下正确使用 IParameterInspector 和 WCF 服务来记录 Web 请求?
【发布时间】:2017-02-12 08:26:14
【问题描述】:

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

只要不发生异常,它就可以正常工作。如果出现异常,AfterCall 事件将永远不会被执行。

发生异常时是否有机会执行 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;
        }
    }
}

【问题讨论】:

    标签: c# .net wcf logging exception-handling


    【解决方案1】:

    我建议使用标准 WCF 方法,即使用 AfterCall 来获得成功的响应。在出现异常的情况下,您应该实现 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
        }
    }
    

    剩下的唯一挑战是您可能希望在两种可能的情况下共享 BeforeCall 的状态。在 AfterCall 中,您通常可以使用 CorrelationState 执行此操作,但 ErrorHandler 无法访问。为了实现这一点并保持线程安全,可以使用 .NET 消息传递功能CallContext。通过使用此功能,可以在 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
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多