Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
WCF服务调用在每个调用中包含相同的信息_Wcf_Web Services_Dry - Fatal编程技术网

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

WCF服务调用在每个调用中包含相同的信息,wcf,web-services,dry,Wcf,Web Services,Dry,我有一个web服务,它将被某些应用程序(当前的web站点)使用 这些调用几乎都是特定于某个客户机的,但仍然是相同的。因此,一个调用可能是getAllFoo(),但我需要一些参数来说明Foo来自哪个客户机 如果我只是在所有调用中添加一个标准参数,它会很快变得麻烦,所以我希望这样做有点枯燥和自动化。将包含在所有服务调用中的内容 IDispatchMessageInspector适合我吗?哪些类型的信息可以包含,我可以在方法中访问这些信息吗 我是否应该为调用创建某种属性 如果有人能为我指出解决这个问题

我有一个web服务,它将被某些应用程序(当前的web站点)使用

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

如果我只是在所有调用中添加一个标准参数,它会很快变得麻烦,所以我希望这样做有点枯燥和自动化。将包含在所有服务调用中的内容

IDispatchMessageInspector适合我吗?哪些类型的信息可以包含,我可以在方法中访问这些信息吗

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

如果有人能为我指出解决这个问题的办法,那就太好了

编辑

我正在考虑另一个解决办法

当对特定客户机的服务调用发生在消费者端时,它将在instanceCreation中被知道,因此我可以用一个已知的客户机来实例ServiceClient

我是否可以将此解决方案用于
ClientBase
扩展器

假设我在服务域1(我们调用客户端域以避免将其与服务客户端/消费者混淆),我创建了一个
InformationProvider
消费者端,它有一个
ClientBase
字段。我确保域名(domain1)设置为construction,这样我可以在实例化
ClientBase
时执行相同的操作,这样它就可以让服务知道我在调用哪个域


我仍在学习
WCF
,因此我不确定如何做到这一点。

我可以理解,您希望保持解决方案简单整洁,但最终-正如您自己所说-

。。。我需要一些参数来说明从哪个客户端

最明显、最简单的解决方案是在所有需要的服务调用中包含
client
参数。当然会有不需要客户机参数的服务调用,在这些情况下,您不需要包含参数

在客户机标识符被秘密传递的情况下,您可能可以做一些聪明的事情,但要注意不要做不必要的聪明事情。我会将客户机作为一个简单的参数传递,因为它正被用作一个参数。我想到两个原因:

  • 如果有人维护您的代码,他们会很快理解发生了什么
  • 如果有人需要使用这项服务,很明显如何使用它
  • 一种可能的模式:

    • 确保每个会话都有服务实例化。这意味着您必须使用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构造函数中检索它。但您需要将其添加到每个
    操作契约和所有服务实现中


    另一种选择是拥有一个有状态服务——您第一次使用的实例将保留供您重用(超时/异常除外)。在这种情况下,您可以只发送一次客户机,然后服务将在后续调用中了解客户机。这就是上面描述的模式。这意味着您不能使用http绑定。我相信这样做只会增加应用程序中出现问题的可能性(有状态服务、必须确保初始化操作完成、进行更多服务调用).

    我以前在不干燥的情况下遇到过问题,我真的不想在每次操作合同和每次呼叫中都添加此额外参数。我将主要自己维护这段代码,并创建使用它的客户机。谢谢你的意见。我认为这是正确的方法,但我会给你另一个答案。我会试试这个,看起来不错。我会叫另一个计划B:)我正在考虑你在编辑中说的话。我可以将其设置为一个参数,因为一旦我设置了其他消费者,它会更容易。我在想一个办法来解决这个问题。我想可以将其设置为字段并将其添加到Channel.Method(clientId,otherParams)中。有没有什么方法可以让Genralize方法在这里有所帮助?@IngóVals因为ClientBase都是生成的代码,所以不容易更改。它是作为分部类生成的,因此您可以对其进行扩展,并定义一个替代构造函数,该构造函数将为您设置客户机参数。或者您可以像我上面所做的那样从ClientBase类扩展到您自己的版本。问题是,因为生成的代码是调用
    Channel.Method(clientId,otherParams)
    的地方,您如何更改它来封装clientId?您需要编写另一组没有client id参数的服务操作,然后从某处检索它并调用底层操作。我尽可能避免自动生成的代码,因此我编写了自己的客户端实现ClientBase的代码。但我现在明白你的意思了。