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

迁移遗留SOAP项目:CoreWCF自定义HTTP状态码配置方法问询

CoreWCF 自定义HTTP状态码解决方案(兼容遗留SOAP服务)

针对你在CoreWCF中需要保留遗留SOAP服务自定义HTTP状态码的需求,以下是具体实现方案:


问题1:处理完成后返回HTTP 202状态码

CoreWCF托管在ASP.NET Core之上,可通过IHttpContextAccessor直接操作请求上下文修改响应状态码,避免IsOneWay=true的立即返回问题。

步骤1:注册IHttpContextAccessor服务

在Startup.cs的ConfigureServices方法中添加:

services.AddHttpContextAccessor();

步骤2:在服务类中注入并设置状态码

修改DemoService.cs,注入IHttpContextAccessor并在满足业务条件时设置状态码:

using CoreWCF;
using Microsoft.AspNetCore.Http;
using System.Net;

namespace CoreWcf.Samples.Http
{
    public class DemoService : IDemo
    {
        private readonly IHttpContextAccessor _httpContextAccessor;

        public DemoService(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public string DemoRequest(string tagid, string readerid, string datetime)
        {
            // 模拟业务场景:满足特定条件时返回202
            if (tagid == "async-process")
            {
                _httpContextAccessor.HttpContext.Response.StatusCode = (int)HttpStatusCode.Accepted;
            }
            return $"Received tagid: {tagid}; readerid: {readerid}; datetime: {datetime}";
        }
    }
}

问题2:SOAP Fault返回自定义HTTP状态码

通过实现CoreWCF的IErrorHandler接口捕获异常,修改HTTP状态码同时保留原SOAP Fault结构,确保客户端兼容。

步骤1:创建自定义ErrorHandler

using CoreWCF;
using CoreWCF.Channels;
using CoreWCF.Description;
using CoreWCF.Dispatcher;
using Microsoft.AspNetCore.Http;
using System.Net;

namespace CoreWcf.Samples.Http
{
    public class CustomErrorHandler : IErrorHandler
    {
        private readonly IHttpContextAccessor _httpContextAccessor;

        public CustomErrorHandler(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        // 指定需要处理的异常类型
        public bool HandleError(Exception error)
        {
            return error is FaultException;
        }

        // 自定义Fault响应并设置HTTP状态码
        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            if (error is FaultException faultException)
            {
                // 根据Fault内容匹配自定义状态码
                if (faultException.Message.Contains("Unknown Username or Incorrect Password"))
                {
                    _httpContextAccessor.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                }
                else if (faultException.Message.Contains("Business Conflict"))
                {
                    _httpContextAccessor.HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict;
                }
                // 保留原SOAP Fault结构,避免客户端解析失败
                fault = Message.CreateMessage(version, faultException.CreateMessageFault(), faultException.Action);
            }
        }
    }

    // 服务行为:将ErrorHandler注册到服务宿主
    public class CustomErrorHandlerBehavior : IServiceBehavior
    {
        private readonly IHttpContextAccessor _httpContextAccessor;

        public CustomErrorHandlerBehavior(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
            {
                channelDispatcher.ErrorHandlers.Add(new CustomErrorHandler(_httpContextAccessor));
                foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
                {
                    endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new CustomErrorHandler(_httpContextAccessor));
                }
            }
        }

        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { }
    }
}

步骤2:在Startup.cs中注册ErrorHandler

修改Startup.cs的Configure方法,将自定义行为添加到服务宿主:

public void Configure(IApplicationBuilder app)
{
    var wsHttpBindingWithCredential = new BasicHttpBinding(CoreWCF.Channels.BasicHttpSecurityMode.TransportWithMessageCredential);
    wsHttpBindingWithCredential.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;

    // 获取IHttpContextAccessor实例
    var httpContextAccessor = app.ApplicationServices.GetRequiredService<IHttpContextAccessor>();

    app.UseServiceModel(builder =>
    {
        builder.AddService<DemoService>(serviceOptions =>
        {
            serviceOptions.BaseAddresses.Add(new Uri($"http://localhost:{Program.HTTP_PORT}/DemoService"));
            serviceOptions.BaseAddresses.Add(new Uri($"https://localhost:{Program.HTTPS_PORT}/DemoService"));
        })
        .AddServiceEndpoint<DemoService, IDemo>(wsHttpBindingWithCredential, "/wsHttpUserPassword", ep => { ep.Name = "AuthenticatedDemoEP"; });

        // 注册自定义ErrorHandler和用户名验证器
        builder.ConfigureServiceHostBase<DemoService>(host =>
        {
            host.Description.Behaviors.Add(new CustomErrorHandlerBehavior(httpContextAccessor));
            CustomUserNamePasswordValidator.AddToHost(host);
        });

        var serviceMetadataBehavior = app.ApplicationServices.GetRequiredService<CoreWCF.Description.ServiceMetadataBehavior>();
        serviceMetadataBehavior.HttpGetEnabled = serviceMetadataBehavior.HttpsGetEnabled = true;
    });
}

步骤3:抛自定义FaultException

在服务方法或验证器中抛出带特定消息的FaultException,即可触发对应状态码:

// 在DemoService中抛业务冲突异常
public string DemoRequest(string tagid, string readerid, string datetime)
{
    if (tagid == "duplicate")
    {
        throw new FaultException("Business Conflict: Tag ID already exists");
    }
    // ...其他逻辑
}

关键说明

  • CoreWCF已移除WebOperationContext,官方推荐通过IHttpContextAccessor操作ASP.NET Core上下文。
  • 修改状态码时需保留SOAP响应的标准结构,确保原有客户端无需修改即可解析。
  • 方案完全兼容遗留业务逻辑,同时符合CoreWCF的托管规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 16:40:41