c# - 在客户端拦截来自和发往 Web 服务的 SOAP 消息

标签 c# web-services soap asmx

我有一个与 Web 服务通信的客户端。我与之通信的类是通过wsdl.exe生成的C#类。我现在想记录所有传入和传出的消息。

到目前为止,我所做的是编写一个继承自自动生成的 C# 类的类,并且覆盖了 GetReaderForMessage 方法。这样我就可以或多或少地像这样访问传入的消息:

protected override XmlReader GetReaderForMessage(SoapClientMessage message, int bufferSize)
{
    System.Xml.XmlReader aReader = base.GetReaderForMessage(message, bufferSize);
    System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
    doc.Load(aReader);
    string content = doc.InnerXml.ToString();
    System.Xml.XmlReader aReader2 = System.Xml.XmlReader.Create(new System.IO.StringReader(content));

    return aReader2;
}

显然我对这个解决方案不太满意,因为基本上我是在创建两个 xml 阅读器。一个读取 SOAP 消息的内容,一个返回给方法调用者。另外,我真的不能用 GetWriterForMessage 方法做同样的事情。

但可能是我做的事情太难了。例如,是否可以直接读取 SoapClientMessage 对象的内容?我读过一些建议我应该在这里使用 SoapExtensions 的文章,但据我所知,只有当我创建的“客户端”本身是一个 Web 服务时,这才有效,而在这种情况下它不是。

有什么建议吗?

最佳答案

您需要使用“添加服务引用”而不是“添加 Web 引用”功能来使用此解决方案,如果服务是 ASMX 或 WCF,则可以使用它。 (您需要使用 .NET Framework 3.X 才能使用此功能)

This article将帮助您将服务引用添加到您的 C# 项目。

要拦截请求和响应的 XML,请实现这两个类:

public class InspectorBehavior : IEndpointBehavior
{
    public string LastRequestXML { 
        get
        {
            return myMessageInspector.LastRequestXML;
        }
    }

    public string LastResponseXML { 
        get
        {
            return myMessageInspector.LastResponseXML;
        }
    }


    private MyMessageInspector myMessageInspector = new MyMessageInspector();
    public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {

    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {

    }

    public void Validate(ServiceEndpoint endpoint)
    {

    }


    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.MessageInspectors.Add(myMessageInspector );
    }
}





public class MyMessageInspector : IClientMessageInspector
{
    public string LastRequestXML { get; private set; }
    public string LastResponseXML { get; private set; }
    public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
    {
        LastResponseXML = reply.ToString();
    }

    public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
    {
        LastRequestXML = request.ToString();
        return request;
    }
}

然后,将调用代码更改为:

MyTestServiceSoapClient client = new MyTestServiceSoapClient();
var requestInterceptor = new InspectorBehavior();
client.Endpoint.Behaviors.Add(requestInterceptor );
client.DoSomething("param1", "param2", "param3");
string requestXML = requestInterceptor.LastRequestXML;
string responseXML = requestInterceptor.LastResponseXML;

****编辑**** 这与服务器端技术无关,您可以将它与 WCF、ASMX、PHP 等 Web 服务一起使用,我已经测试过: http://www.w3schools.com/webservices/tempconvert.asmx

并获得以下 XML:

请求XML=

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/CelsiusToFahrenheit</Action>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <CelsiusToFahrenheit xmlns="http://tempuri.org/">
      <Celsius>50</Celsius>
    </CelsiusToFahrenheit>
  </s:Body>
</s:Envelope>

响应XML=

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <s:Header xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" />
  <soap:Body>
    <CelsiusToFahrenheitResponse xmlns="http://tempuri.org/">
      <CelsiusToFahrenheitResult>122</CelsiusToFahrenheitResult>
    </CelsiusToFahrenheitResponse>
  </soap:Body>
</soap:Envelope>

****编辑 2****

“Add Web Reference”不是专门针对ASMX的,不是ASMX客户端技术,“Add Service Reference”不是WCF客户端技术,你可以使用两者来添加对ASMX、WCF、 JSP开发或PHP开发,web service,需要你的应用使用.Net framework 3.5才能使用“Add Service Reference”。

This article提及:

When using the Add Web Reference dialog box in Visual Studio, a client proxy is generated using WSDL information and is added to the Visual Studio project. This is usually used for ASMX services, but you can also use the Add Web Reference dialog box to create a client proxy for WCF services. However, you need to manually type the service URL, and the proxy that is generated uses XML serialization, which is the only type of serialization supported. To create client proxies for WCF services that support the data contract serializer, you can use the Svcutil.exe tool or use the Add Service Reference feature of the Visual Studio Development Tools for the .NET Framework 3.x.

关于c# - 在客户端拦截来自和发往 Web 服务的 SOAP 消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3879199/

相关文章:

web-services - 在 JSON 中将缺失值显示为 null 或根本不显示

java - Glassfish 基本身份验证错误

PHP SoapClient 将数组转换为字符串

java - 为什么在没有配置信任存储位置的情况下从 SoapUI 接受了 SOAP 请求?

c# - 如何在 vNext 依赖注入(inject)中创建构造函数订阅

c# - 数据集的插入/删除/修改的正确顺序是什么?

java - 如何在 Glass Fish Server/Apache Tomcat 上部署 Rest Web 服务?

c# - 如何在 OrientDB .Net API 中执行 Massiveinsert?

c# - 未知 while while 语句

json - Spring Web 服务和 Json