Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在客户端截获来自和指向web服务的SOAP消息_C#_Web Services_Soap_Asmx - Fatal编程技术网

C# 在客户端截获来自和指向web服务的SOAP消息

C# 在客户端截获来自和指向web服务的SOAP消息,c#,web-services,soap,asmx,C#,Web Services,Soap,Asmx,我有一个与web服务通信的客户端。我与之通信的类是通过wsdl.exe生成的C#类。我现在想记录所有传入和传出的消息 到目前为止,我所做的是编写一个从自动生成的C#类继承的类,我已经重写了getReaderformMessage方法。这样,我可以访问传入消息,大致如下所示: protected override XmlReader GetReaderForMessage(SoapClientMessage message, int bufferSize) { System.Xml.Xml

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

到目前为止,我所做的是编写一个从自动生成的C#类继承的类,我已经重写了getReaderformMessage方法。这样,我可以访问传入消息,大致如下所示:

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消息的内容,另一个用于返回方法调用方。另外,对于getWritePerformMessage方法,我不能真正做到同样的事情

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


有什么建议吗?

我建议考虑使用a,我认为它非常适合这种情况。下面是一些描述该过程的链接

要使用此解决方案,您需要使用“添加服务引用”而不是“添加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;
    }
}
然后,将呼叫代码更改为:

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服务,我在以下方面进行了测试:

并获得以下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>

提到:

在Visual Studio中使用“添加Web引用”对话框时,客户端 代理使用WSDL信息生成,并添加到可视化 工作室项目。这通常用于ASMX服务,但您可以 还可以使用“添加Web引用”对话框为创建客户端代理 WCF服务。但是,您需要手动键入服务URL,然后 生成的代理使用XML序列化,这是唯一的 支持的序列化类型。为WCF创建客户端代理 支持数据协定序列化程序的服务,可以使用 Svcutil.exe工具或使用 用于.NETFramework 3.x的VisualStudio开发工具


好啊还有一个问题。我现在有一个从wsdl生成的类继承的类。这个类有一个Login方法,它从“wsdl”类调用Login方法。当我将扩展应用于这个wsdl类时,一切似乎都正常工作,但我不希望这样,因为当web服务更改时,可以重新生成这个类。现在我想把这个扩展应用到我自己的类中,但是扩展类中的方法没有被调用。。。有什么建议吗?你不使用WCF有什么原因吗?我可以回答你的问题@JohnSaunders。我使用的是大量“有效”的遗留代码,企业不希望它“无效”,因此不赞成对“有效”代码进行任何更改。@ChrisHayes:you@trabart?如果没有,那你怎么回答我问他的问题呢。顺便说一句,我同意“如果它没有坏,就不要修理它”。但在我看来,修改现有代码(例如,通过添加日志记录)的需要意味着代码“坏了”。特别是,使用WCF比使用ASMX更容易完成OP想要做的事情。如果代码继续需要更改,那么值得考虑升级。类似地,需要频繁更改的VB6代码应该升级到.NET,因为它将使更改更加容易。特拉巴特,我有类似的项目边界-服务是带有basicHttpBinding的WCF服务,但客户端仅限于使用.NET Framework 2.0。我发现了WCF客户机/服务器解决方案的负载,但不适用于混合解决方案。最后,我使用了@Ceottaki文章中描述的解决方案。希望有帮助。他似乎在使用“添加Web引用”,即ASMX客户端技术,而不是“添加服务引用”,即WCF客户端技术。你错了。WCF包括客户端代码和服务器端代码。“添加服务引用”为任何类型的服务创建WCF客户端。但他可以更改生成代理类的方式,使用svcutil.exe而不是wsdl.exe,并按照您所说的生成WCF客户端!!他可以很容易做到这一点,即使他的服务不是WCF服务,我已经在我的解决方案中提到了这一点。完美!非常感谢。要从一个C#客户机的JavaWeb服务SoapFault异常中获得详细信息让我很难,使用这种技术我可以解决这个问题。干杯
<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>