Introduction

Greetings all, I trust you're all doing well during this pandemic. Stay safe.

The goal of this article is to implement REST API operations in WPF.

Following is a list that we are going to focus on for UI decoration.

Note. This is part 3 of the Rest API implementation with WPF & EF.

If your focus is only on learning REST API's integration with WPF, then you can skip this below listing. However, I highly recommend going through this list of prerequisites.

  1. Building a DataAccessLayer
  2. Building a REST API Layer
  3. Data Bindings in WPF
  4. Relay Command in WPF
  5. INotifypropertychanged in MVVM

Now that you've done that, let's move on with our objective. We are going to focus on the middle layer from the following architecture. The presentation layer of course.

Architecture

To do that, Right-click on solution => add new Project & then select WPF application.

I have divided this article into 3 subparts:

The REST API integration in C#

We need to have a class for 4 interfaces, Get, Post, Put & Delete.

Right-click on the WPF project & click on the add new class option. Then name it WebAPI

First, we are going to add the Get method.

class WebAPI
{
    /// <summary>
    /// Get employee details
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    public static Task<HttpResponseMessage> GetCall(string url)
    {
        try
        {
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            string apiUrl = API_URIs.baseURI + url;
            using (HttpClient client = new HttpClient())
            {
                client.BaseAddress = new Uri(apiUrl);
                client.Timeout = TimeSpan.FromSeconds(900);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                var response = client.GetAsync(apiUrl);
                response.Wait();
                return response;
            }
        }
        catch (Exception ex)
        {
            throw;
        }
    }
}

Second, is the Post method.

/// <summary>
/// creates a new employee
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="url"></param>
/// <param name="model"></param>
/// <returns></returns>
public static Task<HttpResponseMessage> PostCall<T>(string url, T model) where T : class
{
    try
    {
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
        string apiUrl = API_URIs.baseURI + url;
        using (HttpClient client = new HttpClient())
        {
            client.BaseAddress = new Uri(apiUrl);
            client.Timeout = TimeSpan.FromSeconds(900);
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            var response = client.PostAsJsonAsync(apiUrl, model);
            response.Wait();
            return response;
        }
    }
    catch (Exception ex)
    {
        throw;
    }
}

Third, is the Put method.

/// <summary>
/// Updates employees details
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="url"></param>
/// <param name="model"></param>
/// <returns></returns>
public static Task<HttpResponseMessage> PutCall<T>(string url, T model) where T : class
{
    try
    {
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
        string apiUrl = API_URIs.baseURI + url;
        using (HttpClient client = new HttpClient())
        {
            client.BaseAddress = new Uri(apiUrl);
            client.Timeout = TimeSpan.FromSeconds(900);
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            var response = client.PutAsJsonAsync(apiUrl, model);
            response.Wait();
            return response;
        }
    }
    catch (Exception ex)
    {
        throw;
    }
}

Finally, the Delete method.

/// <summary>
/// Delete employee's record
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static Task<HttpResponseMessage> DeleteCall(string url)
{
    try
    {
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
        string apiUrl = API_URIs.baseURI + url;
        using (HttpClient client = new HttpClient())
        {
            client.BaseAddress = new Uri(apiUrl);
            client.Timeout = TimeSpan.FromSeconds(900);
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            var response = client.DeleteAsync(apiUrl);
            response.Wait();
            return response;
        }
    }
    catch (Exception ex)
    {
        throw;
    }
}

Now that you've done that, we can move forward with the 2nd phase of this article, which is,

ViewModel

Let me give you a tour of MainWindowViewModel.

class MainWindowViewModel

using A.Utilities;
using DataAccessLayer;
using Prism.Commands;
using Prism.Mvvm;
using System.Collections.Generic;
using System.ComponentModel;
using System.Net.Http;

namespace A
{
    class MainWindowViewModel : BindableBase, INotifyPropertyChanged
    {
        #region Properties

        private List<Employee> _employees;

        public List<Employee> Employees
        {
            get { return _employees; }
            set { SetProperty(ref _employees, value); }
        }

        private Employee _selectedEmployee;

        public Employee SelectedEmployee
        {
            get { return _selectedEmployee; }
            set { SetProperty(ref _selectedEmployee, value); }
        }

        private bool _isLoadData;

        public bool IsLoadData
        {
            get { return _isLoadData; }
            set { SetProperty(ref _isLoadData, value); }
        }

        private string _responseMessage = "Welcome to REST API Tutorials";

        public string ResponseMessage
        {
            get { return _responseMessage; }
            set { SetProperty(ref _responseMessage , value); }
        }

        #region [Create Employee Properties]

        private string _firstName;

        public string FirstName
        {
            get { return _firstName; }
            set { SetProperty(ref _firstName, value); }
        }

        private string _lastName;

        public string LastName
        {
            get { return _lastName; }
            set { SetProperty(ref _lastName, value); }
        }

        private string _gender;

        public string Gender
        {
            get { return _gender; }
            set { SetProperty(ref _gender, value); }
        }

        private int _salary;

        public int Salary
        {
            get { return _salary; }
            set { SetProperty(ref _salary, value); }
        }
        #endregion

        private bool _isShowForm;

        public bool IsShowForm
        {
            get { return _isShowForm; }
            set { SetProperty(ref _isShowForm, value); }
        }

        private string _showPostMessage = "Fill the form to register an employee!";

        public string ShowPostMessage
        {
            get { return _showPostMessage; }
            set { SetProperty(ref _showPostMessage, value); }
        }
        #endregion

        #region ICommands
        public DelegateCommand GetButtonClicked { get; set; }
        public DelegateCommand ShowRegistrationForm { get; set; }
        public DelegateCommand PostButtonClick { get; set; }
        public DelegateCommand<Employee> PutButtonClicked { get; set; }
        public DelegateCommand<Employee> DeleteButtonClicked { get; set; }
        #endregion

        #region Constructor
        /// <summary>
        /// Initalize perperies & delegate commands
        /// </summary>
        public MainWindowViewModel()
        {
            GetButtonClicked = new DelegateCommand(GetEmployeeDetails);
            PutButtonClicked = new DelegateCommand<Employee>(UpdateEmployeeDetails);
            DeleteButtonClicked = new DelegateCommand<Employee>(DeleteEmployeeDetails);
            PostButtonClick = new DelegateCommand(CreateNewEmployee);
            ShowRegistrationForm = new DelegateCommand(RegisterEmployee);
        }
        #endregion

        #region CRUD
        /// <summary>
        /// Make visible Regiter user form
        /// </summary>
        private void RegisterEmployee()
        {
            IsShowForm = true;
        }

        /// <summary>
        /// Fetches employee details
        /// </summary>
        private void GetEmployeeDetails()
        {
            var employeeDetails = WebAPI.GetCall(API_URIs.employees);
            if (employeeDetails.Result.StatusCode == System.Net.HttpStatusCode.OK)
            {
                Employees = employeeDetails.Result.Content.ReadAsAsync<List<Employee>>().Result;
                IsLoadData = true;
            }
        }

        /// <summary>
        /// Adds new employee
        /// </summary>
        private void CreateNewEmployee()
        {
            Employee newEmployee = new Employee()
            {
                FirstName = FirstName,
                LastName = LastName,
                Gender = Gender,
                Salary = Salary
            };
            var employeeDetails = WebAPI.PostCall(API_URIs.employees, newEmployee);
            if (employeeDetails.Result.StatusCode == System.Net.HttpStatusCode.Created)
            {
                ShowPostMessage = newEmployee.FirstName + "'s details has successfully been added!";
            }
            else
            {
                ShowPostMessage = "Failed to update" + newEmployee.FirstName + "'s details.";
            }
        }

        /// <summary>
        /// Updates employee's record
        /// </summary>
        /// <param name="employee"></param>
        private void UpdateEmployeeDetails(Employee employee)
        {
            var employeeDetails = WebAPI.PutCall(API_URIs.employees+ "?id="+employee.ID, employee);
            if (employeeDetails.Result.StatusCode == System.Net.HttpStatusCode.OK)
            {
                ResponseMessage = employee.FirstName + "'s details has successfully been updated!";
            }
            else
            {
                ResponseMessage = "Failed to update"+ employee.FirstName + "'s details.";
            }
        }

        /// <summary>
        /// Deletes employee's record
        /// </summary>
        /// <param name="employee"></param>
        private void DeleteEmployeeDetails(Employee employee)
        {
            var employeeDetails = WebAPI.DeleteCall(API_URIs.employees + "?id=" + employee.ID);
            if (employeeDetails.Result.StatusCode == System.Net.HttpStatusCode.OK)
            {
                ResponseMessage = employee.FirstName + "'s details has successfully been deleted!";
            }
            else
            {
                ResponseMessage = "Failed to delete" + employee.FirstName + "'s details.";
            }
        }
        #endregion
    }
}

Finally, the WPF View is used to display the REST API operations.

After having all these fields updated, Our MainWindow will look like this.

MainWindow

MainWindow.xaml

<Window x:Class="A.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        xmlns:ViewModel="clr-namespace:A"
        Title="MainWindow" Height="600" Width="350">
    <Window.Resources>
        <ViewModel:MainWindowViewModel x:Key="VM" />
        <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
    </Window.Resources>
    <Grid x:Name="MainGrid"
          DataContext="{Binding Source={StaticResource VM}}"
          HorizontalAlignment="Center">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="4*"/>
        </Grid.RowDefinitions>
    
        <StackPanel x:Name="StackPanelGetPost"
                    Orientation="Horizontal"
                    HorizontalAlignment="Center"
                    Margin="0 10 0 0">
            <Button x:Name="ButtonGet"
                    Command="{Binding GetButtonClicked}"
                    Height="20"
                    Width="120"
                    Content="GET"/>
            <Button x:Name="ButtonPost"
                    Command="{Binding ShowRegistrationForm}"
                    Margin="10 0 0 0"
                    Height="20"
                    Width="120"
                    Content="Register Employee"
                    VerticalAlignment="Bottom"/>
        </StackPanel>
        <Grid x:Name="GridEmployeeDetails"
              Visibility="{Binding IsLoadData, Converter={StaticResource BooleanToVisibilityConverter}}"
              Grid.Row="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <DataGrid x:Name="DataGridEmployee"
                      ItemsSource="{Binding Employees}"
                      SelectedItem="{Binding SelectedEmployee}"
                      AutoGenerateColumns="False"
                      AlternatingRowBackground="LightBlue"
                      BorderBrush="Gray"
                      BorderThickness="5"
                      Background="LightGray"
                      Margin="0 10 0 0"
                      RowBackground="LightGray"
                      Width="310" >
                <DataGrid.Columns>
                    <DataGridTextColumn x:Name="ColumnFirstName"
                                        Header="First Name"
                                        Binding="{Binding FirstName}"/>
                    <DataGridTextColumn x:Name="ColumnLastName"
                                        Header="Last Name"
                                        Binding="{Binding LastName}"/>
                    <DataGridTextColumn x:Name="ColumnGender"
                                        Header="Gender"
                                        Binding="{Binding Gender}"/>
                    <DataGridTextColumn x:Name="ColumnSalary"
                                        Header="Salary"
                                        Binding="{Binding Salary}"/>
                </DataGrid.Columns>
            </DataGrid>
            <StackPanel x:Name="StackPanlePutDelete"
                        HorizontalAlignment="Center"
                        Margin="0 10 0 0"
                        Orientation="Horizontal"
                        Grid.Row="1">
                <Button x:Name="ButtonPut"
                        Command="{Binding PutButtonClicked}"
                        CommandParameter="{Binding SelectedEmployee}"
                        Height="20"
                        Width="120"
                        Content="Update"/>
                <Button x:Name="ButtonDelete"
                        Command="{Binding DeleteButtonClicked}"
                        CommandParameter="{Binding SelectedEmployee}"
                        Margin="10 0 0 0"
                        Height="20"
                        Width="120"
                        Content="Delete"/>
            </StackPanel>
            <TextBlock x:Name="TextBlockResponse"        
                       Text="{Binding ResponseMessage}"
                       HorizontalAlignment="Center"        
                       Margin="20 8 0 0"          
                       Grid.Row="2" />
        </Grid>
            
        <Grid x:Name="GridCreateNewEmployee"
              Visibility="{Binding IsShowForm, Converter={StaticResource BooleanToVisibilityConverter}}"
              Grid.Row="2">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="5*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Label x:Name="LabelUserFirstName"        
                   Content="First Name:"        
                   Margin="0 10 0 0"/>
            <Label x:Name="LabelUserLastName"            
                   Content="Last Name:"            
                   Grid.Row="1"/>
            <Label x:Name="LabelGender"            
                   Content="Gender:"            
                   Grid.Row="2"/>
            <Label x:Name="LabelSalary"            
                   Content="Salary:"            
                   Grid.Row="3"/>
    
            <TextBox x:Name="TextBoxUserFirstName"              
                     Text="{Binding FirstName}"        
                     Height="20"               
                     Width="150"              
                     Grid.Column="1"/>
            <TextBox x:Name="TextBoxUserLastName"              
                     Text="{Binding LastName}"        
                     Height="20"               
                     Width="150"              
                     Grid.Row="1"     
                     Grid.Column="1"/>
            <TextBox x:Name="TextBoxGender"              
                     Text="{Binding Gender}"        
                     Height="20"               
                     Width="150"              
                     Grid.Row="2"     
                     Grid.Column="1"/>
            <TextBox x:Name="TextBoxSalary"      
                     Text="{Binding Salary}"        
                     Height="20"               
                     Width="150"               
                     Grid.Column="1"          
                     Grid.Row="3"/>
    
            <Button x:Name="ButtonAdd"          
                    Height="20"          
                    Width="100"          
                    Content="POST"          
                    HorizontalAlignment="Center"          
                    Margin="20 10 0 0"            

Now run that beautiful piece of code, and you will be able to perform the actions the same as in the following gif.

Note. Watch the complete gif to come across all the operations.

Output

That just looks delicious. Everything has been added in perfect amounts & it is working as smoothly as butter on a hot pan & believe me, the final product does taste good.

So, folks, This is how you call a REST API in your C# backed project.

Conclusion

I will leave you here to do further R & D. Find the source code here for your reference. Give it a shot!

I also appreciate the patience of the audience who has come along for all 3 parts to learn this. Kudos.

If you have all the 3 projects running under 1 solution, then you have to select 2 major projects as the startup project. Go to the solution properties and do as follows.

Startup Project

If you wish to talk, feel free to meet me @