Mr. Spock
Mr. Spock

Reputation: 355

NServicebus receive messages without all the NServicebus specific stuff

I am new to NServicebus and have struggled to find an answer in the documentation.

I am trying to receive a message that is posted to Amazon SQS in a simple JSON format like this:

"MyMessage": {
    "Id": 1,
    "Name": "Name",
    "Field1": "text",
    "Field2": 1,
    "Field3": false
}

However whenever this gets sent to the queue my NServicebus subscriber says it is a poison message and doesn't try to handle it.

I realize that this message is missing a lot of NServicebus stuff because when I publish a message via NServicebus it looks like this:

{
    "Headers": {
        "NServiceBus.MessageId": "a244a014-e331-41e6-b6ca-aed6011af905",
        "NServiceBus.MessageIntent": "Publish",
        "NServiceBus.ConversationId": "e42f0308-4c51-4787-ade0-aed6011af90f",
        "NServiceBus.CorrelationId": "a244a014-e331-41e6-b6ca-aed6011af905",
        "NServiceBus.OriginatingMachine": "DESKTOP-1234567",
        "NServiceBus.OriginatingEndpoint": "endpoint",
        "$.diagnostics.originating.hostid": "da7dce712dfbc0f093aa30eb7f25d2b4",
        "NServiceBus.ContentType": "application/json",
        "NServiceBus.EnclosedMessageTypes": "Type",
        "NServiceBus.Version": "7.7.3",
        "NServiceBus.TimeSent": "2022-07-18 17:10:16:400164 Z"
    },
    "Body": "Base 64 encoded string here",
    "S3BodyKey": null
}

The problem is the message I am receiving is not published via NServicebus and comes in the format I showed above. It doesn't have all of the headers and a body that is base64 encoded.

Is there a way to set up NServicebus to be able to receive and handle such a message? Or is it just not built to handle stuff like this?

Note: This is a .Net 6 application

Edit: I found this article that mentions how NServicebus can receive messages without all the headers, but it doesn't mention how.

https://www.bradjolicoeur.com/Article/nsb-features-message-headers

Upvotes: 1

Views: 358

Answers (2)

Sebastian Weber
Sebastian Weber

Reputation: 6806

I'm a bit late to the party but this should do the trick quite nicely:

public class SetTheMessageTypeYouExpect : Behavior<IIncomingPhysicalMessageContext>
{
    public override Task Invoke(IIncomingPhysicalMessageContext context, Func<Task> next)
    {
        context.Message.Headers[Headers.EnclosedMessageTypes] = typeof(MyNativeMessage).AssemblyQualifiedName;
        return next();
    }
}

and register the behavior

endpointConfiguration.Pipeline.Register(
    new SetTheMessageTypeYouExpect(),
    "Translate raw json to message");

Upvotes: 0

Hadi Eskandari
Hadi Eskandari

Reputation: 26354

What you want is called Native Send and is actually documented. You have to conform your messages to the format NServiceBus expects in order to be able to have handlers correctly process it.

A native send function would look like this:

public static async Task SendMessage(IAmazonSQS sqsClient, string queue, string messageBody, Dictionary<string, string> headers)
{
    var bodyBytes = Encoding.UTF8.GetBytes(messageBody);
    var base64Body = Convert.ToBase64String(bodyBytes);
    var serializedMessage = Newtonsoft.Json.JsonConvert.SerializeObject(new
    {
        Headers = headers,
        Body = base64Body,
    });
    var queueUrlResponse = await sqsClient.GetQueueUrlAsync(QueueNameHelper.GetSqsQueueName(queue));
    await sqsClient.SendMessageAsync(queueUrlResponse.QueueUrl, serializedMessage);
}

To use this you'd need to specify message type and some other header values:

await SendMessage(
    sqsClient: client,
    queue: "samples-sqs-nativeintegration",
    messageBody: "{Property:'PropertyValue'}",
    headers: new Dictionary<string, string>
    {
        {"NServiceBus.EnclosedMessageTypes", "MessageTypeToSend"},
        {"NServiceBus.MessageId", "99C7320B-A645-4C74-95E8-857EAB98F4F9"}
    }
);

Upvotes: 1

Related Questions