我正在使用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;
}
}
}
答案 0 :(得分: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 Messaging功能CallContext。通过使用此功能,可以在 BeforeCall 和 ProvideFault 之间共享请求上下文。
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
}
}