在获取 HTTP 400 响应代码的 WCF 客户端上获取响应

问题描述 投票:0回答:1

我正在使用下一个代码(在 .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代码吗?

谢谢。

.net wcf soap httpresponse protocolexception
1个回答
0
投票

首先,第二个问题: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>
© www.soinside.com 2019 - 2024. All rights reserved.