2
votes

I'm building a Windows Phone app and cannot ouse the Microsoft.ServiceBus.Messaging.QueueClient class.

I then try to use the Azure Service Bus REST API to do a Send, but that requires that I build a SAS token. But to build the SAS token I need to use Windows.Security.Cryptography.Core.MacAlgorithmNames.HmacSha256. This class is shown in type-ahead but when compiling it does not exist.

How can I post a message to a Service Bus Queue or Topic using the Send REST API?

1

1 Answers

2
votes

I'll include the complete code that send a message to the Service Bus using the REST API, including creating the SAS token and HmacSha256 hash.

You need to update the sample with your unique Service Bus namespace and keys, and you will probably want to store it somewhere better than in the method...

How to create a SAS token is documented in http://msdn.microsoft.com/library/azure/dn170477.aspx and https://code.msdn.microsoft.com/windowsazure/Service-Bus-HTTP-Token-38f2cfc5.

I took the implementation of HmacSha256 from HMACSHA256 on Windows Phone 8.1?

private static void SendSBMessage(string message)
{
    try
    {
        string baseUri = "https://<your-namespace>.servicebus.windows.net";
        using (System.Net.Http.HttpClient client = new System.Net.Http.HttpClient())
        {
            client.BaseAddress = new Uri(baseUri);
            client.DefaultRequestHeaders.Accept.Clear();

            string token = SASTokenHelper();
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SharedAccessSignature", token);

            string json = JsonConvert.SerializeObject(message);
            HttpContent content = new StringContent(json, Encoding.UTF8);
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            string path = "/<queue-or-topic-name>/messages"; 

            var response = client.PostAsync(path, content).Result;
            if (response.IsSuccessStatusCode)
            {
                // Do something
            }
            else
            {
                // Do something else
            }
        }
    }
    catch(Exception ex)
    {
        // Handle issue
    }
}

private static string SASTokenHelper()
{
    string keyName = "RootManageSharedAccessKey";
    string key = "<your-secret-key>";
    string uri = "<your-namespace>.servicebus.windows.net";

    int expiry = (int)DateTime.UtcNow.AddMinutes(20).Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
    string stringToSign = WebUtility.UrlEncode(uri) + "\n" + expiry.ToString();
    string signature = HmacSha256(key, stringToSign);
    string token = String.Format("sr={0}&sig={1}&se={2}&skn={3}", WebUtility.UrlEncode(uri), WebUtility.UrlEncode(signature), expiry, keyName);

    return token;
}

// Because Windows.Security.Cryptography.Core.MacAlgorithmNames.HmacSha256 doesn't
// exist in WP8.1 context we need to do another implementation
public static string HmacSha256(string key, string value)
{
    var keyStrm = CryptographicBuffer.ConvertStringToBinary(key, BinaryStringEncoding.Utf8);
    var valueStrm = CryptographicBuffer.ConvertStringToBinary(value, BinaryStringEncoding.Utf8);

    var objMacProv = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha256);
    var hash = objMacProv.CreateHash(keyStrm);
    hash.Append(valueStrm);

    return CryptographicBuffer.EncodeToBase64String(hash.GetValueAndReset());
}