WCF маршрутизация, как добавить Backuplist программно

Я использую службу маршрутизации WCF и пытаюсь реализовать аварийное переключение, мне нужно программно добавить резервный список таблицы фильтров, это пример конфигурации:

<system.serviceModel>
          <client>
            <endpoint address="http://localhost:8081/Service1" binding="basicHttpBinding"
                      contract="*" name="ServiceOperation1" />
            <endpoint address="http://localhost:8081/Service2" binding="basicHttpBinding"
                      contract="*" name="ServiceOperation2" />
            <endpoint address="http://localhost:8081/Service3" binding="basicHttpBinding"
                      contract="*" name="ServiceOperation3" />
          </client>
          <routing>
            <filters>
              <filter name="MatchAllFilter" filterType="MatchAll" />
            </filters>
            <filterTables>
              <filterTable name="RoutingTable">
                <add filterName="MatchAllFilter" endpointName="ServiceOperation1" backupList="BackUps" />
              </filterTable>
            </filterTables>
            <backupLists>
              <backupList name="BackUps">
                <add endpointName="ServiceOperation2"/>
                <add endpointName="ServiceOperation3" />
              </backupList>
            </backupLists>
          </routing>
          <behaviors>
            <serviceBehaviors>
              <behavior name="">
                <routing filterTableName="RoutingTable" />
              </behavior>
            </serviceBehaviors>
          </behaviors>
            <services>
                <service name="System.ServiceModel.Routing.RoutingService">
                  <endpoint address="binary" binding="basicHttpBinding"
                           contract="System.ServiceModel.Routing.IRequestReplyRouter" name="VirtualEndpoint" />
                    <host>
                        <baseAddresses>
                            <add baseAddress="http://localhost:8080/RoutingService/Router" />
                        </baseAddresses>
                    </host>
                </service>
            </services>
</system.serviceModel>

Мне удалось добавить FilterTable, который я нашел пример в этом вопросе

вот мой фрагмент кода:

var routingHost = new ServiceHost(typeof(RoutingService));
var routingEp = routingHost.AddServiceEndpoint(typeof(System.ServiceModel.Routing.IRequestReplyRouter), mybinding, url);      
var filterTable = new MessageFilterTable<IEnumerable<ServiceEndpoint>>();   
filterTable.Add(new MatchAllMessageFilter(), new List<ServiceEndpoint>()
                        {
                            serviceoperation1Endpoint
                        });


 routingHost.Description.Behaviors.Add(
                              new RoutingBehavior(new RoutingConfiguration(filterTable, false)));

routingHost.open();

так по моему сценарию ServiceOperation2 а также ServiceOperation3 являются конечными точками резервного копирования, я провел много исследований, я не нашел способа добавить резервный список программно

Любая идея, как я могу добавить резервную копию в filterTable?

2 ответа

Решение

Я в конечном итоге с этим решением для динамического создания файла конфигурации

В моем сценарии я загружаю свои конечные точки из базы данных и генерирую конфигурацию службы маршрутизации из нее,

public class MyServiceEndPoint 
{
    public string TypeName { get; set; }

    public string Url { get; set; }

    public string Name { get; set; }
}

//// generates routing service configuration section, including client enoints/filterTable/backups and routing service behavior
private void CreateRoutingConfiguration(List<MyServiceEndPoint> serviceEndpoints)
{
     ///// group endopints by Name, each service could have multiple endpoints ( 1 main and n backup endpoints)
    var groupedEndpoitns = (from endp in serviceEndpoints
                                    group endp by endp.Name into endpGroup
                                    select new { ServiceName = endpGroup.Key, EndPoint = endpGroup }).ToList();



    var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
    var serviceModelSectionGroup = System.ServiceModel.Configuration.ServiceModelSectionGroup.GetSectionGroup(config);

    var routingSection = (RoutingSection)serviceModelSectionGroup.Sections["routing"];
    var clientsection = (ClientSection)serviceModelSectionGroup.Sections["client"];
    var bindingSection = (BindingsSection)serviceModelSectionGroup.Sections["bindings"];
    var behaviorSection = (BehaviorsSection)serviceModelSectionGroup.Sections["behaviors"];

    bindingSection.NetTcpBinding.Bindings.Clear();
    clientsection.Endpoints.Clear();
    var filterTable = new FilterTableEntryCollection() { Name = "RoutingTable" };
    routingSection.Filters.Clear();
    routingSection.FilterTables.Clear();
    routingSection.BackupLists.Clear();

    var nettcpBinding = new NetTcpBindingElement()
    {
        Name = "myTcpBinding",
        TransferMode = TransferMode.Buffered,
        MaxBufferSize = 2147483647,
        MaxReceivedMessageSize = 2147483647,        
        SendTimeout = new TimeSpan(0, 10, 0),
        ReceiveTimeout = new TimeSpan(0, 10, 0),

    };

    nettcpBinding.Security.Mode = SecurityMode.None;
    bindingSection.NetTcpBinding.Bindings.Add(nettcpBinding);


    foreach (var endpointGroup in groupedEndpoitns)
    {
        var backupListItem = new BackupEndpointCollection();
        backupListItem.Name = endpointGroup.ServiceName + "Backup";

        var filter = new FilterElement();
        filter.Name = endpointGroup.ServiceName + "Filter";
        filter.FilterType = FilterType.Custom;
        filter.CustomType = "MyServiceContractMessageFilterType,asemblyName";
        filter.FilterData = endpointGroup.EndPoint.FirstOrDefault().ClientTypeName;
        routingSection.Filters.Add(filter);

        int endpointCount = 0;
        List<ChannelEndpointElement> channelEndpoints = new List<ChannelEndpointElement>();
        foreach (var endpoint in endpointGroup.EndPoint)
        {
            endpointCount++;
            var channelEndpoint = new ChannelEndpointElement();
            channelEndpoint.Address = new Uri(endpoint.Url);
            channelEndpoint.Binding = "netTcpBinding";
            channelEndpoint.BindingConfiguration = "myTcpBinding";
            channelEndpoint.Contract = "*";
            channelEndpoint.Name = $"{endpoint.Name}EndPoint{endpointCount}";
            clientsection.Endpoints.Add(channelEndpoint);
            channelEndpoints.Add(channelEndpoint);

        }

        var firstChannelEndpoint = channelEndpoints.FirstOrDefault(); /// this endpoint will be selected as main endpoint
        var filterTableItem = new FilterTableEntryElement();
        filterTableItem.FilterName = filter.Name;
        filterTableItem.EndpointName = firstChannelEndpoint.Name;
        filterTableItem.BackupList = backupListItem.Name;
        filterTable.Add(filterTableItem);    

        foreach (var backupEndpoints in channelEndpoints)
        {
            backupListItem.Add(new BackupEndpointElement() { EndpointName = backupEndpoints.Name });
            routingSection.BackupLists.Add(backupListItem);
        }
    }

    routingSection.FilterTables.Add(filterTable);    
    behaviorSection.ServiceBehaviors.Clear();
    var behavior = new ServiceBehaviorElement();
    behavior.Add(new RoutingExtensionElement() { FilterTableName = filterTable.Name });
    behaviorSection.ServiceBehaviors.Add(behavior);
    config.Save(ConfigurationSaveMode.Modified, false);
    ConfigurationManager.RefreshSection("system.serviceModel/routing");
    ConfigurationManager.RefreshSection("system.serviceModel/client");        
ConfigurationManager.RefreshSection("system.serviceModel/behaviors");
}

Итак, сначала я сгенерировал файл конфигурации, а затем создал службу маршрутизации, например:

CreateRoutingConfiguration(serviceEndpoints);
routingHost = new ServiceHost(typeof(RoutingService));
routingHost.AddServiceEndpoint(typeof(System.ServiceModel.Routing.IRequestReplyRouter), mybinding, $"net.tcp://localhost:6000/Router");
routingHost.Open();

надеюсь, это будет полезно для кого-то

Я никогда не делал этого, но быстрый просмотр документации по MSDN для фильтров сообщений показывает, что альтернативные конечные точки резервного копирования настраиваются с помощью класса FilterTableElementEntry (свойство BackupList).

Таблица фильтров - это именованная коллекция объектов FilterTableEntryElement, которые определяют связь между фильтром, основной конечной точкой назначения и списком альтернативных резервных конечных точек. Записи таблицы фильтров также позволяют указывать необязательный приоритет для каждого условия фильтра.

Проверьте таблицы фильтров и BackupList в Google, и вы столкнетесь с примерами использования этого. Этот пример выглядит особенно многообещающим с большим количеством комментариев, описывающих шаги.

Другие вопросы по тегам