使用WCF实现不需要操作标头的SOAP服务器

4
我正在尝试使用WCF实现接受SOAP 1.2 over HTTP的Web服务。不幸的是,我必须与不发送HTTP头部的“action”参数的旧客户端一起工作。这似乎导致了WCF的问题,因为(至少默认情况下)它似乎无法在没有“action”的情况下将请求路由到适当的位置。
我创建了一个基于“BasicHttpBinding”的绑定,但将“MessageVersion”设置为“MessageVersion.Soap12”,我认为这将消除使用WS-Addressing的要求。
然后,我在“IContractBehavior”中重载了“ApplyDispatchBehaviour”,将“DispatchRuntime.OperationSelector”设置为“IDispatchOperationSelector”的自定义实现,该实现根据SOAP主体的内容选择正确的操作(基本上是此MSDN文章中使用的方法)。
默认情况下,这似乎不起作用,并且在进行请求时未调用“SelectOperation”函数。
但是,如果我向我的合同添加具有空操作的虚拟操作,如下所示:
[OperationContract( Action = "" )]
void DoNothing();

突然间,SelectOperation开始被调用,我的代码按预期工作了。看起来我没有成功地使WCF不再需要操作头 - 我只是停止了操作头直接映射到操作。但是,由于契约是从.wsdl文件生成的,因此似乎很难通过编辑它来使事情正常运转。

所以我的问题是:如何在不使用操作头的情况下使用WCF接受SOAP 1.2请求?除非我弄错了,SOAP 1.2规范并不要求操作头,因此肯定有一些方法可以在WCF中实现这一点,而不必诉诸于修改契约的hack手段。


你可以使用Action="*",然后单个操作将捕获所有请求 - 不过我认为这不是理想的解决方案? - Chris
很抱歉,@Chris。我不想去修改生成的文件,因为那样做会被视为黑客行为。除非在从wsdl文件生成接口时有一些选项可以传递给svcutil.exe来实现这一点? - obmarg
1个回答

2
我今天刚刚成功解决了这个问题的答案。原来使用的EndpointDispatcher具有一个ActionMessageFilter作为其ContractFilter,并且基于操作过滤掉了一些消息。

在我将ContractFilter更新为MatchAllMessageFilter之后,所有的消息都被传递到我的IDispatchOperationSelector中,可以根据SOAP正文内容进行选择。

我用于执行此操作的代码位于IContractBehavior.ApplyDispatchBehaviour中:

foreach(
    var endpointDispatcher in
    dispatchRuntime.ChannelDispatcher.Endpoints
    )
{
    endpointDispatcher.ContractFilter = new MatchAllMessageFilter();
}

我可能会在未来更新,使用比MatchAllMessageFilter更适合的过滤器,但目前它能够胜任工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接