You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用WCF Client调用SOAP服务时无法读取HTTP Statuscode

在.NET 6.0中获取SOAP服务调用的HTTP状态码

问题背景

我们基于.NET 6.0环境,通过以下代码调用SOAP服务:

public Task<MyResponseModel> SendAsync(MyRequestModel request)
{
    var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport)
    {
        OpenTimeout = TimeSpan.FromSeconds(30),
        SendTimeout = TimeSpan.FromSeconds(10),
    };
    var endpointAddress = new EndpointAddress("https://example.com/");
    ChannelFactory<IWcfClient> channelFactory = null;
    try
    {
        channelFactory = new ChannelFactory<IWcfClient>(binding, endpointAddress);
        channelFactory.Endpoint.EndpointBehaviors.Add(new InspectMessageBehavior());
        IWcfClient channel = channelFactory.CreateChannel();
        return channel.SendItemAsync(request);
    }
    catch (Exception)
    {
        if (channelFactory != null)
            channelFactory.Abort();
        throw;
    }
}

当SOAP服务端出现错误时,返回的错误信息完全一致,无法针对不同业务错误做流程处理,唯一的差异是HTTP状态码,但我们始终无法读取到这个状态码。第三方服务提供方不愿修改此行为,我们已经尝试过以下方法但均无效:

  • 直接读取异常信息
  • 实现IEndpointBehavior尝试读取状态码
  • 捕获ChannelFactory的Faulted、Closed等事件(Faulted事件未触发)

解决方案

可以通过自定义IClientMessageInspector,从WCF的HttpResponseMessageProperty中提取HTTP状态码,具体实现如下:

1. 实现自定义消息检查器

这个检查器会在收到服务回复后,提取HTTP状态码并保存:

public class HttpStatusCodeInspector : IClientMessageInspector
{
    public int? HttpStatusCode { get; private set; }

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        return null;
    }

    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        if (reply.Properties.TryGetValue(HttpResponseMessageProperty.Name, out var property))
        {
            var httpResponse = property as HttpResponseMessageProperty;
            HttpStatusCode = (int)httpResponse.StatusCode;
        }
    }
}

2. 实现对应的EndpointBehavior

用于将检查器注入到WCF客户端的运行时:

public class HttpStatusCodeBehavior : IEndpointBehavior
{
    public HttpStatusCodeInspector Inspector { get; } = new HttpStatusCodeInspector();

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.MessageInspectors.Add(Inspector);
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }

    public void Validate(ServiceEndpoint endpoint) { }
}

3. 修改调用代码,获取状态码

在调用SOAP服务时,通过自定义Behavior获取状态码,即使发生异常也能拿到:

public async Task<MyResponseModel> SendAsync(MyRequestModel request)
{
    var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport)
    {
        OpenTimeout = TimeSpan.FromSeconds(30),
        SendTimeout = TimeSpan.FromSeconds(10),
    };
    var endpointAddress = new EndpointAddress("https://example.com/");
    ChannelFactory<IWcfClient> channelFactory = null;
    HttpStatusCodeBehavior statusCodeBehavior = null;

    try
    {
        channelFactory = new ChannelFactory<IWcfClient>(binding, endpointAddress);
        statusCodeBehavior = new HttpStatusCodeBehavior();
        channelFactory.Endpoint.EndpointBehaviors.Add(statusCodeBehavior);
        
        IWcfClient channel = channelFactory.CreateChannel();
        var response = await channel.SendItemAsync(request);
        // 成功时也可以获取状态码
        var successStatusCode = statusCodeBehavior.Inspector.HttpStatusCode;
        return response;
    }
    catch (Exception)
    {
        if (channelFactory != null)
            channelFactory.Abort();
        
        // 异常时读取状态码,根据状态码做业务处理
        if (statusCodeBehavior?.Inspector.HttpStatusCode.HasValue == true)
        {
            var errorStatusCode = statusCodeBehavior.Inspector.HttpStatusCode.Value;
            // 示例:根据不同状态码执行不同逻辑
            // switch (errorStatusCode)
            // {
            //     case 400:
            //         // 处理参数错误
            //         break;
            //     case 500:
            //         // 处理服务内部错误
            //         break;
            // }
        }
        throw;
    }
}

原理说明

WCF在处理HTTP协议的SOAP调用时,会将底层HTTP响应的信息封装到HttpResponseMessageProperty中,这个属性可以从回复消息的Properties集合中取出。自定义的IClientMessageInspector会在收到服务回复后执行AfterReceiveReply方法,此时就能提取出HTTP状态码,无论服务返回成功还是SOAP错误,这个属性都会被正确填充。

内容的提问来源于stack exchange,提问作者Koen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 06:43:20