ForwardingTopology
. This sample should be used only if EndpointOrientedTopology
is required.Prerequisites
An environment variable named AzureServiceBus.
with the connection string for the Azure Service Bus namespace.
Azure Service Bus Transport
This sample uses the Azure Service Bus Transport (Legacy).
Code walk-through
This sample has two endpoints:
Publisher
publishesBaseEvent
andDerivedEvent
events.Subscriber
subscribes to and handlesBaseEvent
andDerivedEvent
events.
DerivedEvent
derives from BaseEvent
. The difference between the two events is the Data
property provided with DerivedEvent
.
public class BaseEvent :
IEvent
{
public Guid EventId { get; set; }
}
public class DerivedEvent :
BaseEvent
{
public string Data { get; set; }
}
Publisher
The Publisher
will publish an event of type BaseEvent
or DerivedEvent
based on the input it receives from the console.
Subscriber
By default, all events handled in Subscriber
will be auto-subscribed. Default topology subscription behavior will create two subscriptions, one for each event.
Auto-subscription behavior
Normally, this would be fine. Not so with ASB transport and polymorphic events. Each subscription is filtering messages based on the NServiceBus.
header. When an event of BaseType
is published, it's going only into Samples.
subscription:
ForwardingTopology
is used.But whenever DerivedEvent
event is published, both Samples.
and Samples.
subscriptions get a copy of that message:
Since DerivedEvent
implements BaseEvent
, it's NServiceBus.
header will contain both types:
Events.DerivedEvent, Shared, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null;
Events.BaseEvent, Shared, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
Both filters will pick the DerivedEvent
message, causing duplicate delivery to the Subscriber
. The NServiceBus Subscriber
endpoint will invoke handlers for each type that message implements. The end result will be multiple invocations for the same message.
DerivedEvent sent. EventId: c3c07de2-433f-4b31-8f76-1b9826409471
2015-11-02 13:00:37.655 INFO DerivedEventHandler Received DerivedEvent. EventId: c3c07de2-433f-4b31-8f76-1b9826409471 Data: more data
2015-11-02 13:00:39.415 INFO BaseEventHandler Received BaseEvent. EventId: c3c07de2-433f-4b31-8f76-1b9826409471
2015-11-02 13:00:39.500 INFO DerivedEventHandler Received DerivedEvent. EventId: c3c07de2-433f-4b31-8f76-1b9826409471 Data: more data
2015-11-02 13:00:39.505 INFO BaseEventHandler Received BaseEvent. EventId: c3c07de2-433f-4b31-8f76-1b9826409471
How to restrict the message handlers
To address this in general and allow proper handling of polymorphic events, Subscriber
has do the following:
- Disable automatic subscription.
- Subscribe explicitly to the base events only of polymorphic events.
- Subscribe explicitly to the non-polymorphic events it's interested in.
endpointConfiguration.DisableFeature<AutoSubscribe>();
When an event is a polymorphic event, such as DerivedEvent
, the endpoint will subscribe to the base event only.
await endpointInstance.Subscribe<BaseEvent>()
.ConfigureAwait(false);
For this sample, configuring Subscriber
as described above will create the topology that only has the BaseEvent
subscription serving as "catch-all".
The sample now adheres to the expected polymorphic message handling
DerivedEvent sent. EventId: c23951b0-0864-4c35-8314-25f354d07d7d
2015-11-02 13:22:31.165 INFO DerivedEventHandler Received DerivedEvent. EventId: c23951b0-0864-4c35-8314-25f354d07d7d Data: more data
2015-11-02 13:22:31.175 INFO BaseEventHandler Received BaseEvent. EventId: c23951b0-0864-4c35-8314-25f354d07d7d
topology.RegisterPublisher(typeof(BaseEvent), "Samples.ASB.Polymorphic.Publisher");