2
votes

With NServiceBus you can subscribe by interface, eg:

public class MyEvent: ISomeInterface {}

public class Handler: IHandleMessages<ISomeInterface>{...}

This all seems to work happily, however when you have multiple interfaces eg:

public class MyEvent: ISomeInterface, ISomeOtherInterface {}

public class Handler: IHandleMessages<ISomeInterface>{/*Works fine*/}

public class Handler: IHandleMessages<ISomeOtherInterface>{/*Doesnt work*/}

When using pub/sub the message is correctly subscribed to in either case, but when the message is actually published the receiving service errors with:

No handlers could be found for message type: ISomeInterface

It appears to only work if the interface you are handling is the first on the sent message class. If I swap the order of interfaces on the actual event implementation around the second handler works fine but the first errors with a similar message (ie order of interfaces is whats causing the issue)

Is there some way to handle messages by interface no matter what order the interfaces were in when the message was constructed?

I've tried this with the handler using NSB 3 and NSB 4 both produce the same result.

EDIT:

As requested heres a more detailed snippet of the subscriber config I am using. I've also put together a minimal repro pub/sub app to demonstrate the issue I'm having (on github here).

Configure.Features.Disable<NServiceBus.Features.TimeoutManager>().Disable<NServiceBus.Features.SecondLevelRetries>();
Configure.With()
    .DefineEndpointName("nsbinterfaces.subscriber")
    .DefiningEventsAs(t => t.Namespace != null && t.Namespace.Contains(".Events"))
    //.NinjectBuilder(kernel)
    .DefaultBuilder()
    .UseTransport<Msmq>()
        .PurgeOnStartup(false)
    .MsmqSubscriptionStorage("nsbinterfaces.subscriber")
    .UnicastBus()
        .LoadMessageHandlers()
        .ImpersonateSender(false)
    .CreateBus()
    .Start(
        () => Configure.Instance.ForInstallationOn<NServiceBus.Installation.Environments.Windows>().Install());
3
Which container are you using? Seems very likely that it has to do with container automatic registration.Phil Sandler
@PhilSandler Im using the NServicebus.Ninject adapter, ill try swapping it out for something else on Monday and see if that sorts it out. It should just work in this use case shouldn't it? I'm not missing some good this isn't allowed?Not loved
Can you share the code to reproduce this?Sean Farmar
@SeanFarmar see my edit + example repro solutionNot loved
@PhilSandler I tried also with the default builder and it seemed not to help. Any other ideas?Not loved

3 Answers

2
votes

After looking at the repro, I think I know what's going on.

Your Publisher knows about it's own event (MyEvent) and two interfaces that it implements. The two interfaces are in an assembly that is shared.

Your subscriber knows nothing about MyEvent, so it doesn't know that it implements both interfaces. It's either an ISomeInterface or an ISomeOtherInterface, so it deserializes it to one of those types.

Since the order of the interface seems to dictate what type of message it is received as, I would guess that NSB will deserialize the message to the first type it sees that it knows about (per process).

    <?xml version="1.0"?>
    <Messages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"    
     xmlns="http://tempuri.net/NsbInterfaces.Publisher.Events" 
     xmlns:baseType="NsbInterfaces.Events.ISomeInterface" 
     xmlns:baseType1="NsbInterfaces.Events.ISomeOtherInterface">    
    <MyEvent></MyEvent>
    </Messages>
1
votes

You need to move you interface implementation to the shared assembly (NsbInterfaces.Events)

Added a pull request to you repo

HTH

0
votes

I asked this question in the NSB forums and its been converted to an issue, which looks like it should be resolved in v5 of the software. (https://github.com/Particular/NServiceBus/issues/2301)

Until its fixed I think there's 2 options:

  • Send it as 2 separate messages
  • Put the implementation into the published library (Thanks @seanfarmar)