在现有 WCF SOAP 服务中添加 Http 标头不起作用

Posted

技术标签:

【中文标题】在现有 WCF SOAP 服务中添加 Http 标头不起作用【英文标题】:Adding Http Header in an existing WCF SOAP Service is not working 【发布时间】:2018-07-08 19:28:42 【问题描述】:

我想为我的 WCF SOAP 服务添加一个 HTTP 标头。我的最终目标是通过这个 HTTP 标头发送 API 密钥。

下面是我的代码:

[ServiceBehavior(Namespace = "http://****.com/**/1.1")]
public class MyWcfSvc : IMyVerify

    const int MaxResponseSize = 0xffff; // 64K max size - Normally it will be MUCH smaller than this

    private static readonly NLogLogger Logger;

    static MyWcfSvc()
    
        Logger = new NLogLogger();
        // Add an HTTP Header to an outgoing request 
        HttpRequestMessageProperty requestMessage = new HttpRequestMessageProperty();
        requestMessage.Headers["User-Auth"] = "MyHttpHeaderValue";
        OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestMessage;
    

我在 HTTP 请求标头下看不到 User-Auth 标头。

我也尝试了另一种方法。

public AnalyzeResponse Analyze(AnalyzeRequest analyzeRequest)
    
        HttpRequestMessageProperty requestMessage = new HttpRequestMessageProperty();
        requestMessage.Headers["User-Auth"] = "MyHttpHeaderValue";
        OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestMessage;
.
.
. Rest of the service implementation
.
.
.

但是,我仍然没有在请求消息中看到任何 HTTP 标头信息。我正在使用 SOAP UI 发送请求并查看响应。

我应该怎么做?我是否应该对与课程相关的服务进行更改?或者我需要对web.config 文件进行一些更改?

【问题讨论】:

How to add a custom HTTP header to every WCF call? 我跟着那个,但它不起作用,这就是我问这个问题的原因。 不确定你想要完成什么......当你的服务发送它时在响应中输出一个HTTP头,或者当有人调用服务时,你想要传递和HTTP头,或者什么还有吗? 我建议您包括:服务器代码、客户端/消费代码、预期结果和实际结果(可能使用日志)...您的问题目前令人困惑。 【参考方案1】:

SOAP 标头

要添加 SOAP 标头,请使用以下代码客户端

using (OperationContextScope scope = new OperationContextScope((IContextChannel)channel))

    MessageHeader<string> header = new MessageHeader<string>("MyHttpHeaderValue");
    var untyped = header.GetUntypedHeader("User-Auth", ns);
    OperationContext.Current.OutgoingMessageHeaders.Add(untyped);

    // now make the WCF call within this using block

然后,服务器端,使用:

MessageHeaders headers = OperationContext.Current.IncomingMessageHeaders;
string identity = headers.GetHeader<string>("User-Auth", ns);

注意。 ns标头 XML 元素的命名空间 URI。

HTTP 标头

添加 Http 标头:

// Add a HTTP Header to an outgoing request 
HttpRequestMessageProperty requestMessage = new HttpRequestMessageProperty();
requestMessage.Headers["MyHttpHeader"] = "MyHttpHeaderValue";
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestMessage;

并抓住它服务器端

IncomingWebRequestContext request = WebOperationContext.Current.IncomingRequest; 
WebHeaderCollection headers = request.Headers; 
Console.WriteLine(request.Method + " " + request.UriTemplateMatch.RequestUri.AbsolutePath); 

foreach (string headerName in headers.AllKeys)
 
    Console.WriteLine(headerName + ": " + headers[headerName]); 

【讨论】:

这是 SOAPHeader,不是 HttpHeader。 为答案竖起大拇指。我使用第二种方法使用 .Net 核心 API 将标头添加到 WCF 方法。谢谢。【参考方案2】:

如果您尝试将 HTTP 请求标头添加到客户端请求,您可以按照以下步骤操作。

创建一个客户端消息检查器。例如:

public class CustomInspector : IClientMessageInspector

    public void AfterReceiveReply(ref Message reply, object correlationState)
    
    

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    
        HttpRequestMessageProperty reqProps = request.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
        if(reqProps == null)
        
            reqProps = new HttpRequestMessageProperty();
        

        reqProps.Headers.Add("Custom-Header", "abcd");
        request.Properties[HttpRequestMessageProperty.Name] = reqProps;

        return null;
    

创建一个端点行为来加载这个检查器:

public class CustomBehavior : IEndpointBehavior

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    
    

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    
        clientRuntime.ClientMessageInspectors.Add(new CustomInspector());
    

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    
    

    public void Validate(ServiceEndpoint endpoint)
    
    

最后将此行为添加到端点。

class Program

    static void Main(string[] args)
    
        ChannelFactory<ICalculator> factory = new ChannelFactory<ICalculator>("BasicHttpsBinding_ICalculator");
        factory.Endpoint.EndpointBehaviors.Add(new CustomBehavior());
        var client = factory.CreateChannel();

        var number = client.Add(1, 2);

        Console.WriteLine(number.ToString());
    

上面的例子对我有用。我可以看到 Fiddler 的请求标头。

【讨论】:

【参考方案3】:

在客户端有比 Leonardo 更好的解决方案。他的解决方案需要手动修改每个请求。 Here 是 ClientMessageInspector 的解决方案,它会自动为每个传出请求添加标头。

1:使用覆盖定义 MessageInspector: Bellow 是唯一一种覆盖方法,其余为空。

public class ClientMessageInspector : IClientMessageInspector

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    
        HttpRequestMessageProperty property = new HttpRequestMessageProperty();
        property.Headers["User-Agent"] = "value";
        request.Properties.Add(HttpRequestMessageProperty.Name, property);
        return null;
    
...

    将此消息检查器绑定到 EndPointBehavior。 Bellow 是唯一一种覆盖方法,其余为空。

    public class CustomEndpointBehavior : IEndpointBehavior
    
       public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
       
          clientRuntime.ClientMessageInspectors.Add(new ClientMessageInspector());
       
       ...
    
    最后一步是将新行为添加到 WCF 端点:
Endpoint.EndpointBehaviors.Add(new CustomEndpointBehavior());

【讨论】:

以上是关于在现有 WCF SOAP 服务中添加 Http 标头不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何将自定义 WCF 协议通道添加到现有绑定

WCF SOAP 服务忽略内容类型字符集

使用soap 1.2的WCF服务

将 HTTPS 绑定添加到 IIS 后,具有 Windows 身份验证的 WCF SOAP Web 服务停止工作

HTTP 标头或 SOAP 标头中的 WCF 肥皂操作?

将授权标头添加到 WCF 基架 SOAP Web 服务