Wcf 记录ClientBase对象接收到的SOAP原始响应
我有一个应用程序,它使用服务引用生成的ClientBase对象调用第三方WCF SOAP服务。每隔一段时间,服务调用就会返回一个错误异常,而不是一条异常消息“处理请求时出错”,这是完全通用的 即使在服务错误期间,也应该有一个随响应返回的跟踪ID值,以便该服务的开发人员可以调试/排除任何问题。因此,理想情况下,我希望记录出现异常时返回到ClientBase对象的原始响应。如果可能的话,我不想记录每一条消息,那太过分了Wcf 记录ClientBase对象接收到的SOAP原始响应,wcf,logging,soap,Wcf,Logging,Soap,我有一个应用程序,它使用服务引用生成的ClientBase对象调用第三方WCF SOAP服务。每隔一段时间,服务调用就会返回一个错误异常,而不是一条异常消息“处理请求时出错”,这是完全通用的 即使在服务错误期间,也应该有一个随响应返回的跟踪ID值,以便该服务的开发人员可以调试/排除任何问题。因此,理想情况下,我希望记录出现异常时返回到ClientBase对象的原始响应。如果可能的话,我不想记录每一条消息,那太过分了 有没有一种方法可以使用ClientBase捕获这些信息?可能有某个上下文对象包含
有没有一种方法可以使用ClientBase捕获这些信息?可能有某个上下文对象包含原始响应内容?如果可能,这需要内置到我的应用程序中。我知道有一些工具充当客户端和服务之间的代理,可以记录http请求/响应,但这不是我想要的。在
ClientBase
本身,没有地方可以获取这些信息。但是您可以在客户端(IClientMessageInspector
)添加一个自定义消息检查器,在那里您可以看到正在接收的所有消息;对于这些消息,您可以检查IsFault
属性,如果为true,则根据需要记录消息
更新:添加示例代码
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
public class StackOverflow_12842014
{
[ServiceContract]
public interface ITest
{
[OperationContract]
string Echo(string text);
}
public class Service : ITest
{
public string Echo(string text)
{
if (text == "throw") throw new ArgumentException("Throwing as requested");
return text;
}
}
class MyClient : ClientBase<ITest>, ITest
{
public MyClient(Binding binding, EndpointAddress address)
: base(binding, address)
{
this.Endpoint.Behaviors.Add(new MyFaultLogger());
}
public string Echo(string text)
{
return this.Channel.Echo(text);
}
class MyFaultLogger : IEndpointBehavior, IClientMessageInspector
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(this);
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
if (reply.IsFault)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Fault received!: {0}", reply);
Console.ResetColor();
}
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
return null;
}
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
host.Description.Behaviors.Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults = true;
host.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "");
host.Open();
Console.WriteLine("Host opened");
MyClient client = new MyClient(new BasicHttpBinding(), new EndpointAddress(baseAddress));
Console.WriteLine(client.Echo("Hello"));
try
{
Console.WriteLine(client.Echo("throw"));
}
catch (Exception)
{
Console.WriteLine("The fault should have been traced");
}
client.Close();
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}
使用System.ServiceModel.Channels;
使用System.ServiceModel.Dispatcher;
公共类StackOverflow_12842014
{
[服务合同]
公共接口测试
{
[经营合同]
字符串回显(字符串文本);
}
公共类服务:ITest
{
公共字符串回显(字符串文本)
{
if(text==“throw”)抛出新的ArgumentException(“根据请求抛出”);
返回文本;
}
}
类MyClient:ClientBase,ITest
{
公共MyClient(绑定、端点地址)
:base(绑定、地址)
{
this.Endpoint.Behaviors.Add(新的MyFaultLogger());
}
公共字符串回显(字符串文本)
{
返回此.Channel.Echo(文本);
}
类MyFaultLogger:IEndpointBehavior,IClientMessageInspector
{
public void AddBindingParameters(ServiceEndpoint端点、BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint端点、ClientRuntime ClientRuntime)
{
添加(此);
}
公共无效ApplyDispatchBehavior(ServiceEndpoint端点、EndpointDispatcher端点Dispatcher)
{
}
公共void验证(ServiceEndpoint)
{
}
接收后公共无效(参考消息回复,对象关联状态)
{
if(reply.IsFault)
{
Console.ForegroundColor=ConsoleColor.Red;
WriteLine(“收到错误!:{0}”,回复);
Console.ResetColor();
}
}
发送请求前的公共对象(参考消息请求,IClientChannel通道)
{
返回null;
}
}
}
公共静态无效测试()
{
string baseAddress=“http://“+Environment.MachineName+”:8000/服务”;
ServiceHost主机=新ServiceHost(类型(服务),新Uri(基地址));
host.Description.Behaviors.Find().IncludeExceptionDetailInFaults=true;
AddServiceEndpoint(typeof(ITest),new BasicHttpBinding(),“”);
host.Open();
Console.WriteLine(“主机已打开”);
MyClient client=newmyclient(new BasicHttpBinding(),newendpointaddress(baseAddress));
Console.WriteLine(client.Echo(“Hello”);
尝试
{
Console.WriteLine(client.Echo(“throw”);
}
捕获(例外)
{
Console.WriteLine(“应该跟踪故障”);
}
client.Close();
控制台。写入(“按ENTER键关闭主机”);
Console.ReadLine();
host.Close();
}
}
> p>您可以考虑另一种捕获XML的方法。与IClientMessageInspector不同,它处理http正文的原始字节内容
您需要将标准包装为新的,并将该自定义绑定应用到您的应用程序中的端点
你也可以看看我是如何在我的项目中做到这一点的-
textMessageEncoding、logging、custom binding和.实现并插入IErrorHandler.providDefault
。请参阅@Paciv,这将是处理服务上的错误处理/日志记录的一种方法。我正在使用客户端对象调用第三方服务。我需要能够访问我的客户在我调用的服务出现故障异常时收到的实际SOAP响应。这比您描述的要多得多,但这是我所需要的一般解决方案。我将发布一些示例代码,因为您没有这样做,所以其他人可以看到这个解决方案是如何实现的。我用一些基于ClientBase的类的代码更新了答案,以跟踪传入的错误。非常感谢:)这就是我在应用程序中所做的。我正在使用一个服务引用,所以我创建了一个助手方法,该方法实例化自动生成的客户机类,然后注入自定义行为。这几乎是唯一的区别。我已经将IEndpointBehavior和IClientMessageInspector实现为两个独立的类,但这只是我个人的偏好。