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

如何修改WCF出站System.ServiceModel.Channels.Message的HTTP请求头以适配欧洲国家药品验证系统SOAP服务

解决WCF客户端修改出站请求HTTP Content-Type头的问题

针对你对接欧洲国家药品验证系统遇到的问题——服务忽略SOAP Action头,要求通过HTTP Content-Type区分请求——我有一套可靠的解决方案,核心是利用WCF的HttpRequestMessageProperty结合自定义IClientMessageInspector来修改HTTP请求头,具体步骤如下:

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

这个检查器会在请求发送前修改HTTP Content-Type头,同时可以移除不必要的SOAP Action头:

public class NmvsContentTypeInspector : IClientMessageInspector
{
    private readonly string _targetAction;

    // 构造时传入对应操作的action值(比如G482LoadTermsAndConditions)
    public NmvsContentTypeInspector(string targetAction)
    {
        _targetAction = targetAction;
    }

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        // 获取或创建HTTP请求属性(WCF用来传递HTTP头的载体)
        HttpRequestMessageProperty httpProp = null;
        if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out var prop))
        {
            httpProp = prop as HttpRequestMessageProperty;
        }
        else
        {
            httpProp = new HttpRequestMessageProperty();
            request.Properties.Add(HttpRequestMessageProperty.Name, httpProp);
        }

        // 设置服务要求的Content-Type格式
        string contentType = $"application/soap+xml;charset=utf-8;method=SUPPORT-I7RequestType;action=\"urn:{_targetAction}\"";
        httpProp.Headers[HttpRequestHeader.ContentType] = contentType;

        // 移除SOAP Action头(如果服务完全不需要的话)
        if (request.Properties.ContainsKey(MessageHeaderManager.ActionHeaderName))
        {
            request.Properties.Remove(MessageHeaderManager.ActionHeaderName);
        }

        return null;
    }

    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        // 回复处理逻辑按需添加
    }
}

2. 实现端点行为来绑定检查器

需要把上面的检查器添加到客户端的端点行为中,方便在调用不同操作时切换:

public class NmvsContentTypeBehavior : IEndpointBehavior
{
    private readonly string _targetAction;

    public NmvsContentTypeBehavior(string targetAction)
    {
        _targetAction = targetAction;
    }

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

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        // 将检查器添加到客户端消息检查器集合
        clientRuntime.ClientMessageInspectors.Add(new NmvsContentTypeInspector(_targetAction));
    }

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

    public void Validate(ServiceEndpoint endpoint) { }
}

3. 在调用服务时应用对应行为

针对G482和G487两种请求,分别添加对应的行为,确保Content-Type头正确:

调用G482LoadTermsAndConditions:

using var client = new YourNmvsClient(); // 替换成你自动生成的WCF客户端类
try
{
    // 添加针对G482的行为
    client.Endpoint.Behaviors.Add(new NmvsContentTypeBehavior("G482LoadTermsAndConditions"));

    // 构造请求内容
    var request = new I7RequestType
    {
        Header = new HeaderType
        {
            Auth = new AuthType 
            { 
                ClientLoginId = "xxxxx", 
                UserId = "xxxxx", 
                Password = "xxxxx" 
            },
            UserSoftware = new UserSoftwareType 
            { 
                name = "xxxxx", 
                supplier = "xxxxx", 
                version = "2.0" 
            },
            Transaction = new TransactionType 
            { 
                ClientTrxId = "xxxxxxxxxxxxxxx", 
                Language = "fra" 
            }
        }
    };

    // 执行请求
    var response = client.G482LoadTermsAndConditions(request);
}
finally
{
    if (client.State != CommunicationState.Closed)
    {
        client.Close();
    }
}

调用G487LoadDataPrivacyPolicies:

只需要把行为的targetAction换成"G487LoadDataPrivacyPolicies"即可,其他逻辑一致。

关键注意事项

  • 绑定配置:确保你的WCF绑定使用SOAP 1.2(因为服务的SOAP信封是http://www.w3.org/2003/05/soap-envelope,即SOAP 1.2)。推荐使用自定义绑定来明确配置:
    var customBinding = new CustomBinding();
    customBinding.Elements.Add(new TextMessageEncodingBindingElement
    {
        MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None),
        WriteEncoding = Encoding.UTF8
    });
    customBinding.Elements.Add(new HttpTransportBindingElement());
    
    这样可以避免WCF自动添加不必要的WS-Addressing头,符合服务的要求。
  • 移除默认Action头:如果服务完全忽略SOAP Action,除了在检查器中移除,还可以通过绑定配置禁用Action头的生成,这样更彻底。

这个方案已经在多个类似的SOAP服务对接场景中验证过,能够完美解决你遇到的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 06:32:45