来自Xamarin Forms PCL的Azure ServiceBus

时间:2016-09-28 16:53:01

标签: xamarin.forms azureservicebus

如何通过Azure Service Bus从Xamarin Forms PCL完成代理消息传递...是否有SDK,库或插件?如果有办法手工推送代理消息,我想可以用HttpClient& REST API ......

1 个答案:

答案 0 :(得分:5)

我终于有了一种从Xamarin PCL向Azure Service Bus Queue发布消息的工作方法!这样做的方法是通过HttpClient。

让解决方案变得难以捉摸的陷阱:

  • Microsoft.ServiceBus.Messaging的nuget包将很乐意安装,但不会暴露于便携式类。

  • WebClient示例比比皆是,但是没有可用的webclient PCL!

  • PCL没有用于共享访问签名的HMACSHA256的本机加密 令牌。从nuget获取PCLCrypto包。
  • 有些文档说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/";
    
    /// <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);
    }
    

    }