Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BrokerProperties REST header values not showing up in .NET client code

I'm writing two small pieces of C# code. The first is for a client-side Portable Class Library. All it does is send messages to an Azure Service Bus topic via the Azure Service Bus REST API, using HttpClient.

I populate the BrokerProperties header on the REST call with valid JSON, and I expect that on the server side, when I receive the message through a subscription, that I'll get my instance of BrokeredMessage.Properties populated with the values I sent from the client.

The one problem I've had on this side is that the documentation says to set Content-Type to application/atom+xml;type=entry;charset=utf-8, but even when I do I get application/json; charset=utf-8, so I'm just using application/json.

With that aside, as far as I can tell, this does what it's supposed to do. It creates the client and the request message, sets the headers, and sends the message. I get a 201 Created every time. Here's all of it:

    private async static void SendServiceBusMessage(Command command)
    {
        // Create the HttpClient and HttpRequestMessage objects
        HttpClient client = new HttpClient();
        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, topicUri);

        // Add the authorization header (CreateAuthToken does the SHA256 stuff)
        request.Headers.Add("Authorization", CreateAuthToken(topicUri, authSasKeyName, authSasKey));

        // Add the content (command is a normal POCO)
        // I've tried application/atom+xml;type=entry;charset=utf-8, always see application/json in the request
        request.Content = new StringContent(JsonConvert.SerializeObject(command), Encoding.UTF8, "application/json");

        // Add the command name and SessionId as BrokeredMessage properties
        var brokeredMessageProperties = new Dictionary<string, string>();
        brokeredMessageProperties.Add("CommandName", command.GetType().Name);
        brokeredMessageProperties.Add("SessionId", Guid.NewGuid().ToString());

        // Add the BrokerProperties header to the request
        request.Content.Headers.Add("BrokerProperties", JsonConvert.SerializeObject(brokeredMessageProperties));

        // I've also tried adding it directly to the request, nothing seems different
        // request.Headers.Add("BrokerProperties", JsonConvert.SerializeObject(brokeredMessageProperties));

        // Send it
        var response = await client.SendAsync(request);
        if (!response.IsSuccessStatusCode)
        {
            // Do some error-handling
        }
    }

and here's an example of the HTTP request it sends. Compare it to the example at the bottom of Send Message documentation... aside from the Content-Type, it looks (functionally) identical to me.

  POST https://myawesomesbnamespace.servicebus.windows.net/commands/messages HTTP/1.1
  Authorization: SharedAccessSignature sr=https%3A%2F%2Fmyawesomesbnamespace.servicebus.windows.net%2Fcommands%2Fmessages&sig=SomeValidAuthStuffHere
  Content-Type: application/json; charset=utf-8
  BrokerProperties: {"CommandName":"CreateJob_V1","SessionId":"94932660-54e9-4867-a020-883a9bb79fa1"}
  Host: myawesomesbnamespace.servicebus.windows.net
  Content-Length: 133
  Expect: 100-continue
  Connection: Keep-Alive

  {"JobId":"6b76e7e6-9499-4809-b762-54c03856d5a3","Name":"Awesome New Job Name","CorrelationId":"47fc77d9-9470-4d65-aa7d-690b65a7dc4f"}

However, when I receive the message on the server, the .Properties are empty. This is annoying.

The server code looks like this. It just gets a batch of messages and does a foreach loop.

    private async Task ProcessCommandMessages()
    {
        List<BrokeredMessage> commandMessages = (await commandsSubscriptionClient.ReceiveBatchAsync(serviceBusMessageBatchSize, TimeSpan.FromMilliseconds(waitTime_ms))).ToList();

        foreach (BrokeredMessage commandMessage in commandMessages)
        {
            // commandMessage.Properties should have CommandName and SessionId,
            // like I sent from the client, but it's empty
            // that's not good
            if (commandMessage.Properties.ContainsKey("CommandName"))
            {
                string commandName = commandMessage.Properties["CommandName"] as string;
                // Do some stuff
            }
            else
            {
                // This is bad, log an error
            }
        }
    }

So, I'm a bit stuck. Can anyone spot something I'm doing wrong here? Maybe it's the Content-Type problem and there's a way around it?

Thanks!

Scott

Seattle, WA, USA

like image 572
Scott Avatar asked Oct 25 '25 21:10

Scott


1 Answers

OK, finally getting back to this. What I misunderstood (and I'd argue the documentation isn't clear about) is that arbitrary properties cannot be passed through the BrokerProperties header. Only named properties from the BrokeredMessage class (like SessionId, Label, etc.) will come through Service Bus to the server.

For properties to show up in BrokeredMessage.Properties, they have to be passed as custom headers on the request. So, in my case,

    request.Headers.Add("CommandName", command.GetType().Name);

gets the CommandName property to show up on the server after the message is passed through Service Bus.

And to pass the SessionId value, I'll still want to pass it through BrokerProperties header.

like image 124
Scott Avatar answered Oct 27 '25 11:10

Scott



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!