Page 11 - MSDN Magazine, March 2018
P. 11
HttpJsonContent requires that I send my JSON in the format of a Windows.Data.Json.JsonValue. So you’ll see where I’ve taken those steps. Alternatively, I could explicitly set the header content on the HttpRequest and then post as a String using the StringContent method,asdemonstratedatbit.ly/2BBjFNE.
I encapsulated all of the logic for interacting with the Azure Functions into a class called CloudService.cs.
Once I figured out the pattern for using the UWP request meth ods and how to create JsonValue objects, I created a method called CallCookieBingeFunctionAsync that encapsulates most of that logic. The method takes two parameters: the name of the Azure Function to call and a JsonValue object. I also created an overload of this method that doesn’t require the JsonValue object parameter.
Here’s the signature for that method:
private async Task<T> CallCookieBingeFunctionAsync<T>(string apiMethod, JsonValue jsonValue)
As there are three different Azure Functions I need to call, let’s start with the simplest—GetTop5GlobalUserScores. This func tion doesn’t take any parameters or other content and returns results as JSON.
TheGetTopGlobalScoresmethodintheCloudServiceclasscalls my new CallCookieBingeFunctionAsync method, passing in the name of the function, and then returns the results contained in the function’s response.
public async Task<List<ScoreViewModel>> GetTopGlobalScores() {
var results= await CallCookieBingeFunctionAsync<List<ScoreViewModel>> ("GetTop5GlobalUserScores");
return results; }
Notice that I’m not passing a second parameter to the method. That means the overload I created that doesn’t require a JsonValue will be called:
private async Task<T> CallCookieBingeFunctionAsync<T>(string apiMethod) {
return await CallCookieBingeFunctionAsync<T>(apiMethod, null); }
This in turn calls the other version of the method and simply passes a null where the JsonValue is expected. Here’s the full listing for the CallCookieBingeFunctionAsync method (which definitely needs an explanation):
private async Task<T> CallCookieBingeFunctionAsync<T>(string apiMethod, JsonValue jsonValue)
{
the helper class, HttpJsonContent, for this step. I copied this class from the JSON section of the official Windows Universal samples (bit.ly/2ry7mBP), which provided me with a means to transform a JsonValue object into an object that implements IHttpCon tent.(YoucanseethefullclassthatIcopiedinthedownload.)Ifno JsonValue is passed into the method, as is the case for the GetTop 5GlobalUserScores function, the httpContent variable will be null.
The next step in the method defines a CancellationTokenSource in the variable cts. While I won’t be handling a cancellation in my code, I wanted to be sure you were aware of this pattern so I’ve included the token nevertheless.
With all of my pieces now constructed—the URI, the httpContent and the CancellationTokenSource, I can finally make the call to my Azure Function using the HttpClient.PostAsync method. The response comes back as JSON. My code reads that and uses JSON.Net’s JsonConvert method to deserialize the response into whatever object was specified by the calling method.
With all of my pieces constructed now—the URI, the httpContent and the CancellationTokenSource, I can finally make the call to my Azure function using the HttpClient.PostAsync method.
If you look back at the code for GetTopGlobalScores, you’ll see I specified that the results should be a List<ScoreViewModel>. ScoreViewModel is a type I created to match the schema of the score data returned by two of the Azure Functions. The class also has some additional properties that format the data based on how I want to display it in the UWP app. Given that the Score ViewModel class is a long listing, I’ll let you inspect its code in the download sample.
Calling an Azure Function That Takes a Parameter
There are still two more Azure Functions to explore. Let’s look now at the other one that returns score data. This function needs the UserId passed in, whereas the previous function took no input. But in this case, I’m still not required to build up the HttpJsonContent because, if you recall the function as it was described in last month’s article, it expects the UserId value to be passed in as part of the URI. The simple example from last month’s article just uses the string 54321 as the UserId in this URI: https://cookiebinge.azurewebsites.net/api/GetUserScores/54321. With the addition of the identity management feature to the app, the UserId will now be a GUID.
March 2018 7
var httpClient = new HttpClient();
var uri = new Uri("https://cookiebinge.azurewebsites.net/api/" + apiMethod); var httpContent = jsonValue != null ? new HttpJsonContent(jsonValue): null; var cts = new CancellationTokenSource();
HttpResponseMessage response = await httpClient.PostAsync(uri,
httpContent).AsTask(cts.Token);
string body = await response.Content.ReadAsStringAsync();
T deserializedBody = JsonConvert.DeserializeObject<T>(body); return deserializedBody;
In the first step, the method creates an instance of Windows.Web.Http.HttpClient. Then the method constructs the information needed to make the request from the HttpClient, beginning with the Web address of the function to be called. All of my functions will begin with https://cookiebinge.azurewebsites.net/api/, so I’ve hardcoded that value into the method and then append the function name passed into the method.
Next, I have to define the headers and any content passed along to the function. As I explained earlier, I’ve chosen to use msdnmagazine.com
}