从 WSDL 更改生成的服务引用调用的 HTTP 主机头

Posted

技术标签:

【中文标题】从 WSDL 更改生成的服务引用调用的 HTTP 主机头【英文标题】:Change HTTP Host-Header of a generated Service Reference call from WSDL 【发布时间】:2020-10-14 12:53:46 【问题描述】:

我的计算机中有一个指向本地端点的 WSDL 链接。我已经生成了服务参考,并且当我在本地执行时可以访问一切正常,即 http://localhost/ApplicationHost/EndPoint

如果我使用另一台计算机(在网络中),请求是通过 IP 完成的,即 Http://15.5.20.10/ApplicationHost/EndPoint 但这会响应 400 Bad request。

将请求的主机更改为“localhost”(在 firefox 和 android 上测试过)可以正常工作。

图像具有完美的功能外壳。地址有 IP,主机是“localhost”,但我无法在 c# 中复制它。

如何使用 C# 和服务参考做同样的事情?到目前为止,我已经尝试了很多添加 http 标头的解决方案,但它们都不会真正更改现有的:即 Adding http headers to a Service Reference service method 或 How to add a custom HTTP header to every WCF call? 或 how to modify http header of request; web reference in C#

【问题讨论】:

【参考方案1】:

在客户端,我们可以通过IClientMessageInspector修改header,这里有一个demo:

   public class ClientMessageLogger : IClientMessageInspector
    
        public void AfterReceiveReply(ref Message reply, object correlationState)
         
        

        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        
            HttpRequestMessageProperty header;
            if (request.Properties.ContainsKey(HttpRequestMessageProperty.Name))
            
                header = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
            
            else
            
                header = new HttpRequestMessageProperty();
                request.Properties.Add(HttpRequestMessageProperty.Name, header);
            

            header.Headers["Host"] = "localhost";
            return null;
        
    

ClientMessageLogger 实现了 IClientMessageInspector 接口,我在客户端发出请求之前修改了它的请求头。

 [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class, AllowMultiple = false)]
    public class CustContractBehaviorAttribute : Attribute, IContractBehavior, IContractBehaviorAttribute, IOperationBehavior
    
        public Type TargetContract => throw new NotImplementedException();

        public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        
            return;
        

        public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
        
            throw new NotImplementedException();
        

        public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        
            clientRuntime.ClientMessageInspectors.Add(new ClientMessageLogger());
        

        public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
        
            throw new NotImplementedException();
        

        public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
        
        

        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
        

        

        public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
        
            return;
        

        public void Validate(OperationDescription operationDescription)
        
            throw new NotImplementedException();
        
    

我们将 ClientMessageLogger 添加到客户端的行为中。

    [CustContractBehavior]
    public interface IService
    ...

最后,我们将此行为添加到服务的接口中。

【讨论】:

这对我不起作用,实际发送请求时主机头仍然相同。

以上是关于从 WSDL 更改生成的服务引用调用的 HTTP 主机头的主要内容,如果未能解决你的问题,请参考以下文章

VS2010 根据WSDL文件(java Web Service)生成.cs文件

如何仅针对某些端点从 WSDL 生成 WCF 客户端?

Webservice客户端动态调用服务端功能方法

wsdl的web服务怎么调用

从 wsdl 生成 html 表单

C# 利用VS自带的WSDL工具生成WebService服务类