3
votes

I am trying to hook up a primitive TestService endpoint to a primitive WCF service, where the WCF service instance sends a primitive TestCommand to the TestService endpoint, using latest NSB 5.2.9/Host6.0:

[ServiceBehavior(
    InstanceContextMode = InstanceContextMode.PerCall,
    ConcurrencyMode = ConcurrencyMode.Single )]
public class MyService : IMyService
{
    private readonly IBus bus;

    public MyService( IBus bus )
    {
        this.bus = bus;
    }

    public void Test( string value )
    {
        bus.Send( new TestCommand( value ) );
    }
}

I am unable to configure this correctly. Error message:

Exception thrown: 'System.InvalidOperationException' in System.ServiceModel.dll

Additional information: No destination could be found for message type Company.App.Commands.TestCommand. Check the <**MessageEndpointMappings**> section of the configuration of this endpoint for an entry either for this specific message type or for its assembly.

I am able to do this without using the "unobtrusive node", but not with conventions. I am very confused as to how to configure this after I tried everything. The WCF Host is self hosted, while the Test endpoint is hosted by NServiceBus.Host.

  1. web.config of the IIS WCF Host application
  2. via NServiceBus.Config.IConfigurationSource
  3. via NServiceBus.Config.IProvideConfiguration

Right now I have this in the web.config, which is seemignly useless and ignored:

<MessageEndpointMappings>
    <add Assembly="Company.App.Messages" Type="Company.App.Commands.TestCommand" Endpoint="testservice" />
</MessageEndpointMappings>

"Unobtrusive mode": I have created a separate project for conventions, which is referenced by the WCF host endpoint and the TestService endpoint.

public class MessageConventions : INeedInitialization
{
    public void Customize( BusConfiguration configuration )
    {
        var conventions = configuration.Conventions();

        conventions.DefiningCommandsAs( t => t.Namespace != null && t.Namespace.StartsWith( "Company.App" ) && t.Namespace.EndsWith( "Commands" ) );
        conventions.DefiningEventsAs( t => t.Namespace != null && t.Namespace.StartsWith( "Company.App" ) && t.Namespace.EndsWith( "Events" ) );
        conventions.DefiningMessagesAs( t => t.Namespace != null && t.Namespace.StartsWith( "Company.App" ) );

        //conventions.DefiningTimeToBeReceivedAs( t => GetTimeToBeReceived( t ) )
        //conventions.DefiningDataBusPropertiesAs( pi => IsDataBusProperty( pi ) );
    }
}

These conventions are seemingly picked up by TestService.

My understanding is that the IIS WCF Host must declare the mappings in its web.config, so that the WCF service knows where to send the messages with bus.Send(new TestCommand("test")); but this does not work.

Then I tried defining these mappings in both endpoints, but no luck.

This method will output all message types that where found using the conventions above:

public class Startup : IWantToRunWhenBusStartsAndStops
{
public MessageMetadataRegistry Messages { get; set; }
public Conventions Conventions { get; set; }

public void Start()
{
    var getAllMessagesMethod = typeof( MessageMetadataRegistry ).GetMethod( "GetAllMessages",
        BindingFlags.NonPublic | BindingFlags.Instance );

    var allMessages = getAllMessagesMethod.Invoke( Messages, new object[ 0 ] ) as IEnumerable<MessageMetadata>;

    foreach ( var metadata in allMessages )
    {
        Type type = metadata.MessageType;
        string name = type.FullName;

        if ( this.Conventions.IsInSystemConventionList( type ) )
            Console.WriteLine( "System Msg: {0}", name );
        else if ( this.Conventions.IsCommandType( type ) )
            Console.WriteLine( "   Command: {0}", name );
        else if ( this.Conventions.IsEventType( type ) )
            Console.WriteLine( "     Event: {0}", name );
        else if ( this.Conventions.IsMessageType( type ) )
            Console.WriteLine( "   Message: {0}", name );

        if ( metadata.TimeToBeReceived != TimeSpan.MaxValue )
            Console.WriteLine( "            TimeToBeReceived={0}", metadata.TimeToBeReceived );
    }
}

public void Stop()
{
}
}

Above method outputs the message type "TestCommand", so it knows about the conventions made.

I already checked 1000x for typos, casing, everyhting. I cleaned the solution. My question is: why can't NServiceBus find the endpoint?

Please help.

1
Can you post your mappings from the web.config?Tyler Day
@TylerDay thanks, I updated my question. The thing to remember is, I tried to configure this with and WTIHOUT the web.config, using IConfigurationSource and IProvideConfiguration. None of these work. Thanks!John
Your webconfig maps a command named "RunTestCommand", not "TestCommand" as your sample code shows.Tyler Day
@TylerDay that wasn't it.Just a type while annonymizing the code above. Apologies.John

1 Answers

1
votes

Unobtrusive means that you tell NServiceBus which classes are command and events by conventions rather than implementing the marker interfaces, you still need to add a message mapping in the app/web config so that NServiceBus knows which queue to send the message to.

The exception is suggesting that is your problem

Check the <**MessageEndpointMappings**> section of the configuration of this endpoint for an entry either for this specific message type or for its assembly.

Make sure you still have something like this in your web.config:

<UnicastBusConfig>
  <MessageEndpointMappings>
    <add Messages="Company.App.Commands.TestCommand, Company.App.Commands" Endpoint="test.server" />
  </MessageEndpointMappings>
</UnicastBusConfig>

EDIT

Now that you have posted your web.config, the problem looks like you have the wrong type name in the web.config:

<add Assembly="Company.App.Messages" Type="Company.App.Commands.RunTestCommand"

but you're doing this bus.Send(new TestCommand(value));

So the web.config is wrong, it should be

<add Assembly="Company.App.Messages" Type="Company.App.Commands.TestCommand"