Reputation: 1438
I'm using WCF routing service and I'm trying to Implement failover, I need to add filter table backuplist programmatically, this is a sample configuration:
<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>
I was able to add FilterTable which I found example in this question
here is my code snippet:
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();
so in my scenario ServiceOperation2
and ServiceOperation3
are the backup endpoints, I made lots of research I coudn't find a way to add backuplist Programmatically
any Idea how can I add backuplist to filterTable?
Upvotes: 0
Views: 627
Reputation: 1438
I ended up with this solution to dynamically generate config file
In my scenario, I load my endpoints from database and generated routing service configuration out of it,
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");
}
so first I generated configuration file and than create an intance of routing service like:
CreateRoutingConfiguration(serviceEndpoints);
routingHost = new ServiceHost(typeof(RoutingService));
routingHost.AddServiceEndpoint(typeof(System.ServiceModel.Routing.IRequestReplyRouter), mybinding, $"net.tcp://localhost:6000/Router");
routingHost.Open();
hope it will be helpful for someone
Upvotes: 2
Reputation: 6344
I've never done this, but a quick look through the documentation on MSDN for Message Filters shows that alternative backup endpoints are configured via the FilterTableElementEntry class (BackupList property).
A filter table is a named collection of FilterTableEntryElement objects that define the association between a filter, a primary destination endpoint, and a list of alternative backup endpoints. The filter table entries also allow you to specify an optional priority for each filter condition.
Check for Filter Table and BackupList on Google, and you'll come across examples of usage of this. This example looks particularly promising with plenty of comments describing the steps.
Upvotes: 1