1
votes

I want use NServiceBus with GetEventStore to create CQRS/EventSourcing solution.

I have a set of Events each is stamped with Aggregate type name and Aggregate id. My domain publishes events using NServiceBus. All events derive from one base type.

I want create message handler which subscribes to all events published by domain, so it can save events in EventStore.

I tried subscribe to my base Event but it doesn't work.

Is there any way to subscribe to all types of events? I don't also want to change NServiceBus configuration or add new handler in my EventStore worker each time I create new domain Event.

2
What version are you on?(we've fixed a few bugs related to subscribing to base classes recently)Andreas Öhlund
@AndreasÖhlund I used 4.2.0, I will try 4.3.0 later and I will update you.Sebastian.Belczyk
@AndreasÖhlund the problem was lying in my configuration. I didn't realize that EndpointConfig's namespace influence configuration.Sebastian.Belczyk

2 Answers

0
votes

I've managed to solve the problem. I have a base Event class and I publish events that derive from the base Event class. On my subscriber I subscribe to base Event and Handle method is firing every time derived event is published.

Messages project

public class Event : IEvent
{
}
public class Event1 : Event
{
}
public class Event2 : Event
{
}

Publisher project

Publishers EndpointConfig

namespace SemplePublisherNamespace
{
    using NServiceBus;
    public class EndpointConfig : IConfigureThisEndpoint, AsA_Publisher
    {

    }
}

Publishers OnBusStart class

public class OnBusStart : IWantToRunWhenBusStartsAndStops
{
    public IBus Bus { get; set; }
    void IWantToRunWhenBusStartsAndStops.Start()
    {
        Bus.Publish(new Event1());
        Bus.Publish(new Event2());
    }

    void IWantToRunWhenBusStartsAndStops.Stop()
    {
    }
}

Publishers app.config

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<configuration>
  <configSections>
    <section name="MessageForwardingInCaseOfFaultConfig" type="NServiceBus.Config.MessageForwardingInCaseOfFaultConfig, NServiceBus.Core" />
    <section name="AuditConfig" type="NServiceBus.Config.AuditConfig, NServiceBus.Core"/>
  </configSections>
  <MessageForwardingInCaseOfFaultConfig ErrorQueue="error"/>
  <AuditConfig QueueName="audit" />
</configuration>

Subscriber project

Subscribers EndpointConfig

namespace SampleSubscriber
{
    using NServiceBus;

    public class EndpointConfig : IConfigureThisEndpoint, AsA_Server
    {
    }
}

Subscribers app.config

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<configuration>
  <configSections>
    <section name="MessageForwardingInCaseOfFaultConfig" type="NServiceBus.Config.MessageForwardingInCaseOfFaultConfig, NServiceBus.Core" />
    <section name="UnicastBusConfig" type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core" />
    <section name="AuditConfig" type="NServiceBus.Config.AuditConfig, NServiceBus.Core" />
  </configSections>
  <MessageForwardingInCaseOfFaultConfig ErrorQueue="error" />
  <UnicastBusConfig>
    <MessageEndpointMappings>
      <add Assembly="Messages" Endpoint="SemplePublisherNamespace" />      
    </MessageEndpointMappings>
  </UnicastBusConfig>
  <AuditConfig QueueName="audit" />
</configuration>

Note that in MessageEndpointMappings secion when adding mapping we set Endpoint name and it's the same as namespace of EndpontConfig class in Publisher project.

Subscriber's Handler class

    public class Subscriber : IHandleMessages<Event>
    {
        public void Handle(Event message)
        {
            Console.WriteLine("Handle: "+message.GetType().Name);
        }

    }
0
votes

Another possible approach would be to have your Event acting as a generic envelope with the actual content inside:

public class GenericEnvelope
{
    ...
    public XmlElement Message { get; set; }
}

This still lets you subscribe once and then pass whatever the content you want but the advantage of such approach is that the envelope could possibly contain some message-oriented attributes that are not part of the message. Another advantage is that passing the content as XmlElement lets you implement your own message-level security/integrity (signing and/or encryption).