拦截来自客户端的Web服务的SOAP消息

tra*_*art 23 c# soap web-services 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;
}
Run Code Online (Sandbox Code Playgroud)

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

但也许我只是做起来太困难了.例如,是否可以直接读取SoapClientMessage对象的内容?我已经阅读了一些文章,建议我应该在这里使用SoapExtensions,但是从我能理解的情况来看,只有我创建的'客户'本身就是一个Web服务,在这种情况下它不是.

有什么建议?

Saw*_*wan 51

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

本文将帮助您将服务引用添加到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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,将呼叫代码更改为:

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;
Run Code Online (Sandbox Code Playgroud)

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

并获得以下XML:

requestXML =

<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>
Run Code Online (Sandbox Code Playgroud)

responseXML的=

<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>
Run Code Online (Sandbox Code Playgroud)

****编辑2****

"添加Web引用"不是专用于ASMX而不是ASMX客户端技术,而"添加服务引用"不是WCF客户端技术,您可以使用它们来添加对ASMX,WCF,JSP开发的引用或PHP开发的Web服务,您需要您的应用程序使用.Net framework 3.5来使用"添加服务引用".

本文提到:

在Visual Studio中使用"添加Web引用"对话框时,将使用WSDL信息生成客户端代理,并将其添加到Visual Studio项目中.这通常用于ASMX服务,但您也可以使用"添加Web引用"对话框为WCF服务创建客户端代理.但是,您需要手动键入服务URL,并且生成的代理使用XML序列化,这是唯一支持的序列化类型.若要为支持数据协定序列化程序的WCF服务创建客户端代理,可以使用Svcutil.exe工具或使用.NET Framework 3.x的Visual Studio开发工具的"添加服务引用"功能.

  • 他似乎使用ASMX客户端技术"添加Web引用",而不是"添加服务引用",这是WCF客户端技术. (2认同)