Расширение поведения службы WCF, вызывающее исключение нулевой ссылки

#wcf #routing #wcf-routing #wcf-behaviour #wcf-extensions

#wcf #маршруты #wcf-маршрутизация #wcf-поведение #wcf-расширения

Вопрос:

Итак, я пытаюсь написать службу маршрутизации. Идея заключается в том, что каждый раз, когда кто-то вызывает службу маршрутизации, конечная точка выбирается случайным образом расширением поведения WCF. Для достижения этого я использовал слегка измененный пример из MSDN под названием DynamicReconfiguration. Часть моего web.config выглядит следующим образом

 <behaviors>
  <serviceBehaviors>
    <behavior>
     <behavior name="behaviorWithUpdate">
       <updateBehavior />
    </behavior>
  </serviceBehaviors>
</behaviors>
<extensions>
  <behaviorExtensions>
    <add name="updateBehavior" type="RouterService.UpdateBehavior, RouterService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
  </behaviorExtensions>
</extensions>
<services>
  

и реализация поведения и расширение поведения

 public class UpdateBehavior : BehaviorExtensionElement, IServiceBehavior
{
    void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {
    }
    void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        var rulesUpdateExtension = new RulesUpdateExtension();
        serviceHostBase.Extensions.Add(rulesUpdateExtension);
    }
    void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }
    class RulesUpdateExtension : IExtension<ServiceHostBase>
    {
        ServiceHostBase _owner;
        List<EndpointAddress> _endpoints = new List<EndpointAddress>
                                                       {
                                                           new EndpointAddress("http://localhost:19338/Service1.svc"),
                                                           new EndpointAddress("http://localhost:20464/Service2.svc")
                                                       };

        void IExtension<ServiceHostBase>.Attach(ServiceHostBase owner)
        {
            this._owner = owner;

            UpdateRules(DateTime.Now.Second % 2 == 0 ? _endpoints[0] : _endpoints[1]);
        }

        void IExtension<ServiceHostBase>.Detach(ServiceHostBase owner)
        {
        }

        void UpdateRules(EndpointAddress endpoint)
        {
            var rc = new RoutingConfiguration();

            var serviceEndpoint = new ServiceEndpoint(
                    ContractDescription.GetContract(typeof(IService1)),
                    new BasicHttpBinding(),
                    endpoint);
            rc.FilterTable.Add(new MatchAllMessageFilter(), new List<ServiceEndpoint> { serviceEndpoint });

            this._owner.Extensions.Find<RoutingExtension>().ApplyConfiguration(rc);
        }
    }

    public override Type BehaviorType
    {
        get { return typeof(UpdateBehavior); }
    }

    protected override object CreateBehavior()
    {
        return new UpdateBehavior();
    }
}
  

Проблема в том, что последняя строка метода UpdateRules вызывает исключение NullReferenceException. Он не может найти это расширение, даже если я прикрепляю его к поведению. В примере из MSDN служба маршрутизации размещена в консольном приложении, и здесь я пытаюсь разместить ее в IIS. Я здесь чего-то не хватает…

Ответ №1:

В примере проекта RoutingService код в routing.cs программно внедряет RoutingExtension в RoutingService. Обычно это делается в файле конфигурации с помощью элемента behaviors> serviceBehaviors> поведение> маршрутизация, чтобы настроить таблицу фильтров для использования. Однако, поскольку службе WCF может быть назначено только одно поведение службы через файл конфигурации, пример проекта RoutingService динамически добавляет RoutingExtension при инициализации узла службы.

Чтобы сделать то же самое в IIS, вам необходимо создать пользовательскую фабрику хостов служб для выполнения той же функции, что и код routing.cs в примере проекта. Посмотрите в этой статье MSDN, как создать пользовательский хост. Здесь также показано, как вы могли бы настроить его с помощью IIS.