WPF - REST Web API Consumption

When we are working in client machine based software or application development, the most crucial area is data communication from the client machine. Since we are not working here with web development, this means that the data, whether an entry or from a server, will eventually need to be transferred from client machine to server machine or from server machine to client machine. This also adds a sensitivity level to the client applications in terms of which data needs to be sent to the client machine or which data needs to be uploaded to the server machine. The answer to all this is either REST web API or SOAP web services.

Remember people usually use REST web API and SOAP web services interchangeably, however, both are very different from each other and have their own purpose in their respective areas. I recommend the REST vs SOAP stack overflow thread for better understanding. Here's another detailed explanation of REST vs SOAP.

Today, I shall be demonstrating the implementation of REST web API consumption in WPF applications.


Prerequisites

Following are some prerequisites before you proceed further in this tutorial:

  1. Knowledge of REST web API development.
  2. Knowledge of Windows Presentation Form (WPF).
  3. Knowledge of T-SQL Programming
  4. Knowledge of C# programming.
  5. Knowledge of C# LINQ.

You can download the complete source code for this tutorial or you can follow the step by step discussion below. The sample code is developed in Microsoft Visual Studio 2015 Enterprise. For this tutorial, I have created a simple REST web API which is provided with the solution. I will not go into the details of how to develop a REST web API if anyone is interested then go to the link How to develop a REST web API.

Let's begin now.

Step 1

The targeted REST web API and its SQL server database script are provided in the solution. Simply execute the SQL server script into your SQL server.

Step 2

Then open the "RestWebApiServer" visual studio solution and open "Web.config" file and provide your SQL server configuration string.

Step 3

Then execute the project without debugging and leave it as it is.

Step 4

Now, Create a simple database with a table in your SQL Server for storing the data from WPF application on a client machine, I am using SQL Server 2014 as shown below:

  1. USE [WpfWalkthrough]  
  2. GO  
  3. /****** Object:  Table [dbo].[Register]    Script Date: 3/27/2018 5:55:01 PM ******/  
  4. DROP TABLE [dbo].[Register]  
  5. GO  
  6. /****** Object:  Table [dbo].[Register]    Script Date: 3/27/2018 5:55:01 PM ******/  
  7. SET ANSI_NULLS ON  
  8. GO  
  9. SET QUOTED_IDENTIFIER ON  
  10. GO  
  11. CREATE TABLE [dbo].[Register](  
  12.  [id] [int] IDENTITY(1,1) NOT NULL,  
  13.  [fullname] [nvarchar](maxNOT NULL,  
  14.  CONSTRAINT [PK_Register] PRIMARY KEY CLUSTERED   
  15. (  
  16.  [id] ASC  
  17. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ONON [PRIMARY]  
  18. ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]  
  19.   
  20. GO 

In the above script, I have simply created my main database on an end-user client machine and I have created a simple table for storing information.

Step 5

You can see that your table is empty as shown below, also, notice that server database is also empty. Since I am using the same machine for both server and client machines, therefore, both databases are shown here in the same SQL server:


Step 6

Now, create a new WPF application project and name it "WPF Client Web API".

Step 7

Install "Microsoft.AspNet.WebApi.Client" & "Newtonsoft.Json" packages from "Tools->NuGet Package Manager->Manage NuGet Packages for Solutions" into your visual studio WPF project:



Step 8

Now, create "Helper_Code\Common\DAL.cs" file and replace following code in it:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Data;  
  4. using System.Data.SqlClient;  
  5. using System.Linq;  
  6. using System.Text;  
  7. using System.Threading.Tasks;  
  8.   
  9. namespace WPF_Client_Web_API.Helper_Code.Common  
  10. {  
  11.     public class DAL  
  12.     {  
  13.         public static int executeQuery(string query)  
  14.         {  
  15.             // Initialization.  
  16.             int rowCount = 0;  
  17.             string strConn = "Data Source=SQL Server Name(e.g. localhost);Database=SQL Database Name;User Id=SQL User Name;Password=SQL Password;";  
  18.             SqlConnection sqlConnection = new SqlConnection(strConn);  
  19.             SqlCommand sqlCommand = new SqlCommand();  
  20.   
  21.             try  
  22.             {  
  23.                 // Settings.  
  24.                 sqlCommand.CommandText = query;  
  25.                 sqlCommand.CommandType = CommandType.Text;  
  26.                 sqlCommand.Connection = sqlConnection;  
  27.                 sqlCommand.CommandTimeout = 12 * 3600; //// Setting timeeout for longer queries to 12 hours.  
  28.   
  29.                 // Open.  
  30.                 sqlConnection.Open();  
  31.   
  32.                 // Result.  
  33.                 rowCount = sqlCommand.ExecuteNonQuery();  
  34.   
  35.                 // Close.  
  36.                 sqlConnection.Close();  
  37.             }  
  38.             catch (Exception ex)  
  39.             {  
  40.                 // Close.  
  41.                 sqlConnection.Close();  
  42.   
  43.                 throw ex;  
  44.             }  
  45.   
  46.             return rowCount;  
  47.         }  
  48.     }  

The above piece of code will allow us to communicate with the SQL server in order to perform related queries. For this method to work, you need to replace the SQL Server database connection string with your own credentials and settings.

Step 9

Now, create "Helper_Code\Objects\RegInfoRequestObj.cs" & "Helper_Code\Objects\RegInfoResponseObj.cs" files and replace the following code in it:

Helper_Code\Objects\RegInfoRequestObj.cs

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6.   
  7. namespace WPF_Client_Web_API.Helper_Code.Objects  
  8. {  
  9.     public class RegInfoRequestObj  
  10.     {  
  11.         public string fullname { getset; }  
  12.     }  

In the above code, I have simply created my request object, which I will convert to JSON format and post to the REST web API.

Helper_Code\Objects\RegInfoResponseObj.cs

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5.   
  6. namespace WPF_Client_Web_API.Helper_Code.Objects  
  7. {  
  8.     public class RegInfoResponseObj  
  9.     {  
  10.         public bool status { getset; }  
  11.         public int code { getset; }  
  12.         public string message { getset; }  
  13.     }  

In the above code, I have simply created my response object, which I will be using to parse the server JSON format response into a simple object.

Step 10

Create "Model\BusinessLogic\HomeBusinessLogic.cs" file and replace following code in it:

  1. using WPF_Client_Web_API.Helper_Code.Objects;  
  2. using System;  
  3. using System.Collections.Generic;  
  4. using System.IO;  
  5. using System.Linq;  
  6. using System.Reflection;  
  7. using System.Text;  
  8. using System.Threading.Tasks;  
  9. using System.Net.Http;  
  10. using System.Net.Http.Headers;  
  11. using Newtonsoft.Json;  
  12. using WPF_Client_Web_API.Helper_Code.Common;  
  13.   
  14. namespace WPF_Client_Web_API.Model.BusinessLogic.Helper_Code.Common  
  15. {  
  16.     public class HomeBusinessLogic  
  17.     {  
  18.         public static void saveInfo(string fullname)  
  19.         {  
  20.             try  
  21.             {  
  22.                 // Query.  
  23.                 string query = "INSERT INTO [Register] ([fullname])" +  
  24.                                 " Values ('" + fullname + "')";  
  25.   
  26.                 // Execute.  
  27.                 DAL.executeQuery(query);  
  28.             }  
  29.             catch (Exception ex)  
  30.             {  
  31.                 throw ex;  
  32.             }  
  33.         }  
  34.   
  35.         public static async Task<RegInfoResponseObj> PostRegInfo(RegInfoRequestObj requestObj)  
  36.         {  
  37.             // Initialization.  
  38.             RegInfoResponseObj responseObj = new RegInfoResponseObj();  
  39.   
  40.             try  
  41.             {  
  42.                 // Posting.  
  43.                 using (var client = new HttpClient())  
  44.                 {  
  45.                     // Setting Base address.  
  46.                     client.BaseAddress = new Uri("http://localhost:19006/");  
  47.   
  48.                     // Setting content type.  
  49.                     client.DefaultRequestHeaders.Accept.Clear();  
  50.                     client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));  
  51.   
  52.                     // Setting timeout.  
  53.                     client.Timeout = TimeSpan.FromSeconds(Convert.ToDouble(1000000));  
  54.   
  55.                     // Initialization.  
  56.                     HttpResponseMessage response = new HttpResponseMessage();  
  57.   
  58.                     // HTTP POST  
  59.                     response = await client.PostAsJsonAsync("api/WebApi/PostRegInfo", requestObj).ConfigureAwait(false);  
  60.   
  61.                     // Verification  
  62.                     if (response.IsSuccessStatusCode)  
  63.                     {  
  64.                         // Reading Response.  
  65.                         string result = response.Content.ReadAsStringAsync().Result;  
  66.                         responseObj = JsonConvert.DeserializeObject<RegInfoResponseObj>(result);  
  67.   
  68.                         // Releasing.  
  69.                         response.Dispose();  
  70.                     }  
  71.                     else  
  72.                     {  
  73.                         // Reading Response.  
  74.                         string result = response.Content.ReadAsStringAsync().Result;  
  75.                         responseObj.code = 602;  
  76.                     }  
  77.                 }  
  78.             }  
  79.             catch (Exception ex)  
  80.             {  
  81.                 throw ex;  
  82.             }  
  83.   
  84.             return responseObj;  
  85.         }  
  86.     }  

In the above code, I have created a simple wrapper method "SveInfo(...)" that will communicate with the SQL server using my previously created "executeQuery(...)" method from DAL (Data Access Layer) class. This "SaveInfo(...)" method will perform SQL server database insertion query and store the target data from the user into SQL server table as targeted.

The other method "PostRegInfo(...)" will use HttpClient class and establish a connection with REST web API by providing target REST web API URL & username/password (if any) settings and then convert our user input data into JSON format and post that data to the server via REST web API. The "PostRegInfo(...)" also receives a response from the server; i.e., whether it is successful or failed in the form of defined codes, statuses and messages.

Step 11

Now, create a new page "Views\HomePage.xaml" file and replace the following code in it:

  1. <Page x:Class="WPF_Client_Web_API.Views.HomePage"  
  2.       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  3.       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  4.       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"   
  5.       xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   
  6.       xmlns:local="clr-namespace:WPF_Client_Web_API.Views"  
  7.       mc:Ignorable="d"   
  8.       d:DesignHeight="480" d:DesignWidth="640"  
  9.       Title="HomePage">  
  10.   
  11.     <Grid>  
  12.         <DockPanel>  
  13.             <Grid>  
  14.                 <Grid.RowDefinitions>  
  15.                     <RowDefinition Height="0.05*" />  
  16.                     <RowDefinition Height="*" />  
  17.                     <RowDefinition Height="0.05*" />  
  18.                 </Grid.RowDefinitions>  
  19.   
  20.                 <Border Grid.Row="1"  
  21.                         Width=" 400"  
  22.                         Height="300"   
  23.                         BorderThickness="1"   
  24.                         BorderBrush="Black"   
  25.                         CornerRadius="20"   
  26.                         Opacity="1">  
  27.                     <Border.Background>  
  28.                         <ImageBrush ImageSource="/WPF Client Web API;component/Content/img/bg_2.png">  
  29.                             <ImageBrush.RelativeTransform>  
  30.                                 <TransformGroup>  
  31.                                     <ScaleTransform CenterY="0.5" CenterX="0.5" ScaleX="1.5" ScaleY="1.5"/>  
  32.                                     <SkewTransform CenterY="0.5" CenterX="0.5"/>  
  33.                                     <RotateTransform CenterY="0.5" CenterX="0.5"/>  
  34.                                     <TranslateTransform/>  
  35.                                 </TransformGroup>  
  36.                             </ImageBrush.RelativeTransform>  
  37.                         </ImageBrush>  
  38.                     </Border.Background>  
  39.   
  40.                     <StackPanel Orientation="Vertical"   
  41.                                 HorizontalAlignment="Center"  
  42.                                 VerticalAlignment="Center"  
  43.                                 Width=" 400"  
  44.                                 Height="300" >  
  45.   
  46.                         <TextBlock Text="Enter Your Full Name"  
  47.                                    VerticalAlignment="Center"  
  48.                                    HorizontalAlignment="Center"   
  49.                                    Margin="0,70,0,0"   
  50.                                    FontWeight="Bold"   
  51.                                    FontSize="18"   
  52.                                    Foreground="Black" />  
  53.   
  54.                         <Border Width="220"  
  55.                                 Height="50"  
  56.                                 Margin="0,10,0,0">  
  57.   
  58.                             <Border.Background>  
  59.                                 <ImageBrush ImageSource="/WPF Client Web API;component/Content/img/text-box_bg.png"/>  
  60.                             </Border.Background>  
  61.   
  62.                             <TextBox x:Name="txtName"   
  63.                                     BorderThickness="0"  
  64.                                     FontSize="18"  
  65.                                     Width="220"  
  66.                                     Height="50"   
  67.                                     Background="{x:Null}"   
  68.                                     Padding="10,12,0,0"   
  69.                                     Foreground="Black"  
  70.                                     HorizontalAlignment="Center"/>  
  71.                         </Border>  
  72.   
  73.                         <Button x:Name="btnReg"  
  74.                                 Content="Register"  
  75.                                 Width="220"   
  76.                                 Height="50"  
  77.                                 Margin="0,10,0,0"  
  78.                                 FontSize="18"   
  79.                                 FontWeight="Bold"   
  80.                                 Click="BtnReg_Click" />  
  81.   
  82.   
  83.                     </StackPanel>  
  84.                 </Border>  
  85.             </Grid>  
  86.   
  87.         </DockPanel>  
  88.     </Grid>  
  89. </Page> 

In the above code, I have created a simple text box to enter the user's full name and a button which will store the information into the SQL server locally and post the data to REST web API.

Step 12

Open the "Views\HomePage.xaml\HomePage.xaml.cs" file and replace the following code in it:

  1. using WPF_Client_Web_API.Helper_Code.Common;  
  2. using WPF_Client_Web_API.Helper_Code.Objects;  
  3. using WPF_Client_Web_API.Model.BusinessLogic.Helper_Code.Common;  
  4. using System;  
  5. using System.Collections.Generic;  
  6. using System.Linq;  
  7. using System.Text;  
  8. using System.Threading.Tasks;  
  9. using System.Windows;  
  10. using System.Windows.Controls;  
  11. using System.Windows.Data;  
  12. using System.Windows.Documents;  
  13. using System.Windows.Input;  
  14. using System.Windows.Media;  
  15. using System.Windows.Media.Imaging;  
  16. using System.Windows.Navigation;  
  17. using System.Windows.Shapes;  
  18.   
  19. namespace WPF_Client_Web_API.Views  
  20. {  
  21.     /// <summary>  
  22.     /// Interaction logic for HomePage.xaml  
  23.     /// </summary>  
  24.     public partial class HomePage : Page  
  25.     {  
  26.         public HomePage()  
  27.         {  
  28.             InitializeComponent();  
  29.         }  
  30.   
  31.         private async void BtnReg_Click(object sender, RoutedEventArgs e)  
  32.         {  
  33.             try  
  34.             {  
  35.                 // Initialization.  
  36.                 string fullname = this.txtName.Text, obj;  
  37.   
  38.                 // Save Info to Local DB.  
  39.                 HomeBusinessLogic.saveInfo(fullname);  
  40.   
  41.                 // Sending data to server.  
  42.                 RegInfoRequestObj requestObj = new RegInfoRequestObj { fullname = fullname };  
  43.                 RegInfoResponseObj responseObj = await HomeBusinessLogic.PostRegInfo(requestObj);  
  44.   
  45.                 // Veerification.  
  46.                 if (responseObj.code == 600)  
  47.                 {  
  48.                     // Display Message  
  49.                     MessageBox.Show("You are Successfully! Registered""Success", MessageBoxButton.OK, MessageBoxImage.Information);  
  50.                 }  
  51.                 else if (responseObj.code == 602)  
  52.                 {  
  53.                     // Display Message  
  54.                     MessageBox.Show("We are unable to register you at the moment, please try again later""Fail", MessageBoxButton.OK, MessageBoxImage.Error);  
  55.                 }  
  56.   
  57.             }  
  58.             catch (Exception ex)  
  59.             {  
  60.                 // Display Message  
  61.                 MessageBox.Show("Something goes wrong, Please try again later.""Fail", MessageBoxButton.OK, MessageBoxImage.Error);  
  62.   
  63.                 Console.Write(ex);  
  64.             }  
  65.         }  
  66.     }  

In the above code, I have created the action method for the register button and performed a database insertion action to store the data into SQL server. I have also coded on-screen display messages to prompt the user about his/her action. Then I have posted the data to REST web API and displayed the on-screen messages accordingly.

Step 13

We need to attach the page inside the main window so, open the "MainWindow.xaml" file and replace the following in it:

  1. <Window x:Class="WPF_Client_Web_API.MainWindow"  
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  4.         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
  5.         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
  6.         xmlns:local="clr-namespace:WPF_Client_Web_API"  
  7.         mc:Ignorable="d"  
  8.         Title="WPF REST API Consumption" d:DesignHeight="480" d:DesignWidth="640">  
  9.     <Grid>  
  10.         <Grid.Background>  
  11.             <ImageBrush ImageSource="Content/img/main_bg.jpg"/>  
  12.         </Grid.Background>  
  13.         <Frame x:Name="mainFrame"   
  14.                NavigationUIVisibility="Hidden"/>  
  15.     </Grid>  
  16. </Window> 

In the above code, I have added a default background image taken from freepike and a frame which contains my page. The window will immediately navigate to the main page.

Step 14

Now, open the "MainWindow.xaml\MainWindow.cs" file and replace the following code in it:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6. using System.Windows;  
  7. using System.Windows.Controls;  
  8. using System.Windows.Data;  
  9. using System.Windows.Documents;  
  10. using System.Windows.Input;  
  11. using System.Windows.Media;  
  12. using System.Windows.Media.Imaging;  
  13. using System.Windows.Navigation;  
  14. using System.Windows.Shapes;  
  15.   
  16. namespace WPF_Client_Web_API  
  17. {  
  18.     /// <summary>  
  19.     /// Interaction logic for MainWindow.xaml  
  20.     /// </summary>  
  21.     public partial class MainWindow : Window  
  22.     {  
  23.         public MainWindow()  
  24.         {  
  25.             InitializeComponent();  
  26.   
  27.             this.Loaded += MainWindow_Loaded;  
  28.         }  
  29.   
  30.         private void MainWindow_Loaded(object sender, RoutedEventArgs e)  
  31.         {  
  32.             this.mainFrame.Navigate(new Uri("/Views/HomePage.xaml", UriKind.Relative));  
  33.         }  
  34.     }  

The above piece of code will navigate the frame to my main page at the time of launching the main window of the WPF application.

Step 15

Execute the project and you will be able to see the following:




The user input data will be stored in the SQL server table on client machine & server machine as shown below. Since I am using the same machine for both server and client machines, therefore, both databases are shown here in the same SQL server:


Conclusion

In this article, you learned to post WPF application data from client machine to remote server machine using REST web API. You also learned to connect to SQL Server in WPF local client machine in order to store the data. You also learned about storing data from WPF applications directly into the SQL server by performing SQL queries at Data Access Layer of WPF application. You also learned to display success & error messages on WPF UI screen to prompt the user for his/her actions with your WPF application. You learned to capture the REST web API server response into WPF applications and display the messages on the screen accordingly. You learned to add a background to the main window and you learned to add a page within the window by using frame control.

Disclaimer

The background image used in this article has been taken from freepike.

G
M
T

 





Text-to-speech function is limited to 200 characters