在 WCF 端点的相同 windows 服务器服务总线命名空间中有两个不同的主题
Having two different topics within same windows server service bus namespace in WCF endpoint
我定义了两个端点,指向两个不同的服务总线主题。使用相同的 transportClientEndpointBehavior 和相同的服务。
<endpointBehaviors>
<behavior name="securityBehavior">
<transportClientEndpointBehavior>
<tokenProvider>
<windowsAuthentication>
<stsUris>
<stsUri value="https://on-permises:9355/Namespace" />
</stsUris>
</windowsAuthentication>
</tokenProvider>
</transportClientEndpointBehavior>
</endpointBehaviors>
<customBinding>
<binding name="messagingBinding" >
<textMessageEncoding messageVersion="None" writeEncoding="utf-8" >
<readerQuotas maxStringContentLength="2147483647"/>
</textMessageEncoding>
<netMessagingTransport/>
</binding>
</customBinding>
<endpoint name="endpoint1"
address="sb://on-permises/Namespace/topic1"
listenUri="sb://on-permises/Namespace/topic1/subscriptions/sub"
binding="customBinding"
bindingConfiguration="messagingBinding"
contract="WCFService.IService1"
behaviorConfiguration="securityBehavior" />
<endpoint name="endpoint2"
address="sb://on-permises/Namespace/topic2"
listenUri="sb://on-permises/Namespace/topic2/subscriptions/sub"
binding="customBinding"
bindingConfiguration="messagingBinding"
contract="WCFService.IService2"
behaviorConfiguration="securityBehavior" />
一旦我 运行 应用程序,我得到错误:
System.ArgumentException:无法将值添加到集合中,因为集合中已包含相同类型的项目:'Microsoft.ServiceBus.TransportClientEndpointBehavior'。此集合仅支持每种类型的一个实例。
参数名称:item
我尝试定义两个不同的端点行为,但得到了同样的错误。
这里的任何帮助都会有所帮助。
找到解决方案,问题是服务主机试图在 WSDL/Metadata 中添加这两个服务端点。这是没有必要的。因此,在 ServiceMetadataContractBehavior (IContractBehavior) 的帮助下,停止公开 WSDL/Metadata .
任何更好的方法或更正请告诉我。
public class DisableContractMetadata : Attribute, IContractBehavior
{
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
/// Here ServiceMetadataContractBehavior type is derived from IContractBehavior
/// MetadataGenerationDisabled property of ServiceMetadataContractBehavior type = flase disables disables exposing WSDL
contractDescription.ContractBehaviors.Add(new ServiceMetadataContractBehavior() { MetadataGenerationDisabled = true });
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
}
}
请注意,上述答案不完整,因为它实际上并未实现 IContractBehavior
。
由于是托管多个服务造成的,您也可以在主机中进行:
ContractDescription contractDescription = ContractDescription.GetContract(typeof(MyService));
contractDescription.ContractBehaviors.Add(new ServiceMetadataContractBehavior() { MetadataGenerationDisabled = true });
或者,如果您在一个类型上有多个合同,请使用:
private static void DisableMetadataGeneration(Type serviceType)
{
// prevent this error due to hosting multiple services:
// System.ArgumentException: The value could not be added to the collection, as the collection already contains an item of the same type: 'Microsoft.ServiceBus.TransportClientEndpointBehavior'. This collection only supports one instance of each type.
foreach (Type contractType in GetContracts(serviceType))
{
ContractDescription contractDescription = ContractDescription.GetContract(contractType, serviceType);
contractDescription.ContractBehaviors.Add(new ServiceMetadataContractBehavior() { MetadataGenerationDisabled = true });
}
}
private static Type[] GetContracts(Type serviceType)
{
System.Diagnostics.Debug.Assert(serviceType.IsClass);
Type[] interfaces = serviceType.GetInterfaces();
List<Type> contracts = new List<Type>();
foreach (Type type in interfaces)
{
if (type.GetCustomAttributes(typeof(ServiceContractAttribute), false).Any())
{
contracts.Add(type);
}
}
return contracts.ToArray();
}
我定义了两个端点,指向两个不同的服务总线主题。使用相同的 transportClientEndpointBehavior 和相同的服务。
<endpointBehaviors>
<behavior name="securityBehavior">
<transportClientEndpointBehavior>
<tokenProvider>
<windowsAuthentication>
<stsUris>
<stsUri value="https://on-permises:9355/Namespace" />
</stsUris>
</windowsAuthentication>
</tokenProvider>
</transportClientEndpointBehavior>
</endpointBehaviors>
<customBinding>
<binding name="messagingBinding" >
<textMessageEncoding messageVersion="None" writeEncoding="utf-8" >
<readerQuotas maxStringContentLength="2147483647"/>
</textMessageEncoding>
<netMessagingTransport/>
</binding>
</customBinding>
<endpoint name="endpoint1"
address="sb://on-permises/Namespace/topic1"
listenUri="sb://on-permises/Namespace/topic1/subscriptions/sub"
binding="customBinding"
bindingConfiguration="messagingBinding"
contract="WCFService.IService1"
behaviorConfiguration="securityBehavior" />
<endpoint name="endpoint2"
address="sb://on-permises/Namespace/topic2"
listenUri="sb://on-permises/Namespace/topic2/subscriptions/sub"
binding="customBinding"
bindingConfiguration="messagingBinding"
contract="WCFService.IService2"
behaviorConfiguration="securityBehavior" />
一旦我 运行 应用程序,我得到错误: System.ArgumentException:无法将值添加到集合中,因为集合中已包含相同类型的项目:'Microsoft.ServiceBus.TransportClientEndpointBehavior'。此集合仅支持每种类型的一个实例。 参数名称:item
我尝试定义两个不同的端点行为,但得到了同样的错误。 这里的任何帮助都会有所帮助。
找到解决方案,问题是服务主机试图在 WSDL/Metadata 中添加这两个服务端点。这是没有必要的。因此,在 ServiceMetadataContractBehavior (IContractBehavior) 的帮助下,停止公开 WSDL/Metadata .
任何更好的方法或更正请告诉我。
public class DisableContractMetadata : Attribute, IContractBehavior
{
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
/// Here ServiceMetadataContractBehavior type is derived from IContractBehavior
/// MetadataGenerationDisabled property of ServiceMetadataContractBehavior type = flase disables disables exposing WSDL
contractDescription.ContractBehaviors.Add(new ServiceMetadataContractBehavior() { MetadataGenerationDisabled = true });
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
}
}
请注意,上述答案不完整,因为它实际上并未实现 IContractBehavior
。
由于是托管多个服务造成的,您也可以在主机中进行:
ContractDescription contractDescription = ContractDescription.GetContract(typeof(MyService));
contractDescription.ContractBehaviors.Add(new ServiceMetadataContractBehavior() { MetadataGenerationDisabled = true });
或者,如果您在一个类型上有多个合同,请使用:
private static void DisableMetadataGeneration(Type serviceType)
{
// prevent this error due to hosting multiple services:
// System.ArgumentException: The value could not be added to the collection, as the collection already contains an item of the same type: 'Microsoft.ServiceBus.TransportClientEndpointBehavior'. This collection only supports one instance of each type.
foreach (Type contractType in GetContracts(serviceType))
{
ContractDescription contractDescription = ContractDescription.GetContract(contractType, serviceType);
contractDescription.ContractBehaviors.Add(new ServiceMetadataContractBehavior() { MetadataGenerationDisabled = true });
}
}
private static Type[] GetContracts(Type serviceType)
{
System.Diagnostics.Debug.Assert(serviceType.IsClass);
Type[] interfaces = serviceType.GetInterfaces();
List<Type> contracts = new List<Type>();
foreach (Type type in interfaces)
{
if (type.GetCustomAttributes(typeof(ServiceContractAttribute), false).Any())
{
contracts.Add(type);
}
}
return contracts.ToArray();
}