挂钩到第 3 方 Web 服务 (WCF) 调用

Posted

技术标签:

【中文标题】挂钩到第 3 方 Web 服务 (WCF) 调用【英文标题】:Hooking into 3rd Party Web Service (WCF) calls 【发布时间】:2013-03-03 02:35:13 【问题描述】:

在我的工作场所,我们正在升级我们的考勤设置。目前,我们有员工用来办理入住和退房的实体终端。这些终端通过 Web 服务调用与第 3 方 T&A 系统进行通信。

关于 T&A 网络服务:

托管在 IIS 6 上 通过 HTTP 使用 WCF 进行通信 我们只对其中一种公开的方法感兴趣(我们称之为 Beep()

我需要做什么:

保留原来的 T&A 系统,原封不动 编写一个自定义服务,响应对 Beep() 的调用

因此,基本上,我需要搭载对 Beep() 的所有调用,但我不确定最好的方法是什么。

已经考虑过的:

    编写一个自定义 Web 服务,该服务实现与 T&A 服务完全相同的合同,并将所有终端定向到该自定义服务。我的想法是我可以从我的自定义服务中调用原始 T&A 服务,以及应用所需的任何其他逻辑。 这对我来说似乎太过分了,而且似乎有不必要的风险。我们希望尽可能不修改原始系统。 编写自定义 HTTP 处理程序来拦截对原始 T&A 服务的调用。 我们实际上已经在内部做过类似的事情,但我们的实现采用原始 HttpRequest,提取内容,调用自定义服务,最后基于原始请求创建一个 new HttpRequest以便进行对 Beep() 的原始 Web 服务调用。 我不喜欢这种方法的地方是原始的 HttpRequest 丢失了。是的,创建了第二个据称相同的请求,但我对 HttpRequests 的了解还不够,无法保证这是安全的。

我更喜欢选项 2,但它仍然不完美。理想情况下,我们不需要销毁原始的 HttpRequest。有谁知道这是否可能?

如果没有,任何人都可以提出另一种方法吗?是否可以将 IIS 配置为将请求分叉到两个目标?

谢谢

更新 #1

我找到了解决方案(记录在 here),但我仍然愿意接受其他选择。

更新 #2

我喜欢 Flup 的解决方案(和理由)。他得到了赏金:) 谢谢你!

【问题讨论】:

您尝试做的事情的基础听起来有点像“中间人”,但您不想绕过所有信息,我是对的吗?如果 beep() 被调用,也许你可以注册到响应的东西 那么,当我找到自己的解决方案后,我该如何处理赏金? 也许创建一个答案就足够了,将其标记为答案并将赏金设置为您自己:) 【参考方案1】:

您可以将 Web 服务配置为使用自定义操作调用程序,IOperationInvoker

WCF 一如既往地反序列化原始 HTTP 请求,但它不会在现有 Web 服务类上调用 Beep(),而是调用您的调用程序。调用者执行其特殊操作,然后在原始服务上调用 Beep()

实现IHTTPModule 的优势在于,HTTP 的所有内容仍由原始 Web 服务的配置处理,不变。您可以在更高的抽象级别上进行分支,即在 Web 服务的接口上,在 Beep() 方法处。

在不更改现有服务类的情况下设置自定义操作调用程序的本质(这使得它变得更加困难):

实现自定义IOperationBehavior,在其ApplyDispatchBehavior 方法中在服务的Beep() 方法上设置自定义IOperationInvoker。 实现自定义IEndpointBehavior,在其ApplyDispatchBehavior 方法中设置自定义IOperationBehavior。 将这两个行为与您的IOperationInvoker 一起放在类库中并将其添加到现有服务中 然后将服务配置为使用IEndpointBehavior

有关调用程序位,请参见 When and where to set a custom IOperationInvoker? 和 http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/17/wcf-extensibility-ioperationinvoker.aspx。

请参阅Custom Endpoint Behavior using Standard webHttpEndpoint,了解如何配置自定义端点。

【讨论】:

这听起来很完美!我今天会试一试。只要这不会以某种方式改变 Beep() 的行为(例如,神秘地改变故障内容或吞噬异常),那么我很高兴 :) 我今天晚些时候会回来奖励赏金。 像魅力一样工作。谢谢。【参考方案2】:

听起来您实际上想将您的系统集成到 ESB 模式中。现在,MS 解决 ESB 问题的方法是 Biztalk。在这种情况下,Biztalk 是热核弹头坚果饼干。你不想要 Biztalk。

在此处查看lightweight alternatives的结果

【讨论】:

碰巧我们已经在考虑采用 BizTalk 作为我们的 ESB。如果我们得到它,我会考虑使用它:) 我找到了使用自定义IHttpModule 的合适解决方案,因此我不会接受 ESB 建议。对不起:|【参考方案3】:

我找到了使用自定义IHttpModule 的解决方案。请参阅下面的示例:

using System;
using System.Text;
using System.Web;

namespace ForkHandles

    public class ForkHandler : IHttpModule
    
        public void Init(HttpApplication application)
        
            application.BeginRequest += new EventHandler(application_BeginRequest);
        

        void application_BeginRequest(object sender, EventArgs e)
        
            var request = ((HttpApplication)sender).Request;

            var bytes = new byte[request.InputStream.Length];
            request.InputStream.Read(bytes, 0, bytes.Length);
            request.InputStream.Position = 0;

            var requestContent = Encoding.ASCII.GetString(bytes);

            //  vvv
            // Apply my custom logic here, using the requestContent as input.
            //  ^^^
        

        public void Dispose()
        
        
    

这将允许我检查网络服务请求的内容并做出相应的反应。

我对其他侵入性较小的解决方案持开放态度,因为这需要更改已部署的第 3 方 Web 服务的配置。

【讨论】:

【参考方案4】:

如果您想拦截发送到 T&A WCF 服务的消息,我建议您使用自定义侦听器,该侦听器可以通过在 web.cofig 中进行更改来插入服务调用。

这将是透明的。

请查找 WCF 可扩展性 - 消息检查器。

system.diagnostics>
    <sources>
      <source name="System.ServiceModel.MessageLogging">
        <listeners>          
          <add name="ServiceModelMessageLoggingListener">
            <filter type=""/>
          </add>
        </listeners>
      </source>
    </sources>
</system.diagnostics>

【讨论】:

有趣。与 HttpModule 方法相比,这有什么好处?这是更标准的方法吗? 请在网上搜索文章。 我有。我希望从你的个人经验中学习,但没关系。在与我的同事讨论后,我们认为我们将采用 HttpModule 方法。

以上是关于挂钩到第 3 方 Web 服务 (WCF) 调用的主要内容,如果未能解决你的问题,请参考以下文章

使用 WS 安全性在 WCF .NET 中向 Java Web 服务发送请求

Wcf:可配置的服务调用方式

一步一步搭建客服系统 客户列表 - JS($.ajax)调用WCF 遇到的各种坑

WCF 服务客户端:定制的肥皂信封未在线发送

WCF:Svcutil 生成无效的客户端代理、Apache AXIS Web 服务、重载操作

WCF 服务与 ASP.NET Web Api