我正在使用下一个代码(在 .NET 7 中)作为我无法控制的 Java SOAP Web 服务的客户端:
namespace ActuacionMov
{
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.2.0-preview1.23462.5")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://webservice", ConfigurationName="ActuacionMov.ActuacionPortType")]
public interface ActuacionPortType
{
[System.ServiceModel.OperationContractAttribute(Action="urn:actuacion", ReplyAction="urn:actuacionResponse")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
System.Threading.Tasks.Task<ActuacionMov.actuacionResponse> actuacionAsync(ActuacionMov.actuacionRequest request);
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.2.0-preview1.23462.5")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://webservice")]
public partial class actuacion
{
private string datosField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=0)]
public string datos
{
get
{
return this.datosField;
}
set
{
this.datosField = value;
}
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.2.0-preview1.23462.5")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
public partial class actuacionRequest
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservice", Order=0)]
public ActuacionMov.actuacion actuacion;
public actuacionRequest()
{
}
public actuacionRequest(ActuacionMov.actuacion actuacion)
{
this.actuacion = actuacion;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.2.0-preview1.23462.5")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
public partial class actuacionResponse
{
[System.ServiceModel.MessageBodyMemberAttribute(Name="actuacionResponse", Namespace="http://webservice", Order=0)]
[System.Xml.Serialization.XmlArrayItemAttribute("result", IsNullable=false)]
public string[] actuacionResponse1;
public actuacionResponse()
{
}
public actuacionResponse(string[] actuacionResponse1)
{
this.actuacionResponse1 = actuacionResponse1;
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.2.0-preview1.23462.5")]
public interface ActuacionPortTypeChannel : ActuacionMov.ActuacionPortType, System.ServiceModel.IClientChannel
{
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.2.0-preview1.23462.5")]
public partial class ActuacionPortTypeClient : System.ServiceModel.ClientBase<ActuacionMov.ActuacionPortType>, ActuacionMov.ActuacionPortType
{
/// <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 ActuacionPortTypeClient(EndpointConfiguration endpointConfiguration) :
base(ActuacionPortTypeClient.GetBindingForEndpoint(endpointConfiguration), ActuacionPortTypeClient.GetEndpointAddress(endpointConfiguration))
{
this.Endpoint.Name = endpointConfiguration.ToString();
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
}
public ActuacionPortTypeClient(EndpointConfiguration endpointConfiguration, string remoteAddress) :
base(ActuacionPortTypeClient.GetBindingForEndpoint(endpointConfiguration), new System.ServiceModel.EndpointAddress(remoteAddress))
{
this.Endpoint.Name = endpointConfiguration.ToString();
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
}
public ActuacionPortTypeClient(EndpointConfiguration endpointConfiguration, System.ServiceModel.EndpointAddress remoteAddress) :
base(ActuacionPortTypeClient.GetBindingForEndpoint(endpointConfiguration), remoteAddress)
{
this.Endpoint.Name = endpointConfiguration.ToString();
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
}
public ActuacionPortTypeClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
System.Threading.Tasks.Task<ActuacionMov.actuacionResponse> ActuacionMov.ActuacionPortType.actuacionAsync(ActuacionMov.actuacionRequest request)
{
return base.Channel.actuacionAsync(request);
}
public System.Threading.Tasks.Task<ActuacionMov.actuacionResponse> actuacionAsync(ActuacionMov.actuacion actuacion)
{
ActuacionMov.actuacionRequest inValue = new ActuacionMov.actuacionRequest();
inValue.actuacion = actuacion;
return ((ActuacionMov.ActuacionPortType)(this)).actuacionAsync(inValue);
}
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));
}
private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
{
if ((endpointConfiguration == EndpointConfiguration.ActuacionHttpSoap11Endpoint))
{
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;
result.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.Transport;
return result;
}
if ((endpointConfiguration == EndpointConfiguration.ActuacionHttpSoap12Endpoint))
{
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.HttpsTransportBindingElement httpsBindingElement = new System.ServiceModel.Channels.HttpsTransportBindingElement();
httpsBindingElement.AllowCookies = true;
httpsBindingElement.MaxBufferSize = int.MaxValue;
httpsBindingElement.MaxReceivedMessageSize = int.MaxValue;
result.Elements.Add(httpsBindingElement);
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.ActuacionHttpSoap11Endpoint))
{
return new System.ServiceModel.EndpointAddress("https://desajboss.bilbokoudala.lan/ServicioActuacionMOV/services/Actuacion");
}
if ((endpointConfiguration == EndpointConfiguration.ActuacionHttpSoap12Endpoint))
{
return new System.ServiceModel.EndpointAddress("https://desajboss.bilbokoudala.lan/ServicioActuacionMOV/services/Actuacion");
}
throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
}
public enum EndpointConfiguration
{
ActuacionHttpSoap11Endpoint,
ActuacionHttpSoap12Endpoint,
}
}
}
如果 HTTP 响应代码在 200-299 或 500 之间,我工作正常,但是当代码为 400 时,我会收到一个没有任何信息的异常 ProtocolException。
如果我使用 SOAP UI 测试客户端,我可以看到带有错误描述的响应。另外,我正在调试
ClientBase
类的 Microsoft 内部代码,我可以看到错误,但我注意到,即使响应是可访问的,但首先抛出异常。
我尝试使用从自定义
IClientMessageInspector
创建的自定义 IEndpointBehavior
来获取 AfterReceiveReply
中的响应,但从未调用此方法。不像正确调用的BeforeSendRequest
。
这是我使用的代码:
static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials)
{
serviceEndpoint.EndpointBehaviors.Add(new CustomEndpointBehavior());
}
public class CustomEndpointBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new CustomMessageInspector());
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
public class CustomMessageInspector : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
// Nerver arrives here
if (reply.IsFault)
{
// When HTTP 500 error no enter here
}
}
public void BeforeSendRequest(ref Message request, object clientChannel)
{
// Always enter here
}
}
有什么办法可以得到回复吗?
有什么办法可以改变收到的HTTP代码吗?
谢谢。
首先,第二个问题:HTTP代码本身是一个标准协议,作为通信规则,不能随意修改。但是,在开发 Web 应用程序时,您可以通过自定义服务器端代码来控制 HTTP 请求的响应方式。这包括返回不同的 HTTP 状态代码、标头和响应正文内容。
200-299:响应成功。这样就可以正常运行了。
500 内部服务器错误:服务器遇到意外情况,无法完成请求。是一条通用错误消息,表示服务器无法处理请求,但确切原因尚不清楚。你说你可以工作,我想你需要再确认一下。
对于第一个问题,您可以添加日志文件来查看WCF服务的执行情况。
Web.config
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Information,ActivityTracing"
propagateActivity="true">
<listeners>
<add name="xml" />
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="xml" />
</listeners>
</source>
</sources>
<sharedListeners>
<add initializeData="C:\logs\TracingAndLogging-service.svclog" type="System.Diagnostics.XmlWriterTraceListener"
name="xml" />
</sharedListeners>
<trace autoflush="true" />
</system.diagnostics>