Manually connect and send data to an Azure Event Hub
Update 04.02.2017: As theMicrosoft.Azure.EventHubs NuGet package since two days finally support every .NET platform, this post go obsolete.
Azure Event Hubs provide a neat way to collect loads of data that is pushed against them and holds it until its processing. Microsoft offers an SDK to work with Event Hubs for most platforms including .NET, of course. Unfortunately, the provided NuGet package does not work on all .NET platforms, so when targeting UWP for example, you have to implement the Event Hub connection by yourself, which can be a little bit tricky. Here is how to manually connect and send data to an Azure Event Hub.
Get the connection information
Once the Event Hub has been created, open the Service Bus section in the Azure Portal and navigate to your Event Hub. Select the Configure tab and scroll down to the Shared access policiessection. Make sure, you created a policy that has the permission to send data to the Event Hub and note its Name and Primary Key. You need both later.
Besides, we need the base address of the Event Hub, that we can find at the Dashboard tab. The base address is everything beforethe first slash. In my case it’shttps://dachautemp-ns.servicebus.windows.net
](http://pumpingco.de/content/images/2016/10/Screen-Shot-2016-10-08-at-17.05.55.png)
Establish aconnection
Now you are ready to connect. For better separation and reusability, I have created an EventHubService
class in my project. You will need the following variables:
private const string sasKeyName = "{SAS Key Name}"; // Example: DachauTempSender private const string sasKeyValue = "{SAS Key Value}"; // Example: TVez2PZTbE7raAruNgvHGQtDZ7KeqwLRLOt+mTML2Cg= private const string eventHubName = "{Azure Event Hub name}"; // Example: dachautemp private const string eventHubBaseAddress = "{Azure Event Hub base address}"; // Example: https://dachautemp-ns.servicebus.windows.net private HttpClient httpClient = new HttpClient();
With these you are able to authenticate at the REST endpoint of your Event Hub. You need to authenticate to send data and identify yourself so make sure, that you call the authentication process at least once. To authenticate, I created the following method that you can simply copy. It defines an expiry for the access token, which is mandatory and renders the Primary Key to a SHA256 hash that gets the expiry date appended. With this hash we can generate a token with all the other values. This token will be set as the Authorization
header of the HttpClient
and will be used for the next requests.
public void Authenticate() { TimeSpan fromEpochStart = DateTime.UtcNow - new DateTime(1970, 1, 1); string expiry = Convert.ToString((int)fromEpochStart.TotalSeconds + 86400); // 86400s = 24h string stringToSign = WebUtility.UrlEncode(eventHubBaseAddress) + "\n" + expiry; // Create hash MacAlgorithmProvider provider = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha256); var hash = provider.CreateHash(CryptographicBuffer.ConvertStringToBinary(sasKeyValue, BinaryStringEncoding.Utf8)); hash.Append(CryptographicBuffer.ConvertStringToBinary(stringToSign, BinaryStringEncoding.Utf8)); // Generate token var signature = CryptographicBuffer.EncodeToBase64String(hash.GetValueAndReset()); string token = String.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}", WebUtility.UrlEncode(eventHubBaseAddress), WebUtility.UrlEncode(signature), expiry, sasKeyName); // Set HTTP Access token httpClient.DefaultRequestHeaders.Clear(); httpClient.DefaultRequestHeaders.ExpectContinue = false; httpClient.DefaultRequestHeaders.Authorization = AuthenticationHeaderValue.Parse(token); }
Send data to the Event Hub
As soon as you are authenticated, data can be sent. For this, I recommend writing another simple method that simply transforms an object into JSON and sends it to the Event Hub. For the JSON transformation, I used the popular JSON.NET NuGet package. Once the content is in the right format, you can create aStringContent
out of it and send it to the /messages endpoint of your Event Hub. That’s it.
Sometimes, it might happen, that you get a 401 error (unauthorized) as response. If this happens, your access token might be expired. That’s why I simply regenerate it and try to send the request again when this happens, as you can see below.
public async Task SendEventAsync(object datapoint) { // Convert datapoint to JSON var json = JsonConvert.SerializeObject(datapoint); var content = new StringContent(json); // Send event var response = await httpClient.PostAsync($"{eventHubBaseAddress}/{eventHubName}/messages", content); if (response.StatusCode == HttpStatusCode.Unauthorized) { // Maybe token expired available. Renew and try again RefreshAccessToken(); // Try again content = new StringContent(json); response = await httpClient.PostAsync($"{eventHubBaseAddress}/{eventHubName}/messages", content); } // Check if everything went fine if (!response.IsSuccessStatusCode) throw new UnauthorizedAccessException("Could not connect to Azure Event Hub. Access denied."); }
You can find the fullcode at GitHub. Hope that helps!