Header Ads

WPF: REST Web API Consumption

When we are working in client machine base software or application development. The most crucial area is data communication from client machine. Since we are not working here with web development, this means that the data whether entry or from server will eventually needs to be transferred from client machine to server machine or from server machine to client machine. This also adds sensitivity level towards the client applications in terms of which data needs to be sent to the client machine or which data needs to be uploaded to server machine. The answer to all this is either REST web API or SOAP web services.
Remember people usually mix REST web API and SOAP web services as same concepts, however, both are very different from each other and have their own purpose in their respective areas. I recommend REST vs SOAP stack overflow thread for better understanding. Another detail explanation of REST vs SOAP.

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


Prerequisites:

Following are some prerequisites before you proceed further in this tutorial:
  1. Knowledge about REST web API development.
  2. Knowledge about Windows Presentation Form (WPF).
  3. Knowledge about T-SQL Programming
  4. Knowledge about C# programming.
  5. Knowledge about 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.

Download Link

Let's begin now.

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

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

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

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

USE [WpfWalkthrough]
GO
/****** Object:  Table [dbo].[Register]    Script Date: 3/27/2018 5:55:01 PM ******/
DROP TABLE [dbo].[Register]
GO
/****** Object:  Table [dbo].[Register]    Script Date: 3/27/2018 5:55:01 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Register](
 [id] [int] IDENTITY(1,1) NOT NULL,
 [fullname] [nvarchar](max) NOT NULL,
 CONSTRAINT [PK_Register] PRIMARY KEY CLUSTERED 
(
 [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

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

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


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

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 i.e.


8) Now, create "Helper_Code\Common\DAL.cs" file and replace following code in it i.e.

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WPF_Client_Web_API.Helper_Code.Common
{
    public class DAL
    {
        public static int executeQuery(string query)
        {
            // Initialization.
            int rowCount = 0;
            string strConn = "Data Source=SQL Server Name(e.g. localhost);Database=SQL Database Name;User Id=SQL User Name;Password=SQL Password;";
            SqlConnection sqlConnection = new SqlConnection(strConn);
            SqlCommand sqlCommand = new SqlCommand();

            try
            {
                // Settings.
                sqlCommand.CommandText = query;
                sqlCommand.CommandType = CommandType.Text;
                sqlCommand.Connection = sqlConnection;
                sqlCommand.CommandTimeout = 12 * 3600; //// Setting timeeout for longer queries to 12 hours.

                // Open.
                sqlConnection.Open();

                // Result.
                rowCount = sqlCommand.ExecuteNonQuery();

                // Close.
                sqlConnection.Close();
            }
            catch (Exception ex)
            {
                // Close.
                sqlConnection.Close();

                throw ex;
            }

            return rowCount;
        }
    }
}

The above piece of code will allow us to communicate with 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.

9) Now, create "Helper_Code\Objects\RegInfoRequestObj.cs" & "Helper_Code\Objects\RegInfoResponseObj.cs" files and replace following code it i.e.

1) Helper_Code\Objects\RegInfoRequestObj.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WPF_Client_Web_API.Helper_Code.Objects
{
    public class RegInfoRequestObj
    {
        public string fullname { get; set; }
    }
}

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.

2) Helper_Code\Objects\RegInfoResponseObj.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WPF_Client_Web_API.Helper_Code.Objects
{
    public class RegInfoResponseObj
    {
        public bool status { get; set; }
        public int code { get; set; }
        public string message { get; set; }
    }
}

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

10) Create "Model\BusinessLogic\HomeBusinessLogic.cs" file and replace following code in it i.e.

using WPF_Client_Web_API.Helper_Code.Objects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json;
using WPF_Client_Web_API.Helper_Code.Common;

namespace WPF_Client_Web_API.Model.BusinessLogic.Helper_Code.Common
{
    public class HomeBusinessLogic
    {
        public static void saveInfo(string fullname)
        {
            try
            {
                // Query.
                string query = "INSERT INTO [Register] ([fullname])" +
                                " Values ('" + fullname + "')";

                // Execute.
                DAL.executeQuery(query);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public static async Task<RegInfoResponseObj> PostRegInfo(RegInfoRequestObj requestObj)
        {
            // Initialization.
            RegInfoResponseObj responseObj = new RegInfoResponseObj();

            try
            {
                // Posting.
                using (var client = new HttpClient())
                {
                    // Setting Base address.
                    client.BaseAddress = new Uri("http://localhost:19006/");

                    // Setting content type.
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                    // Setting timeout.
                    client.Timeout = TimeSpan.FromSeconds(Convert.ToDouble(1000000));

                    // Initialization.
                    HttpResponseMessage response = new HttpResponseMessage();

                    // HTTP POST
                    response = await client.PostAsJsonAsync("api/WebApi/PostRegInfo", requestObj).ConfigureAwait(false);

                    // Verification
                    if (response.IsSuccessStatusCode)
                    {
                        // Reading Response.
                        string result = response.Content.ReadAsStringAsync().Result;
                        responseObj = JsonConvert.DeserializeObject<RegInfoResponseObj>(result);

                        // Releasing.
                        response.Dispose();
                    }
                    else
                    {
                        // Reading Response.
                        string result = response.Content.ReadAsStringAsync().Result;
                        responseObj.code = 602;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return responseObj;
        }
    }
}

In the above code, I have created a simple wrapper method "SveInfo(...)" that will communicate with 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 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 receive response from server i.e. whether it is successful to failure in a form of defined codes, statuses and messages.

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

<Page x:Class="WPF_Client_Web_API.Views.HomePage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:WPF_Client_Web_API.Views"
      mc:Ignorable="d" 
      d:DesignHeight="480" d:DesignWidth="640"
      Title="HomePage">

    <Grid>
        <DockPanel>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="0.05*" />
                    <RowDefinition Height="*" />
                    <RowDefinition Height="0.05*" />
                </Grid.RowDefinitions>

                <Border Grid.Row="1"
                        Width=" 400"
                        Height="300" 
                        BorderThickness="1" 
                        BorderBrush="Black" 
                        CornerRadius="20" 
                        Opacity="1">
                    <Border.Background>
                        <ImageBrush ImageSource="/WPF Client Web API;component/Content/img/bg_2.png">
                            <ImageBrush.RelativeTransform>
                                <TransformGroup>
                                    <ScaleTransform CenterY="0.5" CenterX="0.5" ScaleX="1.5" ScaleY="1.5"/>
                                    <SkewTransform CenterY="0.5" CenterX="0.5"/>
                                    <RotateTransform CenterY="0.5" CenterX="0.5"/>
                                    <TranslateTransform/>
                                </TransformGroup>
                            </ImageBrush.RelativeTransform>
                        </ImageBrush>
                    </Border.Background>

                    <StackPanel Orientation="Vertical" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center"
                                Width=" 400"
                                Height="300" >

                        <TextBlock Text="Enter Your Full Name"
                                   VerticalAlignment="Center"
                                   HorizontalAlignment="Center" 
                                   Margin="0,70,0,0" 
                                   FontWeight="Bold" 
                                   FontSize="18" 
                                   Foreground="Black" />

                        <Border Width="220"
                                Height="50"
                                Margin="0,10,0,0">

                            <Border.Background>
                                <ImageBrush ImageSource="/WPF Client Web API;component/Content/img/text-box_bg.png"/>
                            </Border.Background>

                            <TextBox x:Name="txtName" 
                                    BorderThickness="0"
                                    FontSize="18"
                                    Width="220"
                                    Height="50" 
                                    Background="{x:Null}" 
                                    Padding="10,12,0,0" 
                                    Foreground="Black"
                                    HorizontalAlignment="Center"/>
                        </Border>

                        <Button x:Name="btnReg"
                                Content="Register"
                                Width="220" 
                                Height="50"
                                Margin="0,10,0,0"
                                FontSize="18" 
                                FontWeight="Bold" 
                                Click="BtnReg_Click" />


                    </StackPanel>
                </Border>
            </Grid>

        </DockPanel>
    </Grid>
</Page>

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

12) Open the "Views\HomePage.xaml\HomePage.xaml.cs" file and replace following code in it i.e.

using WPF_Client_Web_API.Helper_Code.Common;
using WPF_Client_Web_API.Helper_Code.Objects;
using WPF_Client_Web_API.Model.BusinessLogic.Helper_Code.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPF_Client_Web_API.Views
{
    /// <summary>
    /// Interaction logic for HomePage.xaml
    /// </summary>
    public partial class HomePage : Page
    {
        public HomePage()
        {
            InitializeComponent();
        }

        private async void BtnReg_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // Initialization.
                string fullname = this.txtName.Text, obj;

                // Save Info to Local DB.
                HomeBusinessLogic.saveInfo(fullname);

                // Sending data to server.
                RegInfoRequestObj requestObj = new RegInfoRequestObj { fullname = fullname };
                RegInfoResponseObj responseObj = await HomeBusinessLogic.PostRegInfo(requestObj);

                // Veerification.
                if (responseObj.code == 600)
                {
                    // Display Message
                    MessageBox.Show("You are Successfully! Registered", "Success", MessageBoxButton.OK, MessageBoxImage.Information);
                }
                else if (responseObj.code == 602)
                {
                    // Display Message
                    MessageBox.Show("We are unable to register you at the moment, please try again later", "Fail", MessageBoxButton.OK, MessageBoxImage.Error);
                }

            }
            catch (Exception ex)
            {
                // Display Message
                MessageBox.Show("Something goes wrong, Please try again later.", "Fail", MessageBoxButton.OK, MessageBoxImage.Error);

                Console.Write(ex);
            }
        }
    }
}

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

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

<Window x:Class="WPF_Client_Web_API.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF_Client_Web_API"
        mc:Ignorable="d"
        Title="WPF REST API Consumption" d:DesignHeight="480" d:DesignWidth="640">
    <Grid>
        <Grid.Background>
            <ImageBrush ImageSource="Content/img/main_bg.jpg"/>
        </Grid.Background>
        <Frame x:Name="mainFrame" 
               NavigationUIVisibility="Hidden"/>
    </Grid>
</Window>

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

14) Now, open the "MainWindow.xaml\MainWindow.cs" file and replace the following code in it i.e.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPF_Client_Web_API
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            this.Loaded += MainWindow_Loaded;
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            this.mainFrame.Navigate(new Uri("/Views/HomePage.xaml", UriKind.Relative));
        }
    }
}

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

15) Execute the project and you will be able to see following i.e.





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


Conclusion

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


Disclaimer

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

No comments