在将SOAP消息发送到.NET中的Web服务之前获取该消息
我正在调用外部HTTPS Web服务 为了检查错误,所有者需要我发送的SOAP请求 我有一个web引用和VS2008生成的代理类 是否有办法在发送SOAP消息之前查看它?在将SOAP消息发送到.NET中的Web服务之前获取该消息,.net,web-services,soap,.net,Web Services,Soap,我正在调用外部HTTPS Web服务 为了检查错误,所有者需要我发送的SOAP请求 我有一个web引用和VS2008生成的代理类 是否有办法在发送SOAP消息之前查看它? 我在想一些.net代码。。。因为我尝试的嗅探器没有“看到”Web服务调用,所以不知道为什么。您需要的是一个SoapExtension。这里有很多很好的例子: 其中一篇文章链接到: 还可以搜索:如果您在更严格的环境中工作,并且没有使用Fiddler之类的应用程序的特权,您可以执行以下操作: ProxyClass _cla
我在想一些.net代码。。。因为我尝试的嗅探器没有“看到”Web服务调用,所以不知道为什么。您需要的是一个SoapExtension。这里有很多很好的例子: 其中一篇文章链接到:
还可以搜索:如果您在更严格的环境中工作,并且没有使用Fiddler之类的应用程序的特权,您可以执行以下操作:
ProxyClass _class = new ProxyClass();
var requestInterceptor = new CustomInspectorBehavior();
_client.Endpoint.Behaviors.Add(requestInterceptor);
使用(var reader=new System.IO.StreamReader(Request.InputStream))
{
结果=reader.ReadToEnd();
}
这不是一个理想或漂亮的解决方案,但如果您在一个适度受限的环境中工作,它可以完成工作。您可以在Submit之前简单地序列化请求对象,如下所示:
var sreq = new SomeSoapRequest();
// ... fill in here ...
var serxml = new System.Xml.Serialization.XmlSerializer(sreq.GetType());
var ms = new MemoryStream();
serxml.Serialize(ms, sreq);
string xml = Encoding.UTF8.GetString(ms.ToArray());
// in xml string you have SOAP request
var client = new ServiceClient();
var soapInspector = new SoapInspectorBehavior();
client.Endpoint.EndpointBehaviors.Add(soapInspector);
您可以使用IClientMEssageInspector和IEndpointBehavior来完成此操作。我发现使用这种方法可以捕获准确的soap请求,就像fiddler请求一样: 在同一项目中创建如下类:
public class ClientMessageInspector : System.ServiceModel.Dispatcher.IClientMessageInspector
{
#region IClientMessageInspector Members
public string LastRequestXml { get; private set; }
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
string requestHeaderName = request.Headers.Action.Replace("urn:#",string.Empty);
LastRequestXml = request.ToString();
string serializedRequestFile = string.Format(requestHeaderName + "_request_{0}.xml", DateTime.Now.ToString("yyyyMMddHHmmss"));
string exportedFolder = ConfigurationManager.AppSettings["SubmittedRequestXmLocation"];
printSoapRequest(request, exportedFolder, serializedRequestFile);
return request;
}
public void printSoapRequest(System.ServiceModel.Channels.Message request, string exportedFolder, string fileName)
{
if (exportedFolder.Equals(string.Empty))
return;
if (!Directory.Exists(exportedFolder))
{
Directory.CreateDirectory(exportedFolder);
}
string exportedFile = string.Format("{0}\\{1}", exportedFolder, fileName);
if (File.Exists(exportedFile))
{
File.Delete(exportedFile);
}
string strRequestXML = request.ToString();
XDocument xDoc = XDocument.Parse(strRequestXML);
XmlWriter xw = XmlWriter.Create(exportedFile);
xDoc.Save(xw);
xw.Flush();
xw.Close();
LogOutput("Request file exported: " + exportedFile);
}
}
public class CustomInspectorBehavior : IEndpointBehavior
{
private readonly ClientMessageInspector clientMessageInspector = new ClientMessageInspector();
public string LastRequestXml
{
get { return clientMessageInspector.LastRequestXml; }
}
public string LastResponseXml
{
get { return clientMessageInspector.LastRequestXml; }
}
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(clientMessageInspector);
}
}
然后你可以这样称呼它:
ProxyClass _class = new ProxyClass();
var requestInterceptor = new CustomInspectorBehavior();
_client.Endpoint.Behaviors.Add(requestInterceptor);
当您调用服务方法时,它将自动执行拦截器并打印输出。使用这种方式,您还可以在发送到服务器之前操作soap消息 将其添加到web.config或App.config文件的元素中。它将在项目的bin/Debug文件夹中创建一个trace.log文件。或者,可以使用initializeData属性为日志文件指定绝对路径
<system.diagnostics>
<trace autoflush="true"/>
<sources>
<source name="System.Net" maxdatasize="9999" tracemode="protocolonly">
<listeners>
<add name="TraceFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="trace.log"/>
</listeners>
</source>
</sources>
<switches>
<add name="System.Net" value="Verbose"/>
</switches>
</system.diagnostics>
它警告不允许使用maxdatasize和tracemode属性,但它们会增加可记录的数据量,并避免使用十六进制记录所有内容。@mting923的建议非常有用,谢谢 其他想法(例如利用SoapExtension,或创建“spy”类a la)很有趣,但不能用于.NETCore。但生成的SOAP代理类仍然只是一个隐藏的WCF客户机,因此IClientMessageInspector方法非常有效,即使对于调用旧SOAP web服务的.NET核心Azure函数也是如此 在上面的示例中,暗示了响应wireup,但未完全显示。另外,在最新的.NET核心API中,
MessageInspectors
现在是ClientMessageInspectors
,行为现在是EndpointBehaviors
。因此,为了完整起见,以下内容适用于我在.NET Core 3.1 Azure函数中的工作:
public class SoapMessageInspector : IClientMessageInspector
{
public string LastRequestXml { get; private set; }
public string LastResponseXml { get; private set; }
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
LastRequestXml = request.ToString();
return request;
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
LastResponseXml = reply.ToString();
}
}
public class SoapInspectorBehavior : IEndpointBehavior
{
private readonly SoapMessageInspector inspector_ = new SoapMessageInspector();
public string LastRequestXml => inspector_.LastRequestXml;
public string LastResponseXml => inspector_.LastResponseXml;
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(inspector_);
}
}
然后可以这样设置:
var sreq = new SomeSoapRequest();
// ... fill in here ...
var serxml = new System.Xml.Serialization.XmlSerializer(sreq.GetType());
var ms = new MemoryStream();
serxml.Serialize(ms, sreq);
string xml = Encoding.UTF8.GetString(ms.ToArray());
// in xml string you have SOAP request
var client = new ServiceClient();
var soapInspector = new SoapInspectorBehavior();
client.Endpoint.EndpointBehaviors.Add(soapInspector);
在客户端代理上调用web服务调用后,soapInspector.LastRequestXml
和soapInspector.LastResponseXml
将包含原始SOAP请求和响应(作为字符串)。第二个链接有多个选项。公认的答案不一定是最好的(所有三种解决方案都是好的)。仅供参考,我最喜欢Fiddler选项。我使用Web服务引用,而不是WCF引用。如果您使用Web服务引用,您完全可以从头构建整个soap信封。但是,我不推荐它,因为它有可靠的实现和现代的.Soap扩展(公认的答案)有些过时。一般来说,这种方法——通常是“更好”的选择。非常容易添加并立即工作。诊断显示请求和响应SOAP信封以及一些网络跟踪。