C# HTTP - Flurl ComboBox - Download Data and Populate ComboBox

May 16, 2018 Oclemy C# HTTP, C# Flurl, C# ComboBox 8 minutes, 41 seconds

In this tutorial we want to see how to download data from online and populate our C# Windows Forms ComboBox.

We are basically making a HTTP GET request in the background thread via Async Await. We then use the SynchronizationContext to send results to our main thread.

This ensures our application remians smooth and responsive,

To make our HTTP Requests we use Flurl, which is a .NET HTTP library that is fast and easy to work with.

Here's the sample JSON data we are using https://jsonplaceholder.typicode.com/users.

We'll install it via the Nuget Package Manager.

We are Building a Vibrant YouTube Community

We have a fast rising YouTube Channel of friends. So far we've accumulated almost 3 million agreggate views and more than 10,000 subscribers as of the time of writing this. Here's the Channel: ProgrammingWizards TV.

Please go ahead subscribe(free obviously) as well. If you have a question or a comment you can post there instead of in this site.People are suggesting us tutorials to do there so you can too.

Here this tutorial in video version:

What is HTTP?

HTTP stands for Hyper Text Transfer Protocol.

It is an application protocol for distributed, collaborative, and hypermedia information systems.

HTTP is used by the World Wide Web and as a protocol it defines how messages are formatted and transmitted, and what actions Web servers and browsers should take in response to various commands.

C# HTTP

Like any modern, powerful and general purpose language, C# allows us to work with Hyper Text Transfer Protocol.

This it does by providing us abstractions through the HttpClient,a class defined in the System.Net.Http namespace, and that acts as a base class for sending HTTP requests and receiving HTTP responses from a resource identified by a URI.

Introduction To Flurl

Even though C# provides us with a HttpClient class, there are third party libraries that have been developed to make it as easy to incorporate HTTP capabilities in your app as 1,2,3.

One of the most popular such library in C# is Flurl.

Flurl is a modern, fluent, asynchronous, testable, portable, buzzword-laden URL builder and HTTP client library.

It was built by Todd Menier and is very easy to use given it's fluent API.

It's also well documented and maintained.

Flurl Hello World

Here's an example of Flurl, pretty complex HTTP POST example can easily be used as a hello world, in a single line(expression):

var result = await "https://api.mysite.com"
    .AppendPathSegment("person")
    .SetQueryParams(new { a = 1, b = 2 })
    .WithOAuthBearerToken("my_oauth_token")
    .PostJsonAsync(new { first_name = "Frank", last_name = "Underwood" })
    .ReceiveJson<T>();

In that example we are making a POST request with authentication and receiving JSON response, and we do it in fact in the background thread.

We've easily done that in a single expression of code, maybe it can't get easier than that.

Flurl Installation

As a third party library we need to install Flurl. That is however easy and we can work obtain it from Nuget, the .NET package manager.

You install Flurl via the following command:

Install-Package Flurl.Http

What are Async and Await in C#?

Well just keywords. However keywords that allows us do something that has always been complex in software development industry a s whole, achieving seamless asynchrony.

Async and Await keywords allow us write asynchronous programs. They are abstractions that allow us call a function asynchronously.

When we talk about Asynchronous Programming we refer to a mechanism of achieving parallel programming in which a unit of work runs separately from the main application thread and notifies the calling thread of its completion, failure or progress.

Asynchronous Programming is important because it allows you avoid performance bottlenecks and enhance the overall responsiveness of your application.

Traditionally, Asynchronous Programming has always been complicated. These complications then have always been leading to applications that are really difficult to debug hence maintain.

So Microsoft Engineers through C# 5 and .NET 4.5,.NET Core and Windows Runtime simplified this with the introduction of these two keywords.

With Async and Await, you can use resources in the .NET Framework, .NET Core, or the Windows Runtime to create an asynchronous method almost as easily as you create a synchronous method.

Using Async and Await

You can either use the Async and Await together or use Async on its own. If you use it on its own then the method you've used it on will be run synchronously as opposed to asynchronously.

You use the Async keyword in a method, as a modifier:

async Task<string> download() {...}

. As you can see we've followed the Async keyword with a Task<string>. We can use Task or Task<T>. The first one returns void. The second one returns a generic Task of type T. T in this case represents a data type like string, int,double etc. The Task basically represents the task or work that we are doing. In the above case our Task will have string as the final data, on its completion.

Then we come and do our work. Say we want to download data via HttpClient:

HttpClient client = new HttpClient(); 

Then we can define the statement that actually perform the download asynchronously:

Task<string> downloadTask = client.GetStringAsync("http://camposha.info");

Meanwhile we can continue doing some other work that do not rely on the download:

doSomeWork();

Then to perform the actual download:

string downloadedData = await downloadTask; 

The await will download the data and return a string result.

We can then return that data:

return downloadedData;

Let's now mover to a full example, but this time with Flurl as opposed to HttpClient.

Program.cs

Explanations

Let's move step by step.

Add Imports

These include Flurl.Http and System.Threading.Tasks:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Flurl.Http;

Create a POCO

A Plain Old CLR Object class. A data object to represent a single user.

    class User
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
    }

Create Main Class

We call that class Program. It's main because it has our main method:

    class Program
    {..}

Define a SynchronizationContext

SynchronizationContext is a class that will allow us to propagate asynchronous messages to synchronization context.

This is important because we aim to populate a ListBox which is a GUI control that runs on main thread, yet our download is taking place in a background thread.

        private static SynchronizationContext synchronizationContext;

Create That Async Method

To create a method that will run asynchronously, we said the first step is to use the async modifier:

        private static async void downloadJSONData(){..}

Create a task and Run it Asynchronously

We'll use lambda expression to create our Task, then use the await keyword to make sure it's asynchronous and the Run method to actually run it:

                await Task.Run(async () =>
                {..}

Download JSON data Asynchronously into a List

Remember the GetJSONAsync() is an async method that returns a JSON data and using Newtonsoft JSON maps that JSON data into a generic list of objects, in this case user objects.

                    List<User> users = await "https://jsonplaceholder.typicode.com/users".GetJsonAsync<List<User>>();

Populate our ComboBox with data From Background thread

The ComboBox, like all GUI elements runs on the main thread. So how do we populate it with data from background thread?

Well remember our synchronizationContext, it allows us propagate those asynchronous data to our synchronization context, which in this case is in the main thread.

So we loop through our data, posting them so that they are added to ComboBox via the Add() method.

                    foreach (User user in users)
                    {
                        synchronizationContext.Post(new SendOrPostCallback(value =>
                        {
                            //UPDATE ComboBox
                            myComboBox.Items.Add(value as string);

                        }), user.Name);
                    }

Create the ComboBox

We do this programmatically. This combobox will render our JSON data downloaded from the web:

        private static readonly ComboBox myComboBox = new ComboBox
        {
            Location = new Point(30, 70),
            Size = new Size(500, 400),
            Font = new Font(FontFamily.GenericSansSerif, 15),
            DropDownStyle = ComboBoxStyle.DropDownList
        };

Create the Windows Form

The Windows Form that will host our ComboBox;

        private static void createForm()
        {
            synchronizationContext = SynchronizationContext.Current;

            Form myForm = new Form
            {
                Text = "C# HTTP : Flurl - Download Data and Fill ComboBox",
                ClientSize = new Size(564, 520),
                BackColor = Color.MediumSeaGreen
            };
            myComboBox.SelectedIndexChanged += myComboBox_SelectedIndexChanged;
            myForm.Controls.Add(myComboBox);
            Application.EnableVisualStyles();
            Application.Run(myForm);
        }

Show Selected ComboBox Item in MessageBox

If the user clicks one of the items then we show it in a messagebox:

        private static void myComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                MessageBox.Show(myComboBox.SelectedItem.ToString());
            }
            catch (ArgumentOutOfRangeException argumentOutOfRangeException)
            {
                MessageBox.Show(argumentOutOfRangeException.Message);
            }
        }

Our main method

First we create the Form, then download the data. The main method is the entry point to C# application:

        public static void Main()
       {
           downloadJSONData();
           createForm();
        }

Here's the full source code, just copy paste it into an empty C# Console application since we don't use any designer. Then install Flurl as we discussed.

Full Code

Our Program.cscode:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Flurl.Http;

namespace ComboBoxJSON
{
    /*
     * User class. A POCO class.
     */
    class User
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
    }
    class Program
    {
        //will allow us propagate asynchronous messages to  synchronization context
        private static SynchronizationContext synchronizationContext;

        /*
         * Download JSON data
         */
        private static async void downloadJSONData()
        {
            try
            {
                //PERFORM IN BACKGROUND
                await Task.Run(async () =>
                {
                    List<User> users = await "https://jsonplaceholder.typicode.com/users".GetJsonAsync<List<User>>();
                    foreach (User user in users)
                    {
                        synchronizationContext.Post(new SendOrPostCallback(value =>
                        {
                            //UPDATE ComboBox
                            myComboBox.Items.Add(value as string);

                        }), user.Name);
                    }
                });
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }
        private static readonly ComboBox myComboBox = new ComboBox
        {
            Location = new Point(30, 70),
            Size = new Size(500, 400),
            Font = new Font(FontFamily.GenericSansSerif, 15),
            DropDownStyle = ComboBoxStyle.DropDownList
        };

        /*
     * Create a Form, Set its properties and run the application.
     */
        private static void createForm()
        {
            synchronizationContext = SynchronizationContext.Current;

            Form myForm = new Form
            {
                Text = "C# HTTP : Flurl - Download Data and Fill ComboBox",
                ClientSize = new Size(564, 520),
                BackColor = Color.MediumSeaGreen
            };
            myComboBox.SelectedIndexChanged += myComboBox_SelectedIndexChanged;
            myForm.Controls.Add(myComboBox);
            Application.EnableVisualStyles();
            Application.Run(myForm);
        }
        /*
         * ComboBox SelectedIndexChanged event handler. We display a messagebox when item is selected.
         */
        private static void myComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                MessageBox.Show(myComboBox.SelectedItem.ToString());
            }
            catch (ArgumentOutOfRangeException argumentOutOfRangeException)
            {
                MessageBox.Show(argumentOutOfRangeException.Message);
            }
        }
        /*
        * Main method
        */
        public static void Main()
       {
           downloadJSONData();
           createForm();
        }
    }
}

Result

C# HTTP Flurl - Download JSON Data and Populate ComboBox

C# HTTP Flurl - Download JSON Data and Populate ComboBox

Best Regards.

Comments