Question Details

No question body available.

Tags

c# azureservicebus nservicebus

Answers (1)

February 27, 2026 Score: 3 Rep: 2,364 Quality: Medium Completeness: 100%

When moving from the single-topic topology to topic-per-event, an important change is that each concrete event type is published to its own topic. There is no longer a single bundle topic where inheritance can be handled implicitly via filters.

Because of that, subscribing to ProductOrdered does not automatically imply "all derived types." The transport does not infer your CLR inheritance hierarchy at the broker level. Something must explicitly define which concrete topics should flow to that handler.

Centralized explicit mapping (recommended starting point)

There is no built-in way to subscribe to “all derived types” without explicitly mapping them.

Publisher-side multiplexing to a shared ProductOrdered topic

The simplest approach is to centralize the mapping:

  • Scan your shared contracts assembly at startup
  • Find all non-abstract types assignable to ProductOrdered
  • Call topology.SubscribeTo\(...) for each

This keeps handlers clean (IHandleMessages\ stays as-is) and avoids maintaining lists in multiple places.

For most systems, this is the lowest complexity solution and aligns best with topic-per-event.

If you want to avoid enumerating derived types on subscribers entirely, you can route all derived events to a single topic:

topology.PublishTo("ProductOrdered");
topology.PublishTo("ProductOrdered");

Now all ProductOrdered family events go to one topic. Subscribers that want everything simply subscribe to that topic. If some subscribers only care about specific concrete types, you can promote the concrete type name to a native broker property:

transport.OutgoingNativeMessageCustomization = (operation, message) =>
{
    if (operation is MulticastTransportOperation multicast)
    {
        // Subject used here for demonstration only
        message.Subject = multicast.MessageType.FullName;
    }
};

Then define a CorrelationFilter on the subscription, for example:

resource subscription 'Microsoft.ServiceBus/namespaces/topics/subscriptions@2021-06-01-preview' = {
  name: '${productOrderedTopic.name}/subscriber'
  properties: {
    rule: {
      name: 'SomeConcreteProductOnly'
      filterType: 'CorrelationFilter'
      correlationFilter: {
        subject: 'MyNamespace.SomeConcreteProductOrdered'
      }
    }
  }
}

CorrelationFilter can perform well in practice and you can have many of those, so this can be a reasonable tradeoff. However:

  • You are reintroducing filtering overhead.
  • All derived events now share the same topic and quota.
  • You typically manage subscriptions and rules via infrastructure-as-code rather than auto-subscribe.

This is a valid choice, but it is a conscious move back toward grouped topics for that event family.

ProductOrdered is a stable/standalone contract

If ProductOrdered is a stable contract in its own assembly and consumers must not reference any product-specific assemblies, then subscriber-side enumeration will not work. Those endpoints cannot know about derived types at runtime, by design.

In that case, keep topic-per-event for concrete events and use auto-forwarding subscriptions to project them into a stable abstraction topic.

For example:

  • Topic: CarInsurance.OrderProcessing.CarInsuranceProductOrdered
    • Subscription: ProductOrderedForwarder
      • ForwardTo: OrderProcessing.ProductOrdered (topic)
  • Topic: HomeInsurance.OrderProcessing.HomeInsuranceProductOrdered
    • Subscription: ProductOrderedForwarder
      • ForwardTo: OrderProcessing.ProductOrdered (topic)

Consumers of the abstraction subscribe only to OrderProcessing.ProductOrdered and remain unaware of derived types.

  • Auto-forwarding is configured on the subscription and usually provisioned via IaC. Endpoint installers currently do not support that. That would be your choice similar to the CorrelationFilter. But you can use the ServiceBusAdministrationClient too to populate this at runtime or during installation phase although I would generally not recommend using elevated permissions outside the deployment pipeline.
  • Forwarding does not change the message type. The concrete event type is still what gets forwarded, so the payload must be compatible with ProductOrdered if consumers only reference the base contract but it sounds that is the case and NServiceBus will add that additional enclosed message type header.
  • Azure Service Bus supports a maximum of 4 forwarding hops, so avoid long forwarding chains but in general this will work fine since you still have room for an endpoint subscription forwarding to the input queue.

There is no automatic polymorphic subscription mechanism in topic-per-event without either explicit mapping or deliberate multiplexing. More details see and hints to advanced scenarios can be found on our topology documentation page.

If you have further questions or want to discuss your specific constraints, feel free to reach out directly to our support team.