Как многие из нас уже знают, в Visual Studio 2017 вы можете добавить Connected Service
и настроить его так, чтобы он указывал на желаемую службу SOAP, используя соответствующий WSDL.Это создает набор прокси-классов в файле 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,
}
}
}