かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

UWPでAzureのイベントハブにデータを突っ込む

抱かれたい男No1様にとてもお世話になりました。

Windows 10 IoT Core(UWP)でSASトークンを生成buchizo.wordpress.com

ServiceBusの名前空間をokazukihub-nsで作成して、イベントハブ名をokazukihubで作成して、送信の権限を持った口をInputという名前で作りました。ここに、データを突っ込むコードは以下のようになりました。

private async void button_Click(object sender, RoutedEventArgs e)
{
    var client = new HttpClient();
    var content = new ObjectContent<DeviceInfo>(new DeviceInfo
        {
            Id = 0,
            Value = 100,
        },
        new JsonMediaTypeFormatter());

    var sas = this.CreateToken("https://okazukihub-ns.servicebus.windows.net/okazukihub/messages", "Input", "p6U8m6dqSEsCb+3McnCOwsb8L7mcIm0tWmhVIL0u8vg=");
    client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", sas);
    content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/atom+xml")
    {
        CharSet = "utf-8",
    };
    content.Headers.ContentType.Parameters.Add(new System.Net.Http.Headers.NameValueHeaderValue("type", "entry"));
    var result = await client.PostAsync("https://okazukihub-ns.servicebus.windows.net/okazukihub/messages", content);
}

private string CreateToken(string resourceUri, string keyName, string key)
{
    TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
    var expiry = Convert.ToString((int)sinceEpoch.TotalSeconds + 3600); //EXPIRES in 1h 
    string stringToSign = WebUtility.UrlEncode(resourceUri) + "\n" + expiry;
    var signature = ComputeSignature(stringToSign, key);
    var sasToken = String.Format(CultureInfo.InvariantCulture,
        "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
        WebUtility.UrlEncode(resourceUri), WebUtility.UrlEncode(signature), expiry, keyName);

    return sasToken;
}

public string ComputeSignature(string content, string key, BinaryStringEncoding encoding = BinaryStringEncoding.Utf8)
{
    var algorithmProvider = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha256);
    var contentBuffer = CryptographicBuffer.ConvertStringToBinary(content, encoding);
    var keyBuffer = CryptographicBuffer.ConvertStringToBinary(key, encoding);
    var signatureKey = algorithmProvider.CreateKey(keyBuffer);
    var signedBuffer = CryptographicEngine.Sign(signatureKey, contentBuffer);
    return CryptographicBuffer.EncodeToBase64String(signedBuffer);
}

下の2メソッドは抱かれたい男No1様のページのコードになります。ボタンクリックで各種データを作ってサーバーに投げています。DeviceInfoクラスは、自作のIdとValueだけもったクラスになります。

ちょっとはまったのがAuthorizationヘッダーの設定がなかなかうまくいかなかった点です。HttpContent(ObjectContent)のHeadersに追加するとうまく追加できなくて、HttpCLientのDefaultRequestHeadersに追加するとうまくいきました。謎い。

client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", sas);

これで次のステップに進める…。