Azure Service Bus can't receive JSON body

2019-06-14 08:36发布

问题:

When debugging this code, the application stops. No error message or exception are shown.

Project X:

client.OnMessage((message) =>
{
    using (var stream = message.GetBody<Stream>())
    using (var streamReader = new StreamReader(stream, Encoding.UTF8))
    {
        var body = streamReader.ReadToEnd();
    }
 }

Below I'm POSTing JSON objects through a REST API.

Project Y:

public void CreateMessage<T>(T messageToSend, string queueAddress, WebClient webclient)
{
    var apiVersion = "&api-version=2014-01";
    var serializedMessage = JsonConvert.SerializeObject(messageToSend, Formatting.Indented);
    string receivedMessageBody = webclient.UploadString(queueAddress + "/messages" + "?timeout=60&" + apiVersion, "POST", serializedMessage);

}

I can see that messages are received in Azure portal, so there is no authentication problem. Also earlier when I passed data with the Azure SDK with the help of BrokeredMessage, I was able to receive JSON objects as expected. However, I need to use the REST API.

As seen in the picture, the MessageID is there, and I'm also able to get properties. But I want to read the content of the body.

Picture of received object

.

Any ideas how I can get the body?

回答1:

According to your description, I checked this issue and followed Send Message to send my messages to service bus queue.

ForContent-Type to application/atom+xml;type=entry;charset=utf-8, your payload need to be serialized using DataContractSerializer with a binary XmlDictionaryWriter. So you need to construct your payload as follows:

Define your object and send the message:

[DataContract]
public class DemoMessage
{
    [DataMember]
    public string Title { get; set; }
}

wc.Headers["Content-Type"] = "application/atom+xml;type=entry;charset=utf-8";
MemoryStream ms = new MemoryStream();
DataContractSerializer serializer = new DataContractSerializer(typeof(DemoMessage));
serializer.WriteObject(ms, new DemoMessage() { Title = messageBody });
wc.UploadString(sendAddress, "POST",System.Text.UTF8Encoding.UTF8.GetString(ms.ToArray()));

Then you could use the following code to receive the message:

var message = message.GetBody<DemoMessage>(new DataContractSerializer(typeof(DemoMessage)));

For Content-Type to text/plain or not be specified, you could serialize the payload as follows:

var messageBody = JsonConvert.SerializeObject(new DemoMessage(){ Title = messageBody }, Newtonsoft.Json.Formatting.Indented);
wc.UploadString(sendAddress, "POST", messageBody);

For receiving the message, you could use the code below:

using (var stream = message.GetBody<Stream>())
{
    using (var streamReader = new StreamReader(stream, Encoding.UTF8))
    {
        msg = streamReader.ReadToEnd();
        var obj=JsonConvert.DeserializeObject<DemoMessage>(msg);
    }
}

UPDATE:

When debugging this code, the application stops. No error message or exception are shown.

For console application, after configured the client.OnMessage, you need to use Console.ReadKey() or Console.ReadLine() to prevent your application from exiting. Moreover, you could try-catch-throw your processing within client.OnMessage to retrieve the detailed error message for troubleshooting.

UPDATE2:

I just used the following code in my console application with the target framework 4.6.2 and referenced WindowsAzure.ServiceBus.4.1.3.

static void Main(string[] args)
{   
    //send the message
    var wc = new WebClient();
    wc.Headers["Authorization"] = createToken("https://brucesb.servicebus.windows.net/order", "RootManageSharedAccessKey", "{your-key}");
    var messageBody = JsonConvert.SerializeObject(new DemoMessage() { Title = "hello world!!!!" }, Newtonsoft.Json.Formatting.Indented);
    wc.UploadString("https://brucesb.servicebus.windows.net/order/messages", "POST", messageBody);

    //receive the message
    QueueClient client = QueueClient.CreateFromConnectionString(connectionString, "order");
    client.OnMessage(message =>
    {
        using (var stream = message.GetBody<Stream>())
        {
            using (var streamReader = new StreamReader(stream, Encoding.UTF8))
            {
                var msg = streamReader.ReadToEnd();
                var obj = JsonConvert.DeserializeObject<DemoMessage>(msg);
                Console.WriteLine(msg);
            }
        }
    });
    Console.WriteLine("Press any key to exit...");
    Console.ReadLine();
}

static string createToken(string resourceUri, string keyName, string key)
{
    var expiry = (long)(DateTime.UtcNow.AddDays(1) - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
    string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;
    HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
    var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
    var sasToken = String.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}", HttpUtility.UrlEncode(resourceUri), HttpUtility.UrlEncode(signature), expiry, keyName);
    return sasToken;
}

Test: