【问题标题】:ServiceModel.Discovery.DiscoveryClient(string endpointConfigurationName) throws ArgumentNullExceptionServiceModel.Discovery.DiscoveryClient(string endpointConfigurationName) 抛出 ArgumentNullException
【发布时间】:2013-07-24 14:44:51
【问题描述】:

我有一个小型 WCF 客户端,我正在尝试通过应用程序配置文件配置服务发现 - 但是每当我这样做时:

// Create a new DiscoveryClient instance from the 'DiscoveryEndpoint'
// configuration in App.config
DiscoveryClient discoveryClient = new DiscoveryClient("DiscoveryEndpoint");

我收到了ArgumentNullExceptionValue cannot be null. Parameter name: contractDiscoveryClient构造函数的这个重载没有contract参数,并且在App.config中正确指定了契约(见下文)。

以下是 App.config 的相关部分:

<system.serviceModel>
  <client>
    <endpoint name="DiscoveryEndpoint"
              contract="IExampleContract"
              kind="dynamicEndpoint"
              endpointConfiguration="DynamicEndpointConfiguration"/>
  </client>

  <standardEndpoints>
    <dynamicEndpoint>
      <standardEndpoint name="DynamicEndpointConfiguration">
        <discoveryClientSettings>
          <endpoint kind="udpDiscoveryEndpoint"/>
          <findCriteria duration="00:00:02">
            <types>
              <add name="IExampleContract"/>
            </types>
            <scopes>
              <add scope="urn://wcf.test.com/examples/exampleContract/development"/>
            </scopes>
          </findCriteria>
        </discoveryClientSettings>
      </standardEndpoint>
    </dynamicEndpoint>
  </standardEndpoints>
</system.serviceModel>

这是针对 .NET Framework 4.0,使用 Visual Studio 2010 SP1。

DiscoveryClient(string) 构造函数重载的文档表明,这应该使用 App.config 中标识的配置创建一个新的 DiscoveryClient 实例。

有没有其他人遇到过这种行为,如果有,您是如何解决的?

【问题讨论】:

    标签: c# wcf discovery


    【解决方案1】:

    您在配置文件中定义的“DiscoveryEndpoint”实际上是一个服务客户端端点,而不是 DiscoveryClient 端点。

    以下应该有效:

    var exampleContractChannelFactory = new ChannelFactory<IExampleContract>("DiscoveryEndpoint");
    var exampleContractClient = exampleContractChannelFactory.CreateChannel();
    // You can now invoke methods on the exampleContractClient
    // The actual service endpoint used by the client will be looked up dynamically 
    // by the proxy using the DiscoveryClient class internally.
    

    【讨论】:

      【解决方案2】:

      好的,我在启用了Enable .NET Framework source stepping 选项的调试器中花了很多时间,我发现引发此异常的原因(可能)是实现方式中的错误DiscoveryClient 是从配置文件中实例化的 - 在调用堆栈中有一个调用方式,它将硬编码的 null 值传递给 contract 参数,这是引发异常的地方。

      所以,经过多次头疼和大量搜索,我想出了以下解决方法(嗯,更像是一个总数 HACK:!) - 我在这里发布以帮助其他任何人可能会遇到同样的问题。

      // HACK: The following is a workaround for a bug in .NET Framework 4.0
      //       Discovery should be possible when setup from the App.config with the
      //       following three lines of code:
      //
      //         discoveryClient = new DiscoveryClient("DiscoveryEndpoint");
      //         Collection<EndpointDiscoveryMetadata> serviceCollection = discoveryClient.Find(new FindCriteria(typeof(IExampleContract))).Endpoints;
      //         discoveryClient.Close();
      //
      //       However, a bug in the Discovery Client implementation results in an
      //       ArgumentNullException when running discovery in this way.
      //
      //       The following code overcomes this limitation by manually parsing the
      //       standard WCF configuration sections of App.config, and then configuring
      //       the appropriate FindCriteria for a programmatically configured discovery
      //       cycle.  This code can be replaced by the above three lines when either
      //         1. The bug in .NET Framework 4.0 is resolved (unlikely), or
      //         2. The application is retargeted to .NET Framework 4.5 / 4.5.1
      //
      //       To aid future developers, this HACK will be extensively documented
      
      // Load the App.config file into a ConfigurationManager instance and load the configuration
      Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
      
      // Get the ServiceModel configuration group
      ServiceModelSectionGroup serviceModelGroup = ServiceModelSectionGroup.GetSectionGroup(configuration);
      
      // Get the StandardEndpoints configuration node
      StandardEndpointsSection section = serviceModelGroup.StandardEndpoints;
      
      // Get the DynamicEndpoint configuration node
      Configuration dynamicEndpointConfiguration = section["dynamicEndpoint"].CurrentConfiguration;
      
      // Get the first DynamicEndpoint configuration
      // HACK: This assumes only one DynamicEndpoint configuration exists
      //       No additional configurations will be interpreted.  This should
      //       not pose a problem as typically a client will only access a
      //       single service instance.  This can be extended if necessary
      //       at a later time.
      DynamicEndpointElement element = ((DynamicEndpointElement)serviceModelGroup.StandardEndpoints["dynamicEndpoint"].ConfiguredEndpoints[0]);
      
      // Set the required Contract Type
      // HACK: This is currently hard-coded to prevent the need to specify
      //       an AssemblyQualifiedName in the App.config file.  This will
      //       not typically pose a problem as each client will typically
      //       only open a single service exposing a single, well-known,
      //       Contract Type
      FindCriteria criteria = new FindCriteria(typeof(IExampleContract));
      
      // Add all required Scopes to the FindCriteria instance
      foreach (ScopeElement scopeElement in element.DiscoveryClientSettings.FindCriteria.Scopes)
      {
          criteria.Scopes.Add(scopeElement.Scope);
      }
      
      // Get the Discovery Duration
      criteria.Duration = element.DiscoveryClientSettings.FindCriteria.Duration;
      
      // Create a new Discovery Client instance
      DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
      
      // Retrieve the matching Service Endpoints via Dynamic Search
      Collection<EndpointDiscoveryMetadata> serviceCollection = discoveryClient.Find(criteria).Endpoints;
      
      // Close the Discovery Client
      discoveryClient.Close();
      
      // HACK: END -- Process the results of Discovery
      

      请注意,我假设此问题已在 .NET Framework 4.5 / 4.5.1 中解决 - 可能没有,但我目前无法测试。

      如果其他人有比这更优雅或更高效的替代解决方案,请将其发布以帮助其他人。

      【讨论】:

        猜你喜欢
        • 2023-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-07
        • 1970-01-01
        相关资源
        最近更新 更多