问题
How is brokered messaging via Azure Service Bus done from a Xamarin Forms PCL...is there an SDK, library or plugin? If there is a way to hand roll a brokered message, I suppose it could be accomplished with an HttpClient & the REST API ...
回答1:
I finally have a working method for posting a message to an Azure Service Bus Queue from a Xamarin PCL! The way to do this is via an HttpClient.
Gotchas that made the solution elusive:
The nuget package for Microsoft.ServiceBus.Messaging will happily install, but has no exposure to the portable class.
WebClient examples abound, but there is no webclient available in the PCL!
- PCL has no native crypto for HMACSHA256 for Shared Access Signature tokens. Get the PCLCrypto package from nuget.
- Some documentation says request headers of Content-Type : application/atom+xml;type=entry;charset=utf-8, and BrokerProerties are required. Ain't so!
The path to post to is: BaseServiceBusAddress + queue + "/messages"
public const string ServiceBusNamespace = [YOUR SERVICEBUS NAMESPACE]; public const string BaseServiceBusAddress = "https://" + ServiceBusNamespace + ".servicebus.windows.net/"; /// <summary> /// The get shared access signature token. /// </summary> /// <param name="sasKeyName"> /// The shared access signature key name. /// </param> /// <param name="sasKeyValue"> /// The shared access signature key value. /// </param> /// <returns> /// The <see cref="string"/>. /// </returns> 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; } /// <summary> /// Posts an order data transfer object to queue. /// </summary> /// <param name="orderDto"> /// The order data transfer object. /// </param> /// <param name="serviceBusNamespace"> /// The service bus namespace. /// </param> /// <param name="sasKeyName"> /// The shared access signature key name. /// </param> /// <param name="sasKey"> /// The shared access signature key. /// </param> /// <param name="queue"> /// The queue. /// </param> /// <returns> /// The <see cref="Task"/>. /// </returns> 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); } } /// <summary> /// Gets the expiry for a shared access signature token /// </summary> /// <returns> /// The <see cref="string" /> expiry. /// </returns> private static string GetExpiry() { var sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1); return Convert.ToString((int)sinceEpoch.TotalSeconds + 3600); }
}
来源:https://stackoverflow.com/questions/39753431/azure-servicebus-from-xamarin-forms-pcl