One can say Mobile Applications today cannot exist without a connected backend. Unless, you are building a calculator like app there’s a need for every app to connect to server to retrieve user’s data. In this post, I will show how we can use HttpClient
module to make REST API calls in the Xamarin.Forms
application.
In this post, I will be creating a simple ToDo app that:
- Adds a new item to server data
- Fetches existing items from server
- Update an existing item
- Delete an item
The sample can be opened in Xamarin Studio or Visual Studio. For simplicity, I have used Xamarin Studio here. Feel free to use the IDE of your choice, when you give it a try.
Step 1 : Create a Xamarin.Forms application
Open Xamarin Studio, File -> New Solution -> Under Multiplatform App -> Xamarin.Forms -> Forms App
Follow the steps and create a new project. Just to make sure, everything works fine. Build and run the app in iOS/Android. The finished project’s folder structure would look like below :
Step 2 : Write REST API Invocation code in the PCL project – HttpClientDemo
-
Install the package
Microsoft.Net.Http
from Nuget -> For making REST API calls -
Install the package
Newtonsoft.Json
from Nuget -> For Serialization/Deserialization of objects -
Create a new file
TodoItem.cs
with the below lines of code
using System; namespace HttpClientDemo.Models { public class TodoItem { public string Description { get; set; } public string DueDate { get; set; } public bool isDone { get; set; } }}
- Add a new DataService class that is responsible for making API calls
HttpGet Request
HttpClient
class exposes a method called GetStringAsync
to make the get requests. Lets make use of them and invoke our API. The method to invoke get requests will look like below :
/// <summary>/// Gets the todo items async./// </summary>/// <returns>The todo items async.</returns>public async Task<List<TodoItem>> GetTodoItemsAsync() { var response = await client.GetStringAsync("http://localhost:5000/api/todo/items"); var todoItems = JsonConvert.DeserializeObject<List<TodoItem>>(response);return todoItems; }
The async
and await
operators are very handy in making asynchronous calls. Similarly the other Http operations like Post/Put/Delete
can be invoked using the below methods
HttpPost Request
Similar to GetStringAsync
method, we also have PostAsync
method which we can leverage for making Post requests. Sample code below :
/// <summary>/// Adds the todo item async./// </summary>/// <returns>The todo item async.</returns>/// <param name="itemToAdd">Item to add.</param>public async Task<int> AddTodoItemAsync(TodoItem itemToAdd) { var data = JsonConvert.SerializeObject(itemToAdd); var content = new StringContent(data, Encoding.UTF8, "application/json"); var response = await client.PostAsync("http://localhost:5000/api/todo/item", content); var result = JsonConvert.DeserializeObject<int>(response.Content.ReadAsStringAsync().Result); return result;}
HttpPut Request
When we have to modify any existing item, we should be using HttpPut
method. Invoking a put method is as easy as using PutAsync
method from HttpClient library. Sample code below :
/// <summary>/// Updates the todo item async./// </summary>/// <returns>The todo item async.</returns>/// <param name="itemIndex">Item index.</param>/// <param name="itemToUpdate">Item to update.</param>public async Task<int> UpdateTodoItemAsync(int itemIndex, TodoItem itemToUpdate) { var data = JsonConvert.SerializeObject(itemToUpdate); var content = new StringContent(data, Encoding.UTF8, "application/json"); var response = await client.PutAsync(string.Concat("http://localhost:5000/api/todo/", itemIndex), content); return JsonConvert.DeserializeObject<int>(response.Content.ReadAsStringAsync().Result); }
HttpDelete Request
In our sample, to delete the unwanted To-do items, we can make HttpDelete
request to the API. Sample code to do that is given below:
/// <summary>/// Deletes the todo item async./// </summary>/// <returns>The todo item async.</returns>/// <param name="itemIndex">Item index.</param>public async Task DeleteTodoItemAsync(int itemIndex) { await client.DeleteAsync(string.Concat("http://localhost:5000/api/todo/", itemIndex));}
Step 3 : Consume the above changes in the HttpClientDemoPage.xaml.cs
file
Add a method that makes the call to the DataService to load data
async void RefreshData() { items = await dataService.GetTodoItemsAsync(); todoList.ItemsSource = items.OrderBy(item => item.isDone).ThenBy(item => item.DueDate).ToList();}
Invoke this RefreshData
function from the Constructor
to load the data from service on app launch.
public HttpClientDemoPage() { InitializeComponent(); dataService = new DataService(); RefreshData(); }
Similarly, we can make appropriate calls to the Add/Update/Delete methods depending on the UI events we wish.
- Code to add a new todo Item
async void AddButton_Clicked(object sender, System.EventArgs e) { TodoItem newItem = new TodoItem { Description = txtTodoItem.Text.Trim(), DueDate = dpDueDate.Date.ToString("d") }; await dataService.AddTodoItemAsync(newItem); RefreshData();}
- Updating a task as done
public async void OnDone(object sender, EventArgs e) { var mi = ((MenuItem)sender); TodoItem itemToUpdate = (TodoItem)mi.CommandParameter; itemToUpdate.isDone = true; int itemIndex = items.IndexOf(itemToUpdate); await dataService.UpdateTodoItemAsync(itemIndex,itemToUpdate); RefreshData();}
- Deleting the task
public async void OnDelete(object sender, EventArgs e) { var mi = ((MenuItem)sender); TodoItem itemToDelete = (TodoItem)mi.CommandParameter; int itemIndex = items.IndexOf(itemToDelete); await dataService.DeleteTodoItemAsync(itemIndex); RefreshData();}
That’s pretty much it from the code changes. The complete source code is available in Github repo.
https://github.com/svswaminathan/xamarin-forms-httpclient-sample
The repo contains code for both the Web API (built on asp.net core) and the Xamarin Forms app. The readme file contains instructions for running both the API and the App. The finished app should work as shown in the video below:
Though HttpClient
is very easy to use and does the job in most cases, to gain more advantage of the platform specific network libraries, ModernHttpClient can be used. More on that on a separate blog post soon!