代码之家  ›  专栏  ›  技术社区  ›  Roman Pokrovskij Archil Labadze

如何将WCF客户端配置为与托管在回复中不返回内容类型的服务器上的第三方WS-service一起工作?

  •  1
  • Roman Pokrovskij Archil Labadze  · 技术社区  · 15 年前

    如何将WCF客户端配置为与托管在回复中不返回内容类型的服务器上的第三方WS-service一起工作?

    问题是,这种配置为使用basicHttpBinding的WCF客户端会引发异常:“需要内容类型”。。。

    我应该使用自定义绑定还是拒绝WCF?

    P、 S。净额3.5

    P、 P.S 消息:SOAP消息传递需要HTTP内容类型标头,但未找到任何标头 服务器堆栈跟踪: at系统。服务模型。频道。HttpChannelUtilities。ValidateRequestReplyResponse(HttpWebRequest请求、HttpWebResponse响应、HttpChannelFactory工厂、WebException响应异常)

    at系统。服务模型。频道。HttpChannelFactory。HttpRequestChannel。HttpChannelRequest。WaitForReply(TimeSpan超时) at系统。服务模型。频道。请求通道。请求(消息消息、TimeSpan超时) at系统。服务模型。调度员。RequestChannelBinder。请求(消息消息、TimeSpan超时) at系统。服务模型。频道。服务频道。调用(字符串操作、布尔单向、ProxyOperationRuntime操作、对象[]In、对象[]outs、TimeSpan超时) at系统。服务模型。频道。服务频道。调用(字符串操作、布尔单向、ProxyOperationRuntime操作、对象[]In、对象[]Out) at系统。服务模型。频道。ServiceChannelProxy。InvokeService(IMethodCallMessage methodCall,ProxyOperationRuntime操作) at系统。服务模型。频道。ServiceChannelProxy。调用(IMessage消息)

    在[0]处重试异常: at系统。运行时。远程处理。代理。RealProxy。HandlerReturnMessage(IMessage reqMsg,IMessage retMsg) at系统。运行时。远程处理。代理。RealProxy。PrivateInvoke(MessageData和msgData,Int32类型) 在blablabla(自定义代码)

    2 回复  |  直到 15 年前
        1
  •  0
  •   Roman Pokrovskij Archil Labadze    15 年前

    我可以说这是不可能的。我想说明原因:

    非常深层的内部代码(System.ServiceModel.Channels.HttpChannelFactory+HttpRequestChannel+HttpChannelRequest类,WaitForReply方法)-您永远不想进行继承,而Reflection将重点放在这些内部类上-包含两行

    var响应=(HttpWebResponse)此。webRequest。GetResponse();//webRequest是HttpWebRequest的类型 HttpInput输入=HttpChannelUtilities。ValidateRequestReplyResponse(this.webRequest,response,this.factory,responseException);

    由于HttpWebRequest是公共的,而GetResponse是虚拟的,所以似乎可以通过这种方式覆盖它

    public class FakedHttpWebRequest: HttpWebRequest
    {
    
            protected FakedHttpWebRequest(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext)
            {
            }
    
            public override WebResponse GetResponse()
            {
                WebResponse wr = base.GetResponse();
                wr.ContentType = "text/xml";
                return wr;
            }
    }
    

    然后我们需要在某处使用反射来创建FakedHttpWebRequest,而不是HttpWebRequest。。。

    不幸的是,这次“某处”似乎是静态的(!)方法(WebRequest.Create),所以没有机会停留在“小黑客”范围内。

        2
  •  0
  •   Roman Pokrovskij Archil Labadze    15 年前

    我觉得我发现了这个计划是如何被破解的。

    从继承新类 系统服务模型。频道。HttpChannelFactory+HttpRequestChannel+HttpChannelRequest 并重写WaitForReply虚拟方法

    从继承新类 系统服务模型。频道。HttpChannelFactory+HttpRequestChannel 并重写CreateRequest(Message)接口方法

    继承新的班级形式 系统服务模型。频道。HttpChannelFactory 并重写OnCreateChannel(EndpointAddressRemoteAddress,Uri via)方法

    问题:所有这些类都是私有的和内部的(!)。解决方案是,使用反射/发射/类型生成器/codedom在运行时创建它们。所有提到的方法都很短(只有WaitForReply是详细的),所有方法都是虚拟的——在这里我们真的很幸运。

    然后从Http(s)TransportBindingElement继承 并重写BuildChannelFactory(BindingContext上下文);

    然后创建自定义绑定

    :)

    P、 我不确定是否可以从内部受保护的类或其他程序集继承它来创建新类型,但我猜这是可能的。

    推荐文章