在我的解决方案中,我有三个项目。一个是WCF服务,另一个是我调用Web服务的Winforms应用程序,最后一个是类库,其中类已经设计了扩展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
}
以下是我从Winforms应用程序调用Web服务的方法:
private void button1_Click(object sender, EventArgs e)
{
using (ServiceRef.TestServiceSoapClient oService = new ServiceRef.TestServiceSoapClient())
{
textBox1.Text = oService.HelloWorld("Sudip");
var soapRequest = SoapLogger.TraceExtension.XmlRequest.InnerXml;
var soapResponse = SoapLogger.TraceExtension.XmlResponse.InnerXml;
}
}
这两行导致对象引用错误
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>
当我搜索谷歌只是为了知道如何捕获请求/响应xml然后我得到了这么多文章。我跟着很多但没什么作用。
我不清楚是什么样的错误。我在我的类库方法中的每个方法都设置了断点,但是当web服务调用时,没有在类库中执行方法。我不想使用任何像wireshark,fiddler这样的工具来捕获请求/响应xml,而不是想以编程方式做同样的事情。
所以请指导我,我的错误是什么?为什么我得到对象引用没有设置错误?请查看我的代码或转到网址链接并告诉我我的方法有什么问题
答案 0 :(得分:12)
我们只需将请求消息跟踪为。
OperationContext context = OperationContext.Current;
if (context != null && context.RequestContext != null)
{
Message msg = context.RequestContext.RequestMessage;
string reqXML = msg.ToString();
}
答案 1 :(得分:4)
答案 2 :(得分:3)
错误是由于 xmlRequest / xmlResponse 在您访问时尚未初始化而导致的。因此,尝试检查null,或为它们创建默认实例。
从您的代码中,它们仅在ProcessMessage(SoapMessage message){}
中初始化,请确保在调用之前调用该方法
var soapRequest = SoapLogger.TraceExtension.XmlRequest.InnerXml;
var soapResponse = SoapLogger.TraceExtension.XmlResponse.InnerXml;
希望这有帮助。
编辑:
仔细检查您的代码后,我意识到您编写的扩展程序( SoapExtension )适用于 ASP.NET XML Web服务,并且它与WCF没有业务关系服务。
要检查请求并在WCF服务中回复,您可以通过实施 System.ServiceModel.Dispatcher.IDispatchMessageInspector 来扩展服务端的调度程序。
您可以在http://msdn.microsoft.com/en-us/library/ms733104%28v=vs.100%29.aspx
找到示例答案 3 :(得分:0)
还有另一种方法可以查看XML SOAP - custom MessageEncoder。与IDispatchMessageInspector / IClientMessageInspector的主要区别在于它在较低级别上工作,因此它捕获原始字节内容,包括任何格式错误的xml。
为了使用此方法实现跟踪,您需要将标准textMessageEncoding与custom message encoder包装为新binding element,并将该自定义绑定应用于config中的端点。
你也可以看看我在项目中是如何做到的 - wrapping textMessageEncoding,记录encoder,自定义绑定element和config。