【发布时间】:2018-12-27 17:45:05
【问题描述】:
正如我们大多数人已经知道的那样,在 Visual Studio 2017 中,您可以使用相关的 WSDL 添加 Connected Service 并将其配置为指向您想要的 SOAP 服务。这会在 Reference.cs 文件中创建一组代理类,用于与相关 SOAP 服务进行交互。
有没有办法在某个时间点拦截转换后的 SOAP 过程 - 以编程方式 - 所以我们可以知道到底是什么 发送到目标服务?我问这个是因为我需要能够记录发送出去的实际 SOAP,因此不能选择使用单独的应用程序(例如 Fiddler)。
我仔细研究了 Reference.cs 文件中的代码,所有内容都被抽象得如此抽象,以至于我无法确定转换实际发生在哪里。
为了便于讨论,我使用了一个非常简单的免费 SOAP 服务,位于:http://www.dneonline.com/calculator.asmx
生成的Reference.cs 文件的内容显示在本文末尾。在该代码中,您可以看到客户端类的方法AddAsync(...),例如,调用base.Channel.AddAsync(intA, intB),该方法在CalculatorSoap 接口中定义。那么,如果Channel 是CalculatorSoap 接口,那么实际使用的具体类在哪里?这是我所说的如此多抽象的普遍性的一个例子。
我很高兴(也很感激)听到你们任何人对这里发生的事情的任何想法。
谢谢。
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// //
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CalculatorSoapServiceReference
{
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.0.1")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="CalculatorSoapServiceReference.CalculatorSoap")]
public interface CalculatorSoap
{
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/Add", ReplyAction="*")]
System.Threading.Tasks.Task<int> AddAsync(int intA, int intB);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/Subtract", ReplyAction="*")]
System.Threading.Tasks.Task<int> SubtractAsync(int intA, int intB);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/Multiply", ReplyAction="*")]
System.Threading.Tasks.Task<int> MultiplyAsync(int intA, int intB);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/Divide", ReplyAction="*")]
System.Threading.Tasks.Task<int> DivideAsync(int intA, int intB);
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.0.1")]
public interface CalculatorSoapChannel : CalculatorSoapServiceReference.CalculatorSoap, System.ServiceModel.IClientChannel
{
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.0.1")]
public partial class CalculatorSoapClient : System.ServiceModel.ClientBase<CalculatorSoapServiceReference.CalculatorSoap>, CalculatorSoapServiceReference.CalculatorSoap
{
/// <summary>
/// Implement this partial method to configure the service endpoint.
/// </summary>
/// <param name="serviceEndpoint">The endpoint to configure</param>
/// <param name="clientCredentials">The client credentials</param>
static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);
public CalculatorSoapClient(EndpointConfiguration endpointConfiguration) :
base(CalculatorSoapClient.GetBindingForEndpoint(endpointConfiguration), CalculatorSoapClient.GetEndpointAddress(endpointConfiguration))
{
this.Endpoint.Name = endpointConfiguration.ToString();
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
}
public CalculatorSoapClient(EndpointConfiguration endpointConfiguration, string remoteAddress) :
base(CalculatorSoapClient.GetBindingForEndpoint(endpointConfiguration), new System.ServiceModel.EndpointAddress(remoteAddress))
{
this.Endpoint.Name = endpointConfiguration.ToString();
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
}
public CalculatorSoapClient(EndpointConfiguration endpointConfiguration, System.ServiceModel.EndpointAddress remoteAddress) :
base(CalculatorSoapClient.GetBindingForEndpoint(endpointConfiguration), remoteAddress)
{
this.Endpoint.Name = endpointConfiguration.ToString();
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
}
public CalculatorSoapClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
public System.Threading.Tasks.Task<int> AddAsync(int intA, int intB)
{
return base.Channel.AddAsync(intA, intB);
}
public System.Threading.Tasks.Task<int> SubtractAsync(int intA, int intB)
{
return base.Channel.SubtractAsync(intA, intB);
}
public System.Threading.Tasks.Task<int> MultiplyAsync(int intA, int intB)
{
return base.Channel.MultiplyAsync(intA, intB);
}
public System.Threading.Tasks.Task<int> DivideAsync(int intA, int intB)
{
return base.Channel.DivideAsync(intA, intB);
}
public virtual System.Threading.Tasks.Task OpenAsync()
{
return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndOpen));
}
public virtual System.Threading.Tasks.Task CloseAsync()
{
return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginClose(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndClose));
}
private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
{
if ((endpointConfiguration == EndpointConfiguration.CalculatorSoap))
{
System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
result.MaxBufferSize = int.MaxValue;
result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
result.MaxReceivedMessageSize = int.MaxValue;
result.AllowCookies = true;
return result;
}
if ((endpointConfiguration == EndpointConfiguration.CalculatorSoap12))
{
System.ServiceModel.Channels.CustomBinding result = new System.ServiceModel.Channels.CustomBinding();
System.ServiceModel.Channels.TextMessageEncodingBindingElement textBindingElement = new System.ServiceModel.Channels.TextMessageEncodingBindingElement();
textBindingElement.MessageVersion = System.ServiceModel.Channels.MessageVersion.CreateVersion(System.ServiceModel.EnvelopeVersion.Soap12, System.ServiceModel.Channels.AddressingVersion.None);
result.Elements.Add(textBindingElement);
System.ServiceModel.Channels.HttpTransportBindingElement httpBindingElement = new System.ServiceModel.Channels.HttpTransportBindingElement();
httpBindingElement.AllowCookies = true;
httpBindingElement.MaxBufferSize = int.MaxValue;
httpBindingElement.MaxReceivedMessageSize = int.MaxValue;
result.Elements.Add(httpBindingElement);
return result;
}
throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
}
private static System.ServiceModel.EndpointAddress GetEndpointAddress(EndpointConfiguration endpointConfiguration)
{
if ((endpointConfiguration == EndpointConfiguration.CalculatorSoap))
{
return new System.ServiceModel.EndpointAddress("http://www.dneonline.com/calculator.asmx");
}
if ((endpointConfiguration == EndpointConfiguration.CalculatorSoap12))
{
return new System.ServiceModel.EndpointAddress("http://www.dneonline.com/calculator.asmx");
}
throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
}
public enum EndpointConfiguration
{
CalculatorSoap,
CalculatorSoap12,
}
}
}
【问题讨论】:
-
对于#3,只需加载 Telerik Fiddler 并观察流量。
-
在框架的某个地方,你为什么在乎?
-
Here's the thing...I need to be able to grab the SOAP for logging purposes. Using a monitoring application, such as Fiddler, is not an option. I need to do this in code.-- 那么这就是你应该在帖子中提出的问题。
标签: c# visual-studio web-services wcf soap