Reputation: 62886
I need to customise each method in a WCF service - add logging.
So, I install a dedicated operation behavior for each operation when the service host is created:
public class CoreServiceHostFactory : ServiceHostFactory
{
#region Overrides of ServiceHostFactory
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
var host = base.CreateServiceHost(serviceType, baseAddresses);
var operationBehavior = new WcfOperationBehavior();
host.Description.Endpoints
.SelectMany(e => e.Contract.Operations)
.ForEach(o => o.Behaviors.Add(operationBehavior));
return host;
}
#endregion
}
It works locally, but when deployed in QA fails with
The value could not be added to the collection, as the collection already contains an item of the same type: ... This collection only supports one instance of each type. Parameter name: item
The relevant section of the web.config is:
<services>
<service name="DeviceServices.DeviceService" behaviorConfiguration="SLDeviceServices.ServiceBehavior">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="StandardBindingSSL" contract="DeviceServices.IDeviceService">
</endpoint>
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="StandardBinding" contract="DeviceServices.IDeviceService">
</endpoint>
</service>
<service name="DeviceServices.DeviceServiceJSON" behaviorConfiguration="SLDeviceServices.ServiceBehavior">
<endpoint address="" binding="webHttpBinding" bindingConfiguration="StandardBindingSSL" contract="DeviceServices.DeviceServiceJSON" behaviorConfiguration="DeviceServices.JSONDeviceServiceBehavior">
</endpoint>
<endpoint address="" binding="webHttpBinding" bindingConfiguration="StandardBinding" contract="DeviceServices.DeviceServiceJSON" behaviorConfiguration="DeviceServices.JSONDeviceServiceBehavior">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="SLDeviceServices.ServiceBehavior">
<serviceMetadata httpsGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="DeviceServices.JSONDeviceServiceBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
I fail to understand what is the problem. Anyone?
Upvotes: 2
Views: 3351
Reputation: 199
The problem when you access multiple services. Need to check for duplicates when adding operation behavior
host.Description.Endpoints
.Select(e => e.Contract)
.Distinct()
.SelectMany(c => c.Operations)
.ForEach(o =>
{
if(o.Behaviors.Any(x=> x.GetType().Equals(typeof(WcfOperationBehavior))))
{
o.Behaviors.Add(operationBehavior));
}
});
Upvotes: 0
Reputation: 62886
I found the root cause. In QA the service has two endpoints - http and https, but both are bound to the same Contract.
Hence the code
host.Description.Endpoints
.SelectMany(e => e.Contract.Operations)
.ForEach(o => o.Behaviors.Add(operationBehavior));
traverses the same Contract twice. The fix is:
host.Description.Endpoints
.Select(e => e.Contract)
.Distinct()
.SelectMany(c => c.Operations)
.ForEach(o => o.Behaviors.Add(operationBehavior));
Upvotes: 2