Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.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# 如何从WCF服务端捕获传入和传出的XML_C#_Xml_Wcf_Web Services - Fatal编程技术网

C# 如何从WCF服务端捕获传入和传出的XML

C# 如何从WCF服务端捕获传入和传出的XML,c#,xml,wcf,web-services,C#,Xml,Wcf,Web Services,在我的解决方案中,我有三个项目。一个是WCF服务,另一个是Winforms应用程序,我在其中调用web服务,最后一个是类库,其中类已设计为扩展soap扩展类 我的目标是在从Winforms应用程序调用WCF服务时捕获响应和请求xml。当我试图捕获xml时,出现对象引用未设置错误 这是我的类库源代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.W

在我的解决方案中,我有三个项目。一个是WCF服务,另一个是Winforms应用程序,我在其中调用web服务,最后一个是类库,其中类已设计为扩展soap扩展类

我的目标是在从Winforms应用程序调用WCF服务时捕获响应和请求xml。当我试图捕获xml时,出现对象引用未设置错误

这是我的类库源代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.IO;
using System.Net;
using System.Xml;

namespace SoapLogger
{
public class TraceExtension : SoapExtension
{
    private Stream oldStream;
    private Stream newStream;

    private static XmlDocument xmlRequest;
    /// <summary>
    /// Gets the outgoing XML request sent to PayPal
    /// </summary>
    public static XmlDocument XmlRequest
    {
        get { return xmlRequest; }
    }

    private static XmlDocument xmlResponse;
    /// <summary>
    /// Gets the incoming XML response sent from PayPal
    /// </summary>
    public static XmlDocument XmlResponse
    {
        get { return xmlResponse; }
    }

    /// <summary>
    /// Save the Stream representing the SOAP request
    /// or SOAP response into a local memory buffer.
    /// </summary>
    /// <param name="stream">
    /// <returns></returns>
    public override Stream ChainStream(Stream stream)
    {
        oldStream = stream;
        newStream = new MemoryStream();
        return newStream;
    }

    /// <summary>
    /// If the SoapMessageStage is such that the SoapRequest or
    /// SoapResponse is still in the SOAP format to be sent or received,
    /// save it to the xmlRequest or xmlResponse property.
    /// </summary>
    /// <param name="message">
    public override void ProcessMessage(SoapMessage message)
    {
        switch (message.Stage)
        {
            case SoapMessageStage.BeforeSerialize:
                break;
            case SoapMessageStage.AfterSerialize:
                xmlRequest = GetSoapEnvelope(newStream);
                CopyStream(newStream, oldStream);
                break;
            case SoapMessageStage.BeforeDeserialize:
                CopyStream(oldStream, newStream);
                xmlResponse = GetSoapEnvelope(newStream);
                break;
            case SoapMessageStage.AfterDeserialize:
                break;
        }
    }

    /// <summary>
    /// Returns the XML representation of the Soap Envelope in the supplied stream.
    /// Resets the position of stream to zero.
    /// </summary>
    /// <param name="stream">
    /// <returns></returns>
    private XmlDocument GetSoapEnvelope(Stream stream)
    {
        XmlDocument xml = new XmlDocument();
        stream.Position = 0;
        StreamReader reader = new StreamReader(stream);
        xml.LoadXml(reader.ReadToEnd());
        stream.Position = 0;
        return xml;
    }

    /// <summary>
    /// Copies a stream.
    /// </summary>
    /// <param name="from">
    /// <param name="to">
    private void CopyStream(Stream from, Stream to)
    {
        TextReader reader = new StreamReader(from);
        TextWriter writer = new StreamWriter(to);
        writer.WriteLine(reader.ReadToEnd());
        writer.Flush();
    }
    #region NoOp
    /// <summary>
    /// Included only because it must be implemented.
    /// </summary>
    /// <param name="methodInfo">
    /// <param name="attribute">
    /// <returns></returns>
    public override object GetInitializer(LogicalMethodInfo methodInfo,
        SoapExtensionAttribute attribute)
    {
        return null;
    }

    /// <summary>
    /// Included only because it must be implemented.
    /// </summary>
    /// <param name="WebServiceType">
    /// <returns></returns>
    public override object GetInitializer(Type WebServiceType)
    {
        return null;
    }

    /// <summary>
    /// Included only because it must be implemented.
    /// </summary>
    /// <param name="initializer">
    public override void Initialize(object initializer)
    {
    }
    #endregion NoOp
}
这两条线导致对象引用错误

var soapRequest = SoapLogger.TraceExtension.XmlRequest.InnerXml;
var soapResponse = SoapLogger.TraceExtension.XmlResponse.InnerXml;
我只是不明白为什么我会出错

Winforms应用程序有一个
app.config
,我在其中注册类库程序集以捕获xml。这是我的
app.config
详细信息

<?xml version="1.0"?> 
<configuration> 
<system.serviceModel> 
<bindings> 
<basicHttpBinding> 
<binding name="TestServiceSoap"/> </basicHttpBinding> 
</bindings> <client> <endpoint address="http://localhost:6804/Service1.asmx" 
binding="basicHttpBinding" bindingConfiguration="TestServiceSoap" 
contract="ServiceRef.TestServiceSoap" name="TestServiceSoap"/> 
</client> 
</system.serviceModel> 
<system.web> 
<compilation debug="true" targetFramework="4.0" /> 
<webServices> <soapExtensionTypes> 
<add type="SoapLogger.TraceExtension,SoapLogger" priority="1" group="0" /> 
</soapExtensionTypes> </webServices> 
</system.web> 
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> 
</startup> </configuration>

我犯了什么样的错误还不清楚。我在类库方法中的每个方法上都设置了断点,但是当web服务调用时,类库中没有执行任何方法。我不想使用wireshark、fiddler之类的工具来捕获请求/响应xml,而是想通过编程来完成同样的事情

所以请告诉我我的错误是什么?为什么获取对象引用未设置错误?请看一看我的代码或转到url链接,告诉我我的方法有什么错误

  • 配置
  • 发送/接收一些消息
  • 获取日志查看器并打开跟踪输出
  • 利润
    导致此错误的原因是,在访问它们时,xmlRequest/xmlResponse尚未初始化。因此,请尝试检查null,或为它们创建默认实例

    从代码中,它们仅在
    ProcessMessage(SoapMessage){}
    中初始化,请确保在调用之前调用了该方法

     var soapRequest = SoapLogger.TraceExtension.XmlRequest.InnerXml;
     var soapResponse = SoapLogger.TraceExtension.XmlResponse.InnerXml;
    
    希望这有帮助

    编辑:

    仔细检查您的代码后,我意识到您编写的扩展(SoapExtension)是针对ASP.NET XML web服务的,它与WCF服务没有任何关系

    要检查WCF服务中的请求和应答,可以通过实现System.ServiceModel.dispatcher.IDispatchMessageInspector来扩展服务端的dispatcher


    您可以在这里找到示例,我们只需跟踪请求消息即可

    OperationContext context = OperationContext.Current;
    
    if (context != null && context.RequestContext != null)
    
    {
    
    Message msg = context.RequestContext.RequestMessage;
    
    string reqXML = msg.ToString();
    
    }
    

    还有另一种查看XML SOAP的方法-。与IDispatchMessageInspector/IClientMessageInspector的主要区别在于它在较低的级别上工作,因此它捕获原始字节内容,包括任何格式错误的xml

    为了使用这种方法实现跟踪,您需要将一个标准包装为新的,并将该自定义绑定应用到您的应用程序中的端点

    你也可以看到我在我的项目中是如何做到这一点的-
    textMessageEncoding、logging、,自定义绑定和。

    未找到。u plzz能否将我重定向到有关此主题的正确文章,从中我可以获得完整的工作代码示例,可以在我的pc中运行。感谢使用
    System.ServiceModel.Dispatcher.IDispatchMessageInspector的所有完整真实代码?对使用WebService ASMX的客户端有效?
    
    OperationContext context = OperationContext.Current;
    
    if (context != null && context.RequestContext != null)
    
    {
    
    Message msg = context.RequestContext.RequestMessage;
    
    string reqXML = msg.ToString();
    
    }