WCF服务调用在每次调用中包含相同的信息

时间:2011-10-03 12:13:00

标签: wcf web-services dry

我有一个将由某个应用程序(当前网站)使用的Web服务。

这些电话几乎都是特定于某个客户的电话,但仍然是相同的。所以一个调用可能是getAllFoo(),但我需要一些参数来说明Foo来自哪个客户端。

如果我只是为所有调用添加一个标准参数,那么很快就会变得麻烦,所以我希望这样做有点DRY和自动。所有服务电话都会包含的内容。

IDispatchMessageInspector对我来说是正确的吗?可以包含哪些信息,我可以在方法中访问该信息吗?

我是否应该为调用创建某种属性?

如果有人能指出我的解决办法,那就太棒了。

修改

我正在考虑的另一个解决方案。

如果对特定客户端的服务调用发生在消费者端,则会在instanceCreation中知道,因此我可以使用已知客户端实例化ServiceClient。

我可以以某种方式将此解决方案用于ClientBase<>扩展程序。

假设我正在为Domain1服务(让我们调用客户端域不要将它与服务客户端/消费者混淆)我创建了一个InformationProvider消费者端,其中包含ClientBase<IInformationService>字段。我确保在构造时设置了DomainName(domain1),因此在实例化ClientBase<IInformationService>时我可以做同样的事情所以它以某种方式让服务知道我要求的域名。

我还在学习WCF,所以我不确定如何做到这一点。

2 个答案:

答案 0 :(得分:1)

我可以理解你想让你的解决方案变得简单而整洁,但最终 - 就像你自己说的那样 -

  

...我需要一些参数来说明哪个客户......

显而易见且最简单的解决方案是在需要的所有服务调用中包含client参数。肯定会有不需要客户端参数的服务调用,在这种情况下,您不需要包含参数。

如果客户标识符被隐蔽地传递给客户标识符,您可以做一些聪明的事情,但要注意做一些不必要的聪明事情。我会将客户端作为一个简单的参数传递,因为它被用作参数。我想到了两个原因:

  1. 如果有人维护您的代码,他们会很快了解正在发生的事情。
  2. 如果有人需要使用该服务,很明显该如何使用它。

答案 1 :(得分:1)

可能的模式:

  • 确保您为每个会话提供服务实例化。这意味着您必须使用wsHttpBinding,netTcpBinding或自定义绑定,因为http不支持会话。
  • 在实例化每个会话时,始终调用初始化操作,以设置该服务的客户端ID。
  • 将此初始化操作放在代理的构造函数中。

所涉及的步骤将是这样的:

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class MyService : IMyService
{
    private int clientId;

    public void StartUp(int clientId)
    {
        this.clientId = clientId;

然后是客户端,假设您使用生成的代理,将客户端包装在另一个代理中。

public class ExtendedClient : MyServiceClient
{
    public ExtendedClient(int clientid) : base()
    {
        this.StartUp(clientid);
    }

现在您应该实例化ExtendedClient,它将通过提供客户端ID来创建频道并启动服务。

我个人更喜欢简单地为每个服务调用发送客户端ID,但是如果你能够使用会话能力绑定,那么这应该可行。


关于WCF的一些信息。如果您有无状态服务,那么您需要将客户端作为参数包含在每个服务调用中。这意味着您需要在整个代码中包含客户端 - 例如,您可以在ClientBase构造函数中检索它。但是您需要将它添加到每个OperationContract和所有服务实现中。

另一种方法是拥有有状态服务 - 您首次使用的实例将保留供您重用(超时/例外除外)。在这种情况下,您可以只发送一次客户端,然后服务将了解客户端以进行后续调用。这是上述模式。这意味着您无法使用http绑定。我相信通过这样做,你只会增加应用程序中出现问题的可能性(有状态服务,必须确保初始化操作完成,进行更多服务调用)。