Page 38 - MSDN Magazine, May 2019
P. 38
Great! Now you’re all wired up. In the PullRequestForm con- structor, you’re going to inject the IHttpClientFactory you just wired up and assign it to a local variable, as shown in the code here:
private static HttpClient _httpClient;
public PullRequestForm(IHttpClientFactory httpClientFactory) {
InitializeComponent();
_httpClient = httpClientFactory.CreateClient(“github”); }
You now have an HttpClient you can use to make calls out to GitHub to retrieve pull requests, issues and the like. This also makes the next few steps a little tricky. The calls from the HttpClient are going to be async requests, and if you’ve been using WinForms, you know what’s coming. You’re going to have to handle the threading, and send dispatch updates to the UI thread.
In order to kick off retrieving all of the pull requests, let’s add a button to the view. This way you can, in the future, add more repos or more groups of repos to check. Using the designer that you wired up, drag the button on to the form and rename the text to read “Microsoft.” While you’re at it, give your button a more meaningful name like RetrieveData_Button. You’ll need to tie in to the RetrieveData_ Button_Click event, but you need it to be async, using this code:
private async void RetrieveData_Button_Click(object sender, EventArgs e) {
}
Here’s where you’ll want to call a method that retrieves open GitHub pull requests. But first, because you’re dealing with async calls now, youmustwireuptheSynchronizationContext.Youdothisbyadding a new property and updating the constructor with the following code:
private static HttpClient _httpClient;
private readonly SynchronizationContext synchronizationContext;
public PullRequestForm(IHttpClientFactory httpClientFactory) {
InitializeComponent();
synchronizationContext = SynchronizationContext.Current; _httpClient = httpClientFactory.CreateClient(“github”);
}
Next, create a model named PullRequestData, so you can easily deserialize your request. Here’s the code for that:
public class PullRequestData {
public string Url { get; set; }
public string Title { get; set; } }
Finally, create a method named GetPullRequestData. In this method, you’re going to make your request to the GitHub API and retrieve all the open pull requests. You’ll be deserializing a JSON
Figure 2 The ConfigureServices Method
request, so add the latest version of Newtonsoft.Json package to the project. Here’s the code:
private async Task<List<PullRequestData>> GetPullRequestData() {
var gitHubResponse =
await _httpClient.GetStringAsync( $”repos/dotnet/winforms/pulls?state=open”);
var gitHubData = JsonConvert.DeserializeObject<List<PullRequestData>>(gitHubResponse);
return gitHubData; }
This can now be invoked from the RetrieveData_Button_Click method. Once you have a list of the data you want, create a list of labels for each Title so you can display it on the form. After you have the list of labels, you can add them to the UI in the UpdateUI method. Figure 3 shows this.
Your UpdateUI method will then use the synchronizationCon- text to update the UI, like so:
public void UpdateUI(List<Label> labels) {
synchronizationContext.Post(new SendOrPostCallback(o => {
foreach (var label in labels) {
Controls.Add(label);
}
}), labels); }
If you run the application and click the Microsoft button, the UI will be updated with the titles of all the open pull requests from the dotnet/winforms repository on GitHub.
Now it’s your turn. To truly make this a centralized pull request hub, as the title of this article promises, let’s update this example to read from multiple GitHub repositories. These repositories don’t need to be from the Microsoft team, though it’s fun to watch their progress. For example, microservices architectures are very common, and in them you may have numerous repositories that make up your system as a whole. Given that it’s usually a good idea to not leave branches and pull requests out there, unmerged, for too long, a tool like this could boost your insight into open pull requests and improve the quality of your entire system.
You could certainly set up a Web app, but then you’d have to worry about deployments, where it’s going to run, authentication
Figure 3 Invoking from RetrieveData_Button_Click
private async void RetrieveData_Button_Click(object sender, EventArgs e) {
var pullRequestData = await GetPullRequestData();
await Task.Run(() => {
var labelsToAdd = new List<Label>();
var verticalSpaceBetweenLabels = 20;
var horizontalSpaceFromLeft = 10;
for (int i = 0; i < pullRequestData.Count; i++) {
Label label = new Label();
label.Text = pullRequestData[i].Title; label.Left = horizontalSpaceFromLeft; label.Size = new Size(100, 10); label.AutoSize = true;
label.Top = (i * verticalSpaceBetweenLabels); labelsToAdd.Add(label);
}
UpdateUI(labelsToAdd); });
}
private static void ConfigureServices() {
var services = new ServiceCollection(); services.AddHttpClient(); services.AddHttpClient(“github”, c => {
c.BaseAddress = new Uri(“https://api.github.com/”); c.DefaultRequestHeaders.Add(“Accept”, “application/vnd.github.v3+json”); c.DefaultRequestHeaders.Add(“User-Agent”, “HttpClientFactory-Sample”); c.DefaultRequestHeaders.Add(“Accept”, “application/json”); ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
});
services.AddSingleton<PullRequestForm>(); ServiceProvider = services.BuildServiceProvider();
}
32 msdn magazine
WinForms