Rom*_*ias 16 .net soap web-services
我正在调用外部HTTPS Web服务.
为了检查出错了什么,所有者需要我发送的SOAP请求.
我有一个Web引用和由VS 2008生成的生成的代理类...
有没有办法在发送之前查看SOAP消息?
我正在考虑一些.net代码...因为我试过的Sniffer没有"看到"web服务调用不知道为什么.
diz*_*128 12
在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
Run Code Online (Sandbox Code Playgroud)
你需要的是SoapExtension.这里有很多很好的例子:
从在ASP.net中运行的Web引用客户端获取RAW Soap数据
其中一篇文章链接到:http: //msdn.microsoft.com/en-us/magazine/cc164007.aspx
同时搜索SO:https://stackoverflow.com/search?q = SoapExtension
@mting923 的建议真的很有帮助,谢谢!
其他想法(例如,利用 SoapExtension,或创建“间谍”类 a la如何访问 SOAP 响应)很有趣,但不能在 .NET Core 中使用。但是生成的 SOAP 代理类仍然只是底层的 WCF 客户端,因此 IClientMessageInspector 方法是一种享受,即使对于调用旧 SOAP Web 服务的 .NET Core Azure 函数也是如此。
在上面的例子中,响应连线是隐含的,但没有完全显示。此外,在最新的 .NET Core API 中,MessageInspectors
现在ClientMessageInspectors
和Behaviors
现在都是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_);
}
}
Run Code Online (Sandbox Code Playgroud)
然后它可以像这样设置:
var client = new ServiceClient();
var soapInspector = new SoapInspectorBehavior();
client.Endpoint.EndpointBehaviors.Add(soapInspector);
Run Code Online (Sandbox Code Playgroud)
在客户端代理调用Web服务调用,后soapInspector.LastRequestXml
和soapInspector.LastResponseXml
将包含原始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>
Run Code Online (Sandbox Code Playgroud)
它警告不允许使用 maxdatasize 和tracemode 属性,但它们会增加可以记录的数据量,并避免以十六进制记录所有内容。
您可以使用IClientMEssageInspector和IEndpointBehavior来完成此任务。我发现使用这种方法可以捕获确切的肥皂请求,就像提琴手一样:
在同一项目中创建一个像这样的类:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以像下面这样调用它:
ProxyClass _class = new ProxyClass();
var requestInterceptor = new CustomInspectorBehavior();
_client.Endpoint.Behaviors.Add(requestInterceptor);
Run Code Online (Sandbox Code Playgroud)
当您调用service方法时,它将自动执行拦截器并打印输出。使用这种方式,您还可以在发送到服务器之前操纵肥皂消息!
归档时间: |
|
查看次数: |
53855 次 |
最近记录: |