Finally, I have a working method for sending a message to the Azure Service Bus queue from the Xamarin PCL! The way to do this is through the HttpClient.
Gotchas who made the decision elusive:
The nuget package for Microsoft.ServiceBus.Messaging will happily install, but is not subject to, the portable class.
WebClient examples abound, but there is no web client available in PCL!
- PCL HMACSHA256
. PCLCrypto nuget.
- Content-Type: application/atom + xml; type = entry; charset = utf-8 BrokerProerties. !
: BaseServiceBusAddress + queue + "/messages"
public const string ServiceBusNamespace = [YOUR SERVICEBUS NAMESPACE];
public const string BaseServiceBusAddress = "https://" + ServiceBusNamespace + ".servicebus.windows.net/";
public static string GetSasToken(string sasKeyName, string sasKeyValue)
{
var expiry = GetExpiry();
var stringToSign = WebUtility.UrlEncode(BaseServiceBusAddress ) + "\n" + expiry;
var algorithm = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm(MacAlgorithm.HmacSha256);
var hasher = algorithm.CreateHash(Encoding.UTF8.GetBytes(sasKeyValue));
hasher.Append(Encoding.UTF8.GetBytes(stringToSign));
var mac = hasher.GetValueAndReset();
var signature = Convert.ToBase64String(mac);
var sasToken = string.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}", WebUtility.UrlEncode(baseAddress), WebUtility.UrlEncode(signature), expiry, sasKeyName);
return sasToken;
}
public static async Task<HttpResponseMessage> PostOrderDtoToQueue(OrderDto orderDto, string serviceBusNamespace, string sasKeyName, string sasKey, string queue)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(BaseServiceBusAddress);
client.DefaultRequestHeaders.Accept.Clear();
var token = GetSasToken(sasKeyName, sasKey);
client.DefaultRequestHeaders.Add("Authorization", token);
HttpContent content = new StringContent(JsonConvert.SerializeObject(orderDto), Encoding.UTF8);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var path = BaseServiceBusAddress + queue + "/messages";
return await client.PostAsync(path, content);
}
}
private static string GetExpiry()
{
var sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
return Convert.ToString((int)sinceEpoch.TotalSeconds + 3600);
}
}