WCF常用参数ClientMessageInspector、DispatchMessageInspector或者替代方案?

8
我正在使用WCF仅用于数据服务(即仅内部应用程序,非常简洁,没有会话状态等),以保持我们的Web应用程序可扩展性。我们需要为每个服务调用提供一些常规属性,目前我们一直在传递它们。对于每个调用都有一个单独的请求对象并不理想,因为除了这些公共属性之外,其余内容都非常不同,并且在开发过程中经常更改。
目前我正在考虑使用自定义标头和clientmessageinspector来设置值。对于这种情况,这是否是最简单的推荐方法,还是有更好的方法?
更多细节...
下面的红点是我不确定正确方法(或如何去做)的地方。
发送的内容
发送的数据是一组简单的ID(3个或4个,用于用户ID、客户端ID等)-所有这些ID都会影响安全性和性能(在某些情况下,它确定要连接的数据库)。我们还将扩展此功能以包含更复杂的权限-对于Windows工作程序不需要。
调用者将是Web应用程序,在其中这些对象从会话对象中获取,或者是Windows服务工作者,在其中这些对象是手动填充的。
现在的想法
理想情况下,调用者的工作流上的getinstance将自动用会话对象或使用Windows服务调用手动填充这些属性(不同的构造函数?)。然后,我们将确保这些参数始终可用,无需在每个调用它的功能上经常引用构建合同。由于应用程序的规模/复杂性而导致我们目前有很多服务调用(而不是由于错误工程学:)),因此随着权限的扩展变得越来越复杂,以自我说明的方式强制执行规则变得有些困难。
从概念上讲,会话是您在应用程序中处理此操作的地方,但服务实际上只是一个数据访问层(具有视图映射、页面化和最后一次从存储库调用的安全性),因此我们不需要那种重复或复杂性,只需要包括查询中的关键身份和权限字段。
问题
这感觉非常像我们应该在调用时使用标头进行的事情,因为我们总是需要这些字段,但我对设置和获取应位于端点和客户端接口的生命周期中的位置感到有些不确定。我也很高兴被证明是错的。

1
你似乎在考虑的是被称为规范模型消息方案,它是一种强大的方法。该方案详情请参考网站:http://soapatterns.org/patterns/canonical_schema。 - Martin Spamer
嗨,马丁,这是@Slugster建议的模式,但我们真的不想在每次调用时都使用合同所带来的抽象层。大多数请求只需要简单的参数,因为我们的服务是内部的,我们不需要版本控制等。参数更具自我说明性,除非进行复杂的搜索操作,在这种情况下,我们使用合同。 - Gats
3个回答

3
在我的经验中,使用消息检查器进行初始设置和配置可能会非常棘手,在我的研究中也没有一个网站涵盖了所有内容,我不得不从几个不同的地方挑选代码片段并将它们拼凑在一起。
你需要质疑你放在头部的信息。这是需要对被调用的方法可用的信息吗?如果是,则将其放在头部是错误的选择,因为每个方法都需要解析信息。
适合这种情况的信息类型是自定义身份验证和/或与WCF调用相关的用户特定元数据。在我的情况下,我有一个由自动服务发起的WCF调用,该调用被转发到进一步的WCF终点,这是使用消息检查器的理想场景,因为我能够在中继点添加元数据到头部,以供后续终点消费。
如果你只是想打包一些对于每个调用都是共同的数据,那么我会创建一个具有适当属性的基础数据对象,然后仅为更专业的调用扩展它(终点可以确保共同数据存在,或者假设如果它不存在则使用某些默认值)。对于每个终点所需的共同数据,使用消息检查器是过度设计且可能不可行的。

那么每次调用都需要解析数据,这有点笨重,对吧?我对通用数据契约的问题在于我们有数百个调用,我不想有数百个消息契约或带有冗余字段的契约。我们的WCF层实际上是一种数据访问形式,因此精简和易读至关重要。我希望属性“就在那里”,服务调用与“额外”属性保持精简。 - Gats
2
@Gats 用户特定数据在数据库中可以静态存储多少(因此不需要在每次调用时传递 - 您只需传递一个标识符)? 简而言之,如果端点将处理信息,则可以将其放入标题中。 如果所调用的方法将处理它,则它属于合同数据对象(因此我建议将它们放在所有其他数据对象派生自的基础对象中)。 - slugster
再次感谢@slugster。我会在问题中澄清一些推理。 - Gats
我反对让其他对象从基本合同派生的原因是服务所需内容缺乏透明度。除了核心参数外,我们每次调用都需要不同的参数,因此在内部场景中这将变得非常丑陋且过于繁琐(对于外部服务调用来说完全合理)。目前代码精简,易于操作且非常自我记录,因此仅针对核心属性的合同并不是不可能的,但我希望避免每次调用时都要填写它。 - Gats
1
你是否考虑过使用OperationContext.IncomingMessageProperties?你可以定义自己的消息属性,并将其绑定到服务模型层中的特定请求。这些比标头更快,不会影响线路格式,并且在MessageInspector和管道中的其他层中也可用。 - Sajay
显示剩余2条评论

1

这可能是一种比较老的方法,但你可以轻松地从 System.Runtime.Remoting.Messaging 中利用 CallContext。客户端可以使用 IClientMessageInspector 的实现在操作调用时设置调用上下文,并且服务器上可以使用 IMessageInspector 的实现从 CallContext 中检索共享数据。


1
我已经应用了类似的架构; 基本上,每个客户端调用需要携带一些信息,如选择哪个DB、标识符等。在服务器端,这些参数将自动处理并存储在字典中。
我创建了一个通用代理类来包装客户端代理,以便为每个服务调用添加相关的标头。每个需要调用服务的开发人员都使用此通用代理类进行调用。
在服务端,我实现了一个DispatchMessageInspector作为终结点行为,其中从请求标头中提取数据并存储在字典中。该字典在OperationContext的扩展(IExtension<OperationContext>)中初始化,并在请求处理期间可用。
注意,服务的实例上下文模式为PerCall。

嗨Daryal,你有这方面的例子吗? - Gats
虽然我想要更具体的例子,但我将这个标记为答案。 - Gats
1
@Gats 我无法直接分享代码,因为受到公司限制,但以下链接可能有所帮助:http://www.codeproject.com/Articles/73506/Summarizing-Client-Side-Asynchronous-Invocations-i、http://blogs.msdn.com/b/zelmalki/archive/2008/12/29/creating-a-wcf-idispatchmessageinspector.aspx、http://www.codeproject.com/Articles/352678/Add-Custom-Message-Header-in-WCF-4-Calls - daryal

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