Introduction
Want to Download Source code just pull it from Given GitHub URL
https://github.com/saineshwar/SMARTCLIENTPROJECT
In this article, we are going learn to create an application that works online and offline, oh you might think what’s this an application online and offline really means if the application is connected to an internet connection then the application is online and if the application is not connected to any internet connection it's offline.
Fig 1.Users difference in working
For making this kind of application I have created 2 applications.
- Asp.net MVC web application
- Windows application
You again might think why 2 application right?
Asp.net MVC web application
Asp.net MVC web application has the functionality of new Client registration, Login, displaying data.
The web application also contains Web APIs which is going to be consumed by Windows application to Insert data and delete data.
And after inserting the data from Windows application this inserted data must be displayed on the dashboard when user login with user credentials in MVC web application.
All the reporting will be done on data which is available on the web server.
Windows application
In windows application, we are going to log in with same credentials which we have registered in web application and while we are logging for the first time in windows application we need an Internet connection to that you can also login into the application while the application is offline.
After Successful login, a new form is shown in which User is going to add new product and while doing this process we do not require an internet connection.
When an internet connection is available it will sync all data from windows application to web application [web server] and this process will run in background.
Meanwhile it is transferring all data to the web server it will also delete that data from windows application database which is transferred.
Tools Used for development of web application
Vs2012 express
SQL server 2008 express
Vs2012 express
Sqlite database
Let start with understanding structure of database of web application first
Creating database
Before starting understanding with structure lets create a database in SQL server with name SmartDB
It is simple to create a new database just right click on database folder and then select new database a new dialog with name “New database” will pop up in that it will ask for database name just enter SmartDB and click on ok button.
Fig 2.Database View
After creating the database now let’s add tables in the database.
Adding Table in SmartDB database
Table: - ClientRegistration
In this table, we are going to store data of client registration
Fig 3. ClientRegistration table
Table: - ProductTB
In this table, we are going to store data of product which is sent from a windows application.
Fig 4. ProductTB table
After understanding table structure now let move forward to have look on web application how it is created
Creating MVC Application
Let’s begin with creating a windows form application.
Open visual studio IDE from start page click on new project link a new dialog will pop up with name new project, after that from left panel select Templates à inside that Web and finally in middle panel select “ASP.NET MVC 4 Web Application” after that we are going to name your project as “SmartWebApp”.
Fig 5. Creating MVC Application
After naming project just click on Ok button to create project after clicking on the ok button a new dialog will pop up with name “New ASP.NET MVC 4 Project” in this project templates we are going to choose Basic Template and finally click on ok button.
Fig 6. Choosing Project template
Project structure after creating application
Fig 7. Project structure after creating application
After creating the solution we are going to implement a Repository Pattern in this solution.
Implementing repository Pattern
For implementing repository pattern we need to add a class library to the solution.
Fig 8. Implementing repository Pattern
Let’s add the first layer with the name [SmartWebApp.Model] for adding just right click on solution [SmartWebApp] and then select Add àinside that select New Project after selecting a new Add Project a new dialog will pop up inside that select Type visual C# from left panel à inside that select windows after selecting windows in centre panel you will find various projects select class library from it and name it as “SmartWebApp.Model” and final click on ok button.
In a similar way we are going to add all projects
[SmartWebApp.Interface],
[SmartWebApp.Concrete],
[SmartWebApp.BL]
Adding reference to projects
Fig 9. Adding reference to projects
After adding a reference to project now we are going to create a registration page for users to register for using your windows application.
Adding Model in [SmartWebApp.Model]
In this part, we are going to add a simple class in [SmartWebApp.Model] project with name Registration and apply Data Annotations to its properties.
Code snippet of Registration Model
public class Registration
{
[Key]
public long RegistrationID { get; set; }
[Required(ErrorMessage = "Enter First Name")]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 3)]
public string FirstName { get; set; }
[Required(ErrorMessage = "Enter Last Name")]
public string Lastname { get; set; }
[Required(ErrorMessage = "Select Gender")]
public string Gender { get; set; }
[Required(ErrorMessage = "Enter Username ")]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[Remote("ValidateUser", "Register", ErrorMessage = "Username Already Exists")]
public string Username { get; set; }
[Required(ErrorMessage = "Enter Password")]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
public string Password { get; set; }
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
[Required(ErrorMessage = "Enter Confirm Password")]
[DataType(DataType.Password)]
public string ConfirmPassword { get; set; }
[Required(ErrorMessage = "Enter Mobileno")]
public string Mobileno { get; set; }
[Required(ErrorMessage = "Enter EmailID")]
[DataType(DataType.EmailAddress)]
public string EmailID { get; set; }
}
After adding model now let’s move forward to add a Controller and view in step by step way.
Adding Register Controller
For Adding Register Controller Just Right click on Controller Folder inside that select Add and then select Controller , After clicking on Controller new dialog will pop up with name Add Controller. In this Dialog to add Controller we are not going to make any change just click on Add button to add a Controller with name “Register Controller”.
Fig 10. Snapshot after adding Register Controller
Adding Interface IRegistration
After adding registration controller now let’s adding new Interface in SmartWebApp.Interface project with name IRegistration and declare some methods in it
Code snippet of IRegistration Interface
using SmartWebApp.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SmartWebApp.Interface
{
public interface IRegistration
{
int CreateUser(Registration registration);
bool ValidateUser(string Username);
}
}
Adding Dapper ORM
RegistrationConcrete this will have a method that will communicate with the database and for communicating we are going to use ORM [Dapper] it is free ORM install it from NuGet.
For adding Dapper ORM just right click on project then select “Manage NuGet packages” a new dialog will pop up Manage NuGet packages than from left panel select online à then select All , after this there is search online box available in right top , in that just type “Dapper” and select “Dapper dot net” and click on install button to install.
If you want to add from Package Manager Console Just type below command
Fig 11. Installing Dapper ORM
Fig 12. Installing Dapper ORM
After adding Dapper ORM lets add database connection string in web.config file.
Configuring Connection string in web.config file
<connectionStrings>
<add name="DBconnection"
connectionString="Data Source=########; UID=##; Password=##########; Database=SmartDB"
providerName="System.Data.SqlClient" />
</connectionStrings>
After adding connection string in web.config file next we are going to add RegistrationConcrete.
Adding class RegistrationConcrete
After adding interface in SmartWebApp.Interface now let’s implement this interface in concrete class by creating new concrete class for registration in SmartWebApp.Concrete with name.
For adding RegistrationConcrete class just right click on SmartWebApp.Concrete project then selects add à class and name class as RegistrationConcrete.
Fig 13. Snapshot after adding RegistrationConcrete
After adding RegistrationConcrete class next we are going to implement IRegistration interface.
As you know we are going to use Dapper ORM along with that we also going to use store procedure for good performance of the application.
Note: - I am going provide stored procedure scripts for download.
Code snippet of RegistrationConcrete class
using SmartWebApp.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SmartWebApp.Model;
using Dapper;
using System.Data.SqlClient;
using System.Configuration;
using System.Data;
namespace SmartWebApp.Concrete
{
public class RegistrationConcrete : IRegistration
{
public int CreateUser(Registration registration)
{
using (SqlConnection con = new
SqlConnection(ConfigurationManager.ConnectionStrings["DBconnection"].ConnectionString))
{
con.Open();
SqlTransaction sqltans = con.BeginTransaction();
var param = new DynamicParameters();
param.Add("@RegistrationID", registration.RegistrationID);
param.Add("@FirstName", registration.FirstName);
param.Add("@Lastname", registration.Lastname);
param.Add("@Gender", registration.Gender);
param.Add("@Username", registration.Username);
param.Add("@Password", registration.Password);
param.Add("@Mobileno", registration.Mobileno);
param.Add("@EmailID", registration.EmailID);
var result = con.Execute("sprocClientRegistrationInsertUpdateSingleItem",
param,
sqltans,
0,
commandType: CommandType.StoredProcedure);
if (result > 0)
{
sqltans.Commit();
}
else
{
sqltans.Rollback();
}
return result;
}
}
public bool ValidateUser(string Username)
{
using (SqlConnection con = new
SqlConnection(ConfigurationManager.ConnectionStrings["DBconnection"].ConnectionString))
{
con.Open();
var param = new DynamicParameters();
param.Add("@Username", Username);
var result = con.Query
Ohh till now we have completed RegistrationConcrete implementation lets finally complete with business layer implementation.
Adding class RegistrationBL in SmartWebApp.BL
We are going to add RegistrationBL class in [SmartWebApp.BL] project
For Adding RegistrationBL class just right click on SmartWebApp.BL project then select add à class and name class as RegistrationBL.
Fig 14. Snapshot after adding RegistrationBL
Code snippet of RegistrationBL class
using SmartWebApp.Interface;
using SmartWebApp.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SmartWebApp.BL
{
public class RegistrationBL
{
IRegistration _IRegistration;
public RegistrationBL(IRegistration IRegistration)
{
_IRegistration = IRegistration;
}
public int CreateUser(Registration registration)
{
return _IRegistration.CreateUser(registration);
}
public bool ValidateUser(string Username)
{
return _IRegistration.ValidateUser(Username);
}
}
}
The RegistrationBL class has a constructor which is going to receive a concrete object from the controller and this method will call a concrete class from here.
Wows we have completed a small cycle of implementation now let’s make a change in RegisterController which we have added earlier.
Doing Changes in Register Controller
Code snippet of Register Controller
using SmartWebApp.BL;
using SmartWebApp.Concrete;
using SmartWebApp.CryptoLib;
using SmartWebApp.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace SmartWebApp.Controllers
{
public class RegisterController : Controller
{
RegistrationBL _RegistrationBL;
public RegisterController()
{
_RegistrationBL = new RegistrationBL(new RegistrationConcrete());
}
[HttpGet]
public ActionResult NewUser()
{
return View();
}
[HttpPost]
public ActionResult NewUser(Registration Registration)
{
if (ModelState.IsValid)
{
Registration.Password = EncryptandDecryptAES.Encrypt(Registration.Password);
_RegistrationBL.CreateUser(Registration);
TempData["Message"] = "Registration Done Successfully";
return RedirectToAction("NewUser", "Register");
}
else
{
return View(Registration);
}
}
public JsonResult ValidateUser(string Username)
{
if (Request.IsAjaxRequest())
{
var result = _RegistrationBL.ValidateUser(Username);
return Json(result, JsonRequestBehavior.AllowGet);
}
else
{
return Json("Failed", JsonRequestBehavior.AllowGet);
}
}
}
}
If you check RegisterController properly you will see it has a constructor in that we are creating an object of business layer and passing a concrete class as parameter [RegistrationConcrete] to it.
RegistrationBL _RegistrationBL;
public RegisterController()
{
_RegistrationBL = new RegistrationBL(new RegistrationConcrete());
}
In next step we 2 action methods with name NewUser one handles [HttpGet] and other handles [HttpPost] request below is code snippet of it.
[HttpGet]
public ActionResult NewUser()
{
return View();
}
[HttpPost]
public ActionResult NewUser(Registration Registration)
{
if (ModelState.IsValid)
{
Registration.Password = EncryptandDecryptAES.Encrypt(Registration.Password);
_RegistrationBL.CreateUser(Registration);
TempData["Message"] = "Registration Done Successfully";
return RedirectToAction("NewUser", "Register");
}
else
{
return View(Registration);
}
}
When we post a form [Registration] model gets populated with data.
Next step we check is the model which is posted a valid or not if it is valid then we encrypt the password and send this Model to business layer to save in database else we return model back to View for showing error on View.
After understanding the working of 2 Action methods we have finally a single method in the controller is left which is ValidateUser it is used for doing remote validation.
Note: - Remote validation
In this remote validation, we check that user entering username is already exists in the database or not if it is there then it will show error message username already exists.
Code snippet of ValidateUser Action Method
public JsonResult ValidateUser(string Username)
{
if (Request.IsAjaxRequest())
{
var result = _RegistrationBL.ValidateUser(Username);
return Json(result, JsonRequestBehavior.AllowGet);
}
else
{
return Json("Failed", JsonRequestBehavior.AllowGet);
}
}
Remote validation is applied on Model properties.
[Remote("ValidateUser", "Register", ErrorMessage = "Username Already Exists")]
public string Username { get; set; }
Using AES algorithm for securing password
Here for security we are storing password in database in encrypted format use Advanced Encryption Standard (AES) algorithm.
Adding View NewUser
For adding View just right inside [NewUser] Action Method and from List select Add View after selecting Add View a new dialog of Add View will pop up.
The name of the view is the same name as that of Action Method we are not going to make a change in it. After that we are going select View engine that’s Razor .then we are going to create a strong type View for that we are going to select Model [Registration] and in Scaffold template we are going to select Empty template.
If you want layout then check the given option. Finally, click on Add button.
This view will get added in View Folder inside that there will a folder with the name of controller [Register] inside that this view will be placed.
Code snippet of NewUser View
@model SmartWebApp.Model.Registration
@{
ViewBag.Title = "NewUser";
}
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<div class="container">
<br />
<div class="row">
<div class="col-md-3">
@Html.LabelFor(model => model.FirstName)
@Html.TextBoxFor(model => model.FirstName, new { @class = "form-control", autocomplete =
"off" })
@Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="col-md-3">
@Html.LabelFor(model => model.Lastname)
@Html.TextBoxFor(model => model.Lastname, new { @class = "form-control", autocomplete =
"off" })
@Html.ValidationMessageFor(model => model.Lastname)
</div>
<div class="col-md-3">
@Html.LabelFor(model => model.Gender)
@Html.RadioButtonFor(model => model.Gender, "M")@Html.Label("Male")
@Html.RadioButtonFor(model => model.Gender, "F")@Html.Label("Female")
@Html.ValidationMessageFor(model => model.Gender)
</div>
<div class="col-md-3">
@Html.LabelFor(model => model.Username)
@Html.TextBoxFor(model => model.Username, new { @class = "form-control", autocomplete =
"off" })
@Html.ValidationMessageFor(model => model.Username)
</div>
</div>
<div class="row">
<div class="col-md-3">
@Html.LabelFor(model => model.Password)
@Html.PasswordFor(model => model.Password, new { @class = "form-control", autocomplete =
"off" })
@Html.ValidationMessageFor(model => model.Password)
</div>
<div class="col-md-3">
@Html.LabelFor(model => model.ConfirmPassword)
@Html.PasswordFor(model => model.ConfirmPassword, new { @class = "form-control", autocomplete =
"off" })
@Html.ValidationMessageFor(model => model.ConfirmPassword)
</div>
<div class="col-md-3">
@Html.LabelFor(model => model.Mobileno)
@Html.TextBoxFor(model => model.Mobileno, new { @class = "form-control", autocomplete =
"off" })
@Html.ValidationMessageFor(model => model.Mobileno)
</div>
<div class="col-md-3">
@Html.LabelFor(model => model.EmailID)
@Html.TextBoxFor(model => model.EmailID, new { @class = "form-control", autocomplete =
"off" })
@Html.ValidationMessageFor(model => model.EmailID)
</div>
</div>
<br />
<div class="row">
<div class="col-md-3">
<input type="submit" class="btn btn-success" value="Register" />
</div>
</div>
<br />
@if (TempData["Message"] != "" && TempData["Message"] != null)
{
<div class="row">
<div class="col-md-6">
@TempData["Message"]
<br />
Click Here to Login :- @Html.ActionLink("Login", "Users", "Login")
</div>
</div>
}
</div>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Finally, save your application and run.
Snapshot before Registering a User
Fig 15. Snapshot before Registering a User
Snapshot after registering User
Fig 16. Snapshot after Registering a User
After inserting data in Client Registration table.
Fig 17. Snapshot of Client Registration table after registering user
After completed with registering user now let’s move forward to create a Login page.
Adding Login model
Login model contains 2 properties Username and password.
And another model is used for getting data as a response after login.
Code snippet of Login Model
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Web.Mvc;
namespace SmartWebApp.Model
{
public class LoginViewModel
{
[Required(ErrorMessage = "Enter Username ")]
[StringLength(30)]
public string Username { get; set; }
[Required(ErrorMessage = "Enter Password")]
[StringLength(30)]
[DataType(DataType.Password)]
public string Password { get; set; }
}
public class LoginViewResponse
{
public string Username { get; set; }
public string Password { get; set; }
public string RegistrationID { get; set; }
}
}
After adding model let’s start with adding ILogin Interface it is similar as we have added register Interface we just need to follow same steps.
Adding ILogin interface
This interface contains only one method which is ValidateLoginUser method which takes 2 parameters as input
Fig 18. Snapshot after Adding ILogin interface
Code snippet of ILogin Interface
using SmartWebApp.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SmartWebApp.Interface
{
public interface ILogin
{
LoginViewResponse ValidateLoginUser(string Username, string Password);
}
}
After adding model let’s start with adding LoginConcrete class it is similar as we added register concrete we just need to follow same steps.
Adding LoginConcrete
This LoginConcrete class will inherit interface ILogin.
Fig 19. Snapshot after Adding LoginConcrete class
Code snippet of LoginConcrete class
using Dapper;
using SmartWebApp.Interface;
using SmartWebApp.Model;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
namespace SmartWebApp.Concrete
{
public class LoginConcrete : ILogin
{
public LoginViewResponse ValidateLoginUser(string Username, string Password)
{
using (SqlConnection con = new
SqlConnection(ConfigurationManager.ConnectionStrings["DBconnection"].ConnectionString))
{
con.Open();
var param = new DynamicParameters();
param.Add("@Username", Username);
param.Add("@Password", Password);
var result = con.Query
After adding LoginConcrete class next we are going to add business layer LoginBL.
Adding LoginBL
This LoginBL class has a constructor which is going to receive a concrete object from the controller and this method will call concrete class [LoginConcrete] from here.
Fig 20. Snapshot after Adding LoginBL class
Code snippet of LoginBL class
using SmartWebApp.Interface;
using SmartWebApp.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SmartWebApp.BL
{
public class LoginBL
{
ILogin _ILogin;
public LoginBL(ILogin ILogin)
{
_ILogin = ILogin;
}
public LoginViewResponse ValidateLoginUser(string Username, string Password)
{
return _ILogin.ValidateLoginUser(Username, Password);
}
}
}
After adding LoginBL class next we are going to add LoginController.
Adding LoginController
For Adding Login Controller Just Right click on Controller Folder inside that select Add and then select Controller , After clicking on Controller new dialog will pop up with name Add Controller. In this Dialog to add Controller we are not going to make any change just click on Add button to add a Controller with name “Login Controller”.
Fig 21. Snapshot after Adding LoginController
After adding controller, I have changed action method name to Users.
Code snippet of Login Controller
using SmartWebApp.BL;
using SmartWebApp.Concrete;
using SmartWebApp.CryptoLib;
using SmartWebApp.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace SmartWebApp.Controllers
{
public class LoginController : Controller
{
LoginBL LoginBL;
public LoginController()
{
LoginBL = new LoginBL(new LoginConcrete());
}
[HttpGet]
public ActionResult Users()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Users(LoginViewModel LoginViewModel)
{
if (ModelState.IsValid)
{
string password = EncryptandDecryptAES.Encrypt(LoginViewModel.Password);
var val = LoginBL.ValidateLoginUser(LoginViewModel.Username, password);
if (val.RegistrationID == null)
{
Session["UserToken"] = string.Empty;
TempData["Message"] = "Invalid Username and Password.";
return RedirectToAction("Users", "Login");
}
else
{
Session["UserToken"] = val.RegistrationID;
return RedirectToAction("Home", "Dashboard");
}
}
return View("Users", LoginViewModel);
}
[HttpGet]
public ActionResult Logout()
{
Session.Abandon();
return RedirectToAction("Users", "Login");
}
}
}
After making changes in action method name let’s understand action method one by one.
The [HttpGet] action gets called when we first request for a page and in return, it will return View.
Fig 22. Snapshot of Login page
After login screen appears the user will enter username and password and click on login button at this time it will call HTTP post method.
First, step after posting form we are going to check ModelState.IsValid is valid or not if it is not valid then we show error message, and if it is valid then we are going to encrypt password and then pass it to ValidateLoginUser method to check the user entered credentials is valid or not if not then we are going to show error message “Invalid Username and Password” and if it is valid then we are going to redirect it dashboard page which we have not created will show in upcoming steps.
Now we have completed with understanding Login page next we are going to create a product model.
We are creating product model to receive data from window application and then deserialize JSON data and map to model.
Code snippet of Product Model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SmartWebApp.Model
{
public class Product
{
public int ProductID { get; set; }
public string ProductNumber { get; set; }
public string Name { get; set; }
public string Color { get; set; }
public string ProductClass { get; set; }
public decimal Price { get; set; }
public string Description { get; set; }
public DateTime CreatedDate { get; set; }
public string CLientIDToken { get; set; }
}
}
After adding product model next we are going to add IProduct in it will have a method to insert product in the database and get a list of product to display on the dashboard.
Adding IProduct interface
In this interface, we are going to declare 2 methods one for inserting product and other for getting a list of product.
Code snippet of IProduct Interface
using SmartWebApp.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SmartWebApp.Interface
{
public interface IProduct
{
int InsertProduct(Product product);
List
After adding product model next we are going to add ProductConcrete in it will have a method to insert product in the database and get a list of product to display on the dashboard.
Adding ProductConcrete Class
This class contains all code related to inserting data in product table and retrieving data from it.
Code snippet of ProductConcrete Class
using Dapper;
using SmartWebApp.Interface;
using SmartWebApp.Model;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
namespace SmartWebApp.Concrete
{
public class ProductConcrete : IProduct
{
public int InsertProduct(Product product)
{
try
{
using (SqlConnection con = new
SqlConnection(ConfigurationManager.ConnectionStrings["DBconnection"].ConnectionString))
{
con.Open();
SqlTransaction sqltans = con.BeginTransaction();
var param = new DynamicParameters();
param.Add("@ProductID", product.ProductID);
param.Add("@ProductNumber", product.ProductNumber);
param.Add("@Name", product.Name);
param.Add("@Color", product.Color);
param.Add("@ProductClass", product.ProductClass);
param.Add("@Price", product.Price);
param.Add("@Description", product.Description);
param.Add("@CreatedDate", product.CreatedDate);
param.Add("@CLientIDToken", product.CLientIDToken);
var result = con.Execute("sprocProductTBInsertUpdateSingleItem",
param,
sqltans,
0,
commandType: CommandType.StoredProcedure);
if (result > 0)
{
sqltans.Commit();
}
else
{
sqltans.Rollback();
}
return result;
}
}
catch (Exception)
{
throw;
}
}
public List<Product> ListProduct()
{
using (SqlConnection con = new
SqlConnection(ConfigurationManager.ConnectionStrings["DBconnection"].ConnectionString))
{
con.Open();
return con.Query<Product>("sprocProductTBSelectList", null, null, false, 0, commandType:
CommandType.StoredProcedure).ToList();
}
}
}
}
After adding ProductConcrete next step we are going to add ProductBL
Adding ProductBL Class
Code snippet of ProductBL Class
using SmartWebApp.Interface;
using SmartWebApp.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SmartWebApp.BL
{
public class ProductBL
{
IProduct _IProduct;
public ProductBL(IProduct IProduct)
{
_IProduct = IProduct;
}
public int InsertProduct(Product product)
{
return _IProduct.InsertProduct(product);
}
public List
After adding ProductBL next step we are going to add a Web API with name “product”.
Adding Web API
For Adding Web API Just Right click on Controller Folder inside that select Add and then select Controller, after clicking on Controller new dialog will pop up with name Add Controller.
In this Dialog to add API Controller we are going to choose a template as “API controller with empty read/write actions” and then name controller as ProductController and finally just click on Add button to add an API Controller .
Fig 23. Snapshot after adding Product WEB API
Processing of Web API and encryption and decryption of it
After adding Web API we are only going to work on Post method of it because windows application is going to consume this API and send product data in encrypted format.
For doing Encryption and Decryption we are going to use TripleDES algorithm and we are going to share [key ,IV] to windows application to send data in Encrypted format.
This algorithm is added in CryptoLib folder of the solution.
Code snippet of encryption and decryption algorithm
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
namespace SmartWebApp.CryptoLib
{
public static class EncryptionDecryptorTripleDES
{
public static byte[] Encryption(string PlainText, string key, string IV)
{
TripleDES des = CreateDES(key, IV);
ICryptoTransform ct = des.CreateEncryptor();
byte[] input = Encoding.Unicode.GetBytes(PlainText);
return ct.TransformFinalBlock(input, 0, input.Length);
}
public static string Decryption(string CypherText, string key, string IV)
{
byte[] b = Convert.FromBase64String(CypherText);
TripleDES des = CreateDES(key, IV);
ICryptoTransform ct = des.CreateDecryptor();
byte[] output = ct.TransformFinalBlock(b, 0, b.Length);
return Encoding.Unicode.GetString(output);
}
static TripleDES CreateDES(string key, string IV)
{
MD5 md5 = new MD5CryptoServiceProvider();
TripleDES des = new TripleDESCryptoServiceProvider();
des.Key = md5.ComputeHash(Encoding.Unicode.GetBytes(key));
des.IV = Encoding.ASCII.GetBytes(IV);
return des;
}
}
}
After having look on code snippet of CryptoLib, next, we are going to have look on Key and IV stored in web.config file.
Code snippet of key and IV used for encryption and decryption
<appSettings>
<add key="webpages:Version" value="2.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="keyValue" value="18694440" />
<add key="IVValue" value="BFA3EO5T" />
<add key="APIKEY" value="QbOsqf3LZAefzwwSBKHX" />
</appSettings>
Till here we have completed with setting key next we are going see code snippet of ProductController Web API.
Code snippet of ProductController
In this code snippet, we are going to receive data in request parameter from windows application and further Decrypt that data and then deserialize it and cast it to object and insert data in the database.
using SmartWebApp.BL;
using SmartWebApp.Concrete;
using SmartWebApp.CryptoLib;
using SmartWebApp.Filters;
using SmartWebApp.Model;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Script.Serialization;
namespace SmartWebApp.Controllers
{
public class ProductController : ApiController
{
ProductBL ProductBL;
string keyValue = ConfigurationManager.AppSettings["keyValue"].ToString();
string IVValue = ConfigurationManager.AppSettings["IVValue"].ToString();
public ProductController()
{
ProductBL = new ProductBL(new ProductConcrete());
}
[AuthoriseAPI]
public HttpResponseMessage Post(HttpRequestMessage Request)
{
try
{
var Responsedata = Request.Content.ReadAsStringAsync().Result;
string data = EncryptionDecryptorTripleDES.Decryption(Responsedata, keyValue, IVValue);
Product objpro = new JavaScriptSerializer().Deserialize
After you saw code snippet of API we have added security in data encryption and decryption and along with that we also have created token based security to add extra layer of security in this process.
Creating AuthoriseAPI Attribute
For doing this I have added AuthorizeAttribute and along with that we also share an APIKEY to windows application and in every request, this key must be present. If it is not there then it is an unauthorized user or client.
We are going to add this Attribute in filters folder.
For adding Filter just right click on filter folder and then select Add à inside that select Class and then name it as AuthoriseAPI, and then inherit with AuthorizeAttribute.
Fig 24. Snapshot after adding AuthoriseAPI Filter
Code snippet of AuthoriseAPI Attribute
using SmartWebApp.CryptoLib;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
namespace SmartWebApp.Filters
{
public class AuthoriseAPI : AuthorizeAttribute
{
protected override bool IsAuthorized(HttpActionContext actionContext)
{
try
{
string keyValue = ConfigurationManager.AppSettings["keyValue"].ToString();
string IVValue = ConfigurationManager.AppSettings["IVValue"].ToString();
string SmartWeb_APIKEY = ConfigurationManager.AppSettings["APIKEY"].ToString();
IEnumerable
After you saw AuthoriseAPI code snippet
First thing for working this attribute is to set the key in appSettings.
<add key="APIKEY" value="QbOsqf3LZAefzwwSBKHX" />
After setting this key further, we are going to place this attribute on top of ProductController Post method.
Fig 25. Snapshot of Post method of Product Web API
Explaining Code snippet of AuthoriseAPI
AuthoriseAPI attribute will get called before POST action method execution, in this attribute we are going to check token with name APIKEY after that we are going to convert token into FromBase64String then we are going to split it into parts { : } using a colon after splitting we receiving 2 hash values.
string tokens = tokenHeaders.First();
string key = Encoding.UTF8.GetString(Convert.FromBase64String(tokens));
string[] parts = key.Split(new char[] { ':' });
string Windows_APIKEY = parts[0];
string hash2 = parts[1];
string DecryHash1 = EncryptionDecryptorTripleDES.Decryption(hash2, keyValue, IVValue);
string[] datapart = DecryHash1.Split(new char[] { ':' });
string username = datapart[0];
long ticks = long.Parse(datapart[1]);
This hash value is in the encrypted format we need to decrypt it using same key and VI which we have stored in web.config file.
After decryption, you first hash you will find APIKEY and in the second hash you will find Username and Ticks.
First, we compare the date time which we have received from token with the current date of the system if it matches then only we decrypt APIKEY.
And match against key which we have in the web.config file if it gets a match then only we allow to access Web API else error message is shown to user “Not Valid Client!”.
DateTime currentdate = new DateTime(ticks);
if (currentdate.Date == DateTime.Now.Date)
{
string DecryAPIKEY = EncryptionDecryptorTripleDES.Decryption(Windows_APIKEY, keyValue, IVValue);
if (string.Equals(DecryAPIKEY, SmartWeb_APIKEY, comparisonType: StringComparison.InvariantCulture) ==
true)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
After completing with understanding whole stuff next we are further moving to words creating a dashboard where the user can see all data which is sync from windows application on daily basis.
Adding dashboard
For Adding dashboard, we are going to add a controller with name Dashboard and show all product data on that page.
Hmm, we need to show a collection of products right here I am going to use Grid.MVC tool for displaying data.
It is simple to add it from Nuget package manager.
Just type Grid.MVC and click on install button to install.
Fig 26. Installing Grid.MVC package from NuGet
Code snippet of Dashboard controller
We are going to send a list of product to view and on view are just going to bind data to grid view [Grid.MVC].
using SmartWebApp.BL;
using SmartWebApp.Concrete;
using SmartWebApp.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace SmartWebApp.Controllers
{
[AuthenticateUser]
public class DashboardController : Controller
{
ProductBL ProductBL;
public DashboardController()
{
ProductBL = new ProductBL(new ProductConcrete());
}
[HttpGet]
public ActionResult Home()
{
var data = ProductBL.ListProduct();
return View(data);
}
}
}
After creating dashboard lets have look on it how it is displayed.
Fig 27. Installing Grid.MVC package from NuGet
Now we have completed with dashboard part let’s move further to understand another WEB API which is used for authentication.
Creating Authenticate User API
For adding API we need to follow the same step which we have done for adding product API and just we are going to name it as AuthenticateUser.
Fig 28. Snapshot after adding AuthenticateUser Controller
Working of AuthenticateUser API
The work of this API is to just check user passed credentials is valid or not.
This data is passed from windows application it sends Username and Password in encrypted format first we need to decrypt the Deserialize and then finally send to ValidateLoginUser method to check credentials if it is valid then we send data back as a response to consumer [windows application] of WEBAPI in response we send same user details .
Below is json response which is returned.
{
"Username":"saineshwar",
"Password":"et3HqIkdUefzPl+lbxhPeQ==",
"RegistrationID":"1"
}
Code snippet of AuthenticateUser controller
using Newtonsoft.Json;
using SmartWebApp.BL;
using SmartWebApp.Concrete;
using SmartWebApp.CryptoLib;
using SmartWebApp.Filters;
using SmartWebApp.Model;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Script.Serialization;
namespace SmartWebApp.Controllers
{
public class AuthenticateUserController : ApiController
{
LoginBL LoginBL;
public AuthenticateUserController()
{
LoginBL = new LoginBL(new LoginConcrete());
}
[AuthoriseAPI]
public string Post(HttpRequestMessage Request)
{
if (Request != null)
{
var Responsedata = Request.Content.ReadAsStringAsync().Result;
string keyValue = ConfigurationManager.AppSettings["keyValue"].ToString();
string IVValue = ConfigurationManager.AppSettings["IVValue"].ToString();
string data = EncryptionDecryptorTripleDES.Decryption(Responsedata, keyValue, IVValue);
LoginViewModel objVM = new JavaScriptSerializer().Deserialize
After understanding AuthenticateUser API we are further going to add ActionFilter Attribute to authenticate whether the user is logged in to access pages.
For adding Filter just right click on filter folder and then select Add à inside that select Class and then name it as AuthenticateUser , and then inherit with FilterAttribute, IActionFilter.
Fig 29. Snapshot after creating AuthenticateUser Filter
If you have gone through Login code snippet, when user enters valid login and password in response we get [Username, Password, and RegistrationID] we store RegistrationID in session.
Session["UserToken"] = val.RegistrationID;
And this session will be a check inside Action Filter Attribute if it is Null or not if it is Null then we are going to redirect it to Login page.
If it is not null then we are not going to do anything.
Code snippet of AuthenticateUser controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace SmartWebApp.Filters
{
public class AuthenticateUser : FilterAttribute, IActionFilter
{
public void OnActionExecuted(ActionExecutedContext filterContext)
{
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Session["UserToken"] == null)
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new
{
action = "Users",
controller = "Login"
}));
}
}
}
}
Applying AuthenticateUser attributes on Dashboard controller
After creating AuthenticateUser attribute next, we are going to apply it on Dashboard controller such that only authenticated user are allowed to use it.
Fig 30. Snapshot after applying AuthenticateUser attribute on Dashboard controller
Finally, we have completely with SmartWebAPP let’s have look on project structure how it looks.
Complete project structure of SmartWebAPP
Fig 31. Snapshot of completed project structure
Login page
Fig 32. Snapshot of Login view
Dashboard
Fig 33. Snapshot of dashboard view
After completing with web application now let’s start with creating windows form application [Client]
Creating Windows Application [DemoSmartClient]
Before starting with the Creating new project structure lets’s have look on basic idea how is it working and you will be clear to understand rest part easily.
Here we are going to create a windows application this application works online and offline you may think what is online and offline right, it means when we have internet connection that time it will be online and when it is offline means we do not have internet connection, when we do not internet connection at that time we are going save data in local database of application which is [SQLite db] and as we get internet connection we are going to sync data from local database to web application [web server] and delete records from local storage [SQLite db] one by one as we send data and get response , and another important point to note is we are going also secure the data travel between web server and local application by use TripleDES algorithm along with token base security for API.
Fig 1. Working of web and windows application
Creating Windows form Application
Let’s begin with creating a windows form application.
Open visual studio IDE from start page click on new project link a new dialog will pop up with name new project, after that from left panel select Templates à inside that windows and finally in middle panel select “Windows Forms Application” after that we are going to name your project as “DemoSmartClient”.
Fig 2. Creating Windows form application
And finally, click on OK button to create a project.
Implementing repository Pattern
We are going to follow the same step which we have seen while adding repository Pattern in a web application.
Fig 3. Implementing repository Pattern in Windows form application
After adding repository Pattern next step we are going to add SQLite database reference to [DemoSmartClient.Concrete] project from NuGet package manager.
Adding reference to SQLite database to DemoSmartClient.Concrete
For adding SQLite just right click on the project then select “Manage NuGet packages” a new dialog will pop up Manage NuGet packages than from left panel select online à then select All , after this, there is search online box available in right top , in that just type “SQLite” and select “System.Data.SQLite” and click on install button to install.
Fig 4. Installing SQLite in DemoSmartClient.Concrete project
After adding SQLite reference next we are going to create SQLite database and create a table.
Let start with creating database and tables
For doing this process in a manageable way I have created a special interface and class that will handle database management part.
Adding new interface IManageDB in DemoSmartClient.Interface
Adding new interface IManageDB in DemoSmartClient.Interface project and then declare methods in it.
Fig 5. Adding new interface IManageDB in DemoSmartClient.Interface project
Code snippet of IManageDB Interface
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DemoSmartClient.Interface
{
public interface IManageDB
{
void CreateSqlLiteDatabase();
void Changepassword();
void Setpassword();
void Removepassword();
void Createtbproduct();
void Createt_Login_Table();
}
}
Adding new class ManageDBConcrete in DemoSmartClient.Concrete
Adding new class ManageDBConcrete in DemoSmartClient.Concrete project and then implementing IManageDB interface.
Fig 6. Adding new Concrete class ManageDBConcrete in DemoSmartClient.Concrete project
Code snippet of ManageDBConcrete Class
using DemoSmartClient.Interface;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SQLite;
using System.Linq;
using System.Text;
namespace DemoSmartClient.Concrete
{
public class ManageDBConcrete : IManageDB
{
public void CreateSqlLiteDatabase()
{
SQLiteConnection.CreateFile("SmartData.db3");
}
public void Changepassword()
{
using (SQLiteConnection con = new
SQLiteConnection(ConfigurationManager.AppSettings["DBConnection"].ToString()))
{
con.Open();
con.ChangePassword("@@#DEMOSMART#@@");
}
}
public void Setpassword()
{
using (SQLiteConnection con = new
SQLiteConnection(ConfigurationManager.AppSettings["DBConnection"].ToString()))
{
con.SetPassword("@@#DEMOSMART#@@");
}
}
public void Removepassword()
{
using (SQLiteConnection con = new
SQLiteConnection(ConfigurationManager.AppSettings["DBConnection"].ToString()))
{
con.SetPassword("@@#DEMOSMART#@@");
con.Open();
con.ChangePassword("");
}
}
public void Createtbproduct()
{
try
{
using (SQLiteConnection con = new
SQLiteConnection(ConfigurationManager.AppSettings["DBConnection"].ToString()))
{
con.Open();
using (SQLiteCommand com = new SQLiteCommand(con))
{
string createTableQuery =
@"CREATE TABLE IF NOT EXISTS [ProductTB] (
[ProductID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[ProductNumber] NVARCHAR(2048) NULL,
[Name] VARCHAR(2048) NULL,
[Color] VARCHAR(2048) NULL,
[ProductClass] VARCHAR(2048) NULL,
[Price] Decimal(18,2) NULL,
[Description] VARCHAR(2048) NULL,
[CreatedDate] DateTime ,
[CLientIDToken] VARCHAR(2048) NULL
)";
com.CommandText = createTableQuery;
com.ExecuteNonQuery();
}
}
}
catch (Exception)
{
throw;
}
}
public void Createt_Login_Table()
{
using (SQLiteConnection con = new
SQLiteConnection(ConfigurationManager.AppSettings["DBConnection"].ToString()))
{
con.Open();
using (SQLiteCommand com = new SQLiteCommand(con))
{
string createTableQuery =
@"CREATE TABLE IF NOT EXISTS [LoginTB] (
[UserID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[Username] NVARCHAR(2048) NULL,
[Password] VARCHAR(2048) NULL,
[CLientIDToken] VARCHAR(2048) NULL
)";
com.CommandText = createTableQuery;
com.ExecuteNonQuery();
}
}
}
}
}
The first step we are going to create a database with name “SmartData.db3” after that we are going to create two tables [LoginTB, ProductTB] for storing data in it. And also we are going set a password to database for security propose.
In same way we are going to add new class ManageDBBL in DemoSmartClient.BL project
Adding new class ManageDBBL in DemoSmartClient.BL project
Fig 7. Adding new business class ManageDBBL in DemoSmartClient.BL project
Code snippet of ManageDBBL Class
using DemoSmartClient.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DemoSmartClient.BL
{
public class ManageDBBL
{
IManageDB _IManageDB;
public ManageDBBL(IManageDB IManageDB )
{
_IManageDB = IManageDB;
}
public void CreateSqlLiteDatabaseBL()
{
_IManageDB.CreateSqlLiteDatabase();
}
public void ChangepasswordBL()
{
_IManageDB.Changepassword();
}
public void SetpasswordBL()
{
_IManageDB.Setpassword();
}
public void RemovepasswordBL()
{
_IManageDB.Removepassword();
}
public void Createtbproduct()
{
_IManageDB.Createtbproduct();
}
public void Createt_Login_Table()
{
_IManageDB.Createt_Login_Table();
}
}
}
After adding this class we are going to call this method on the first start of the application to creating database and tables.
If you want to view how table’s structure look download SQLite browser
Then if you want to view how table’s structure look like after creating you can download SQLite browser from given URL http://sqlitebrowser.org/
Fig 8. SQLite Database browser view
After downloading install it and then choose a database which we have created.
Databases are located in main project folder [DemoSmartClient\DemoSmartClient\bin\Debug] folder.
Fig 9. SQLite Database is created in binà debug folder [SmartData.db3]
After that select database to view with SQLite browser as shown below and view table structure which we have created.
Fig 10. [SmartData.db3] database view with tables
Next step we are going to create Login page.
Before creating page lets create a repository for Login page first then we are going to call all these methods in the login page.
Adding UserLogin Model
First, we are going to add Model with name UserLogin and add some properties to it.
Code snippet of UserLogin Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DemoSmartClient.Model
{
public class UserLogin
{
public int UserID { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string RegistrationID { get; set; }
}
}
Fig 11. Snapshot after adding UserLogin Class in DemoSmartClient.Model Project
Adding ILogin Interface
After adding Model next we are going to add Interface with name ILogin.
Inside this model, we are going to declare a method which is going to be implementing by LoginConcrete class.
Code snippet of ILogin Interface
using DemoSmartClient.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DemoSmartClient.Interface
{
public interface ILogin
{
string CheckUserExists(string Username, string Password);
int InsertLoginData(UserLogin LoginModel);
}
}
This interface contains 2 methods.
- CheckUserExists method is used for checking the user is already exists in SQLite database or not.
- InsertLoginData method inserting data in LoginTB table.
Adding LoginConcrete Class
LoginConcrete class will inherit ILogin interface
Fig 12. Snapshot after adding LoginConcrete Class in DemoSmartClient.Concrete Project
Code snippet of LoginConcrete Class
using DemoSmartClient.Interface;
using DemoSmartClient.Model;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SQLite;
using System.Linq;
using System.Text;
using System.Data;
namespace DemoSmartClient.Concrete
{
public class LoginConcrete : ILogin
{
public string CheckUserExists(string Username, string Password)
{
string result = string.Empty;
DataSet ds = new DataSet();
using (SQLiteConnection con = new
SQLiteConnection(ConfigurationManager.AppSettings["DBConnection"].ToString()))
{
con.SetPassword("@@#DEMOSMART#@@");
con.Open();
using (SQLiteCommand com = new SQLiteCommand(con))
{
try
{
com.CommandText = "select CLientIDToken from logintb Where Username='" + Username +
"'and Password='" + Password + "'";
com.CommandType = CommandType.Text;
SQLiteDataAdapter da = new SQLiteDataAdapter();
da.SelectCommand = com;
da.Fill(ds);
if (ds != null)
{
if (ds.Tables[0].Rows.Count > 0)
{
result = Convert.ToString(ds.Tables[0].Rows[0]["CLientIDToken"]);
}
}
}
catch (Exception)
{
throw;
}
finally
{
ds.Dispose();
}
}
}
return result;
}
public int InsertLoginData(UserLogin LoginModel)
{
try
{
using (SQLiteConnection con = new
SQLiteConnection(ConfigurationManager.AppSettings["DBConnection"].ToString()))
{
con.SetPassword("@@#DEMOSMART#@@");
con.Open();
using (SQLiteCommand com = new SQLiteCommand(con))
{
string SQLQuery = "insert into LoginTB (Username,Password,CLientIDToken) values ('"
+ LoginModel.Username + "','" + LoginModel.Password + "','" + LoginModel.RegistrationID + "')";
com.CommandText = SQLQuery;
return com.ExecuteNonQuery();
}
}
}
catch (Exception)
{
throw;
}
}
}
}
After completing with understanding login concrete code let’s move forward to add a class that glue interface and concrete together LoginBL
Adding LoginBL Class
Fig 13. Snapshot after adding LoginBL Class in DemoSmartClient.BL Project
Code snippet of LoginBL Class
using DemoSmartClient.Interface;
using DemoSmartClient.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DemoSmartClient.BL
{
public class LoginBL
{
ILogin _ILogin;
public LoginBL(ILogin ILogin)
{
_ILogin = ILogin;
}
public string CheckUserExists(string Username, string Password)
{
return _ILogin.CheckUserExists(Username, Password);
}
public int InsertLoginData(UserLogin LoginModel)
{
return _ILogin.InsertLoginData(LoginModel);
}
}
}
After completing with adding LoginBL class code let’s move forward to design login page and use this method in it.
Adding and Designing Login form
We are going to add new Windows form and going to name it as “Login.cs”
Login form has only 2 text controls and a button on it.
Fig 14. Adding and designing new Login form
Fig 15. Controls on Login form
After design form next we are going to write code for checking internet connection and also for displaying Internet Connection indicator.
Adding CheckInternetConnection class
For checking internet connection I have created a static class with name CheckInternetConnection and it is added in new folder with name CommonLib.
Fig 16. Adding new class with name CheckInternetConnection in CommonLib folder
Code snippet of CheckInternetConnection Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DemoSmartClient.CommonLib
{
public static class CheckInternetConnection
{
[System.Runtime.InteropServices.DllImport("wininet.dll")]
private extern static bool InternetGetConnectedState(out int Description, int ReservedValue);
public static bool CheckNet()
{
int desc;
return InternetGetConnectedState(out desc, 0);
}
}
}
This class will return a Boolean value true or false if internet connection is available then it will return true else it will return false.
After understanding internet connection checker class next we are going to display Internet Connection indicator.
Working of Internet Connection indicator
I have added 2 images one above the other
After adding images we are going to use timer controls for checking internet connection and show indicator.
Adding Timer control on Form for check Internet Connection and displaying Internet Connection indicator
Fig 18. Adding Timer control for check Internet Connection and displaying Internet Connection indicator
Meanwhile we are also setting a static variable which is too used in an entire application for checking internet connection.
Code snippet of NetConnectionChecker
public static class NetConnectionChecker
{
private static bool _Connection;
public static bool Connection
{
get { return _Connection; }
set { _Connection = value; }
}
}
After adding static class next we are going to use connection Timer tick event to display Internet Connection indicator.
Code snippet of Timer ticks event
In this event we check internet connection is available or not and according to this we display image indicator, if internet connection is not there then it will display red image and if internet connection is there then it will display green image.
private void TM1_Tick(object sender, EventArgs e)
{
if (CheckInternetConnection.CheckNet() == true)
{
PBimgRed.Visible = false;
NetConnectionChecker.Connection = true;
if (PBimggreen.Visible == true)
{
PBimggreen.Visible = false;
}
else
{
PBimggreen.Visible = true;
}
}
else
{
NetConnectionChecker.Connection = false;
PBimggreen.Visible = false;
if (PBimgRed.Visible == true)
{
PBimgRed.Visible = false;
}
else
{
PBimgRed.Visible = true;
}
}
}
Fig 19. Displaying Internet Connection indicator when online it shows green light and when offline it show red light
Next we are going to authenticate user.
Authenticate user process with code snippet below
When user enter username and password then click on login button first we are going to check it is not empty, after that we are going to Encrypt password using AES algorithm and pass it to CheckUserExists method to check this value exists in SQLite database or not , if not then we are going to Validate User directly from web server using WEB API [http://localhost:6778/api/authenticateuser] if passed credentials are there on server then in response we are going to get Username and password as response from this WEB API which is Encrypt format we then decrypt this values and again we check against database are this value exists if not then we insert response which we get from API, once these values are inserted in SQLite database now we can validate user when he is offline against SQLite database and allow to do this work
Code snippet of login button
private void BtnLogin_Click(object sender, EventArgs e)
{
try
{
if (txtusername.Text == "")
{
MessageBox.Show("Enter Username");
}
else if (txtpassword.Text == "")
{
MessageBox.Show("Enter Password");
}
else
{
string Username = txtusername.Text;
string Password = txtpassword.Text;
var result = LoginBL.CheckUserExists(Username, EncryptandDecryptAES.Encrypt(Password));
if (string.IsNullOrEmpty(result) && NetConnectionChecker.Connection == false)
{
MessageBox.Show("Login Cannot be done need internet Connection");
}
else if (string.IsNullOrEmpty(result) && NetConnectionChecker.Connection == true)
{
ValidateUserandGetResponse(Username, Password);
}
else
{
ShareObject.CLientIDToken = result;
ShareObject.Username = Username;
MessageBox.Show("Login Successfully");
this.Hide();
Login frm1 = new Login();
frm1.Close();
AddProduct addpro = new AddProduct();
addpro.Show();
}
}
}
catch (Exception)
{
throw;
}
}
Validating User Credentials with WEB API
To this method we are going to pass Username and Password, after that we are going to Encrypt password using AES algorithm and then we are going to use Web Client for calling WEB API for posting data but before that we are going to Encrypt entire object which we are going to send to web server, along with this we also have token based authentication for extra security [“APIKEY”] we generate token key and sent to web server and on web server it validate token key when is sent and then it will decrypt data sent and validate against SQL server on web server and in response we are going to get Username and password as response from this WEB API which is Encrypt format we then decrypt this values.
Code snippet of ValidateUserandGetResponse Method
public void ValidateUserandGetResponse(string Username, string Password)
{
try
{
UserLogin objvm = new UserLogin()
{
Username = Username,
Password = EncryptandDecryptAES.Encrypt(Password)
};
ShareObject.Username = Username;
using (var client = new WebClient())
{
string ClientToken = ConfigurationManager.AppSettings["CLientIDToken"].ToString();
string keyValue = ConfigurationManager.AppSettings["keyValue"].ToString();
string IVValue = ConfigurationManager.AppSettings["IVValue"].ToString();
Uri URI = new Uri(ConfigurationManager.AppSettings["LoginURI"].ToString());
client.Headers.Add("Content-Type:application/json");
client.Headers.Add("APIKEY", GenerateToken.CreateToken(Username, ClientToken, DateTime.Now.Ticks));
client.Headers.Add("Accept:application/json");
client.UploadStringCompleted += new UploadStringCompletedEventHandler(Callback);
string SerializeData = JsonConvert.SerializeObject(objvm);
byte[] buffer = EncryptionDecryptorTripleDES.Encryption(SerializeData, keyValue, IVValue);
client.UploadStringAsync(URI, Convert.ToBase64String(buffer));
}
}
catch (Exception)
{
throw;
}
}
Code snippet of callback method
This method gets called when we get a response from API and it is in encrypted form, first we need to decrypt it and then we are going to deserialize it than we get the final output as an object.
void Callback(object sender, UploadStringCompletedEventArgs e)
{
string ClientToken = ConfigurationManager.AppSettings["CLientIDToken"].ToString();
string keyValue = ConfigurationManager.AppSettings["keyValue"].ToString();
string IVValue = ConfigurationManager.AppSettings["IVValue"].ToString();
if (e.Error != null)
{
}
if (e.Result != null || !string.IsNullOrEmpty(e.Result))
{
string finalData = JToken.Parse(e.Result).ToString();
string data = EncryptionDecryptorTripleDES.Decryption(finalData, keyValue, IVValue);
UserLogin userlogin = JsonConvert.DeserializeObject
After completing with understanding code snippet now next we are going to move forward to create product model.
Adding product Model in DemoSmartClient.Model project
We are creating this model for send object to SQLite database to insert product in product table along with this we are using same product model [object] to send data to web server.
Fig 20. Adding product Model in DemoSmartClient.Model project
First, we are going to add Model with name Product
Code snippet of Product Model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DemoSmartClient.Model
{
public class Product
{
public int ProductID { get; set; }
public string ProductNumber { get; set; }
public string Name { get; set; }
public string Color { get; set; }
public string ProductClass { get; set; }
public decimal Price { get; set; }
public string Description { get; set; }
public DateTime CreatedDate { get; set; }
public string CLientIDToken { get; set; }
}
}
After adding Model next we are going to add Interface with name IProduct.
Adding IProduct Interface in DemoSmartClient.Interface project
In this interface, we are going to declare a method for inserting product, Get product data, deleting product data.
Fig 21. Adding IProduct Interface in DemoSmartClient.Interface project
Code snippet of IProduct Interface
using DemoSmartClient.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
namespace DemoSmartClient.Interface
{
public interface IProduct
{
bool AddProduct(Product Product);
DataTable GetData(string CLientIDToken);
bool DeleteProduct(int ProductID);
}
}
After adding interface next we are going to add ProductConcrete class.
Adding ProductConcrete Class in DemoSmartClient.Concrete project
ProductConcrete class will inherit IProduct interface.
In concrete class we write entire database accessing part in this class I have written code for the inserting product, getting the product, and delete a product.
Fig 22. Adding ProductConcrete Class in DemoSmartClient.Concrete project
Note: - I am using SQLiteDatabaseHelper class for doing CRUD operation I will provide this class with project source code.
Code snippet of ProductConcrete Class
using DemoSmartClient.Interface;
using DemoSmartClient.Model;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SQLite;
using System.Data;
namespace DemoSmartClient.Concrete
{
public class ProductConcrete : IProduct
{
SQLiteDatabaseHelper db;
public ProductConcrete()
{
db = new SQLiteDatabaseHelper();
}
public bool AddProduct(Product Product)
{
try
{
bool result = false;
Dictionary
After adding ProductConcrete class next we are going to add ProductBLin DemoSmartClient.BL project.
Adding ProductBL Class in DemoSmartClient.BL project
The business class just sits between the user interface and Repository pattern data class.
Fig 23. Adding ProductBL Class in DemoSmartClient.BL project
Code snippet of ProductBL Class
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
namespace DemoSmartClient.BL
{
public class ProductBL
{
IProduct _IProduct;
public ProductBL(IProduct IProduct)
{
_IProduct = IProduct;
}
public bool AddProduct(Product Product)
{
return _IProduct.AddProduct(Product);
}
public DataTable GetData(string CLientIDToken)
{
return _IProduct.GetData(CLientIDToken);
}
public bool DeleteProduct(int ProductID)
{
return _IProduct.DeleteProduct(ProductID);
}
}
}
After adding business layer next step, we are going to Create Add Product form.
Adding Product form
The Product form is used to collect data of the product and save in SQLite database and display records to the user as we add in DataGridView.
We have simply added some textbox controls and drop-down controls on the form with a pair of button and DataGridView for displaying data.
Meanwhile if you look to bottom of page we have added 2 components
- Timer
- BackgroundWorker
Here we have a timer on the page which is used for calling BackgroundWorker at a particular interval.
And work of BackgroundWorker is to push data to the web server using Web Client.
Fig 24. Product form view with all controls and components
After adding form and components next step we are going to do is save the product in the database.
Save product in SQLite database
If you look at below code snippet first we are validating controls if everything is valid then we are asking for confirmation “do you want to save data?” yes or no, if yes then we are saving data in database and same time we are getting that data from database and displaying it in DataGridView and finally resetting controls data after adding.
Code snippet of BtnSave button Event
private void BtnSave_Click(object sender, EventArgs e)
{
try
{
if (TxtProductNumber.Text == "")
{
MessageBox.Show("Enter Product Number");
TxtProductNumber.Focus();
}
else if (TxtProductName.Text == "")
{
MessageBox.Show("Enter Product Name");
TxtProductName.Focus();
}
else if (TxtPrice.Text == "")
{
MessageBox.Show("Enter Price");
TxtPrice.Focus();
}
else if (ComboColor.SelectedIndex == -1)
{
MessageBox.Show("Select Color");
ComboColor.Focus();
}
else if (ComboClass.SelectedIndex == -1)
{
MessageBox.Show("Select Class");
ComboClass.Focus();
}
else
{
string message = "Are you sure you want save this record";
if (MessageBox.Show(message, "confirmation", MessageBoxButtons.YesNo,
MessageBoxIcon.Information) == System.Windows.Forms.DialogResult.Yes)
{
string selectedComboColor = ComboColor.Items[ComboColor.SelectedIndex].ToString();
string selectedComboClass = ComboClass.Items[ComboClass.SelectedIndex].ToString();
Product objproduct = new Product();
objproduct.Color = selectedComboColor;
objproduct.Description = TxtDescription.Text;
objproduct.Name = TxtProductName.Text;
objproduct.Price = Convert.ToDecimal(TxtPrice.Text);
objproduct.ProductNumber = TxtProductNumber.Text;
objproduct.ProductClass = selectedComboClass;
objproduct.CreatedDate = DateTime.Now;
objproduct.CLientIDToken = ShareObject.CLientIDToken;
ProductBL.AddProduct(objproduct);
DGData.DataSource = ProductBL.GetData(ShareObject.CLientIDToken);
DGData.ReadOnly = true;
Clear();
}
}
}
catch (Exception)
{
throw;
}
}
Resetting controls code snippet
public void Clear()
{
TxtDescription.Text = string.Empty;
TxtProductName.Text = string.Empty;
TxtPrice.Text = string.Empty;
TxtProductNumber.Text = string.Empty;
ComboColor.SelectedIndex = -1;
ComboClass.SelectedIndex = -1;
}
After understanding code snippet of saving product next we are going to understand how to delete product from database.
Deleting product from database
For the deleting record, you need to select row which you want to delete in DataGridView and then click on delete button.
Fig 25. Deleting product from database
After that, it will ask for confirmation for deleting records yes / no if yes then it will get cell id of zeroth position which will be product id and then pass it to business layer for deleting it from the database, after deleting we are again going to rebind DataGridView.
Code snippet of btnDelete button Event
private void btnDelete_Click(object sender, EventArgs e)
{
try
{
string message = "Are you sure you want to delete this record(s)";
if (MessageBox.Show(message, "confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Information)
== System.Windows.Forms.DialogResult.Yes)
{
foreach (DataGridViewRow item in this.DGData.SelectedRows)
{
int productID = Convert.ToInt32(item.Cells[0].Value);
ProductBL.DeleteProduct(productID);
}
DGData.DataSource = ProductBL.GetData(ShareObject.CLientIDToken);
DGData.AllowUserToAddRows = false;
DGData.ReadOnly = true;
}
}
catch (Exception)
{
throw;
}
}
After understanding code snippet of the deleting product next we are going to understand how to Timer and BackgroundWorker are used to push data to web server.
Working of Timer and BackgroundWorker are used to push data to web server
Fig 26. Working of Timer and BackgroundWorker
Let’s start with timer first we are going to use timer tick event to call BackgroundWorker and we have set its interval to 60000 millisecond which is 1 minute after every 1 minute it is going to call BackgroundWorker RunWorkerAsync(); event .
Fig 27. Setting Properties and Events of Timer Control
Code snippet of Timer tick event
private void TMSyncData_Tick(object sender, EventArgs e)
{
BGWorkerDataPusher.RunWorkerAsync();
}
Next, we are going to see event and properties of BackgroundWorker which we are going to set.
Setting Properties and Event of BackgroundWorker
We are going to use this component for running task in the background. You might think which task we are going to run in the background, ha we are going to push data of the product to the web server in the background.
Fig 28. Setting Properties and Events of BackgroundWorker Control
Let’s see sequence of event execution of BackgroundWorker
The first event which gets invokes when RunWorkerAsync(); is called is DoWork then it is followed by ProgressChanged and at last RunWorkerCompleted event is called.
Code snippet of DoWork event
In this event we are going to check internet connection is available then only we are going to call method BackgroundProcessLogicMethod();
private void BGWorkerDataPusher_DoWork(object sender, DoWorkEventArgs e)
{
if (NetConnectionChecker.Connection == true)
{
BackgroundProcessLogicMethod();
}
}
In BackgroundProcessLogicMethod(); method we are going get data from database according to user and then assign values to product model and then passing product model to DataPusher(Product Product) method.
Code snippet of BackgroundProcessLogicMethod Method
public void BackgroundProcessLogicMethod()
{
var data = ProductBL.GetData(ShareObject.CLientIDToken);
for (int i = 0; i < data.Rows.Count; i++)
{
Product Product = new Product();
Product.ProductID = Convert.ToInt32(data.Rows[i]["ProductID"]);
Product.Name = Convert.ToString(data.Rows[i]["Name"]);
Product.Price = Convert.ToDecimal(data.Rows[i]["Price"]);
Product.Color = Convert.ToString(data.Rows[i]["Color"]);
Product.Description = Convert.ToString(data.Rows[i]["Description"]);
Product.ProductClass = Convert.ToString(data.Rows[i]["ProductClass"]);
Product.CreatedDate = Convert.ToDateTime(data.Rows[i]["CreatedDate"]);
Product.CLientIDToken = Convert.ToString(data.Rows[i]["CLientIDToken"]);
Product.ProductNumber = Convert.ToString(data.Rows[i]["ProductNumber"]);
DataPusher(Product);
if (data.Rows.Count > 0)
{
BGWorkerDataPusher.ReportProgress((data.Rows.Count * 10));
}
else
{
BGWorkerDataPusher.ReportProgress((10 * 10));
}
}
}
And in DataPusher method we are going use WebClient to call product WEBAPI which is created in SmartWebapp application, and then to pass data we first need to serialize product model which we are going to send and Encrypt serialize data along with this we are also going to send APIKEY from header which we have shared logic of generating APIKEY with SmartWebapp application for token based authentication.
he best to keep URL and token is appSettings in App.config.
Once we make changes here this is applied to the entire application.
In DataPusher method we are going to use 4 key [CLientIDToken, LiveURI, keyValue, IVValue]
<appSettings>
<add key="DBConnection" value="Data Source=SmartData.db3" />
<add key="keyValue" value="18694440" />
<add key="IVValue" value="BFA3EO5T" />
<add key="LiveURI" value="http://localhost:6778/api/product" />
<add key="LoginURI" value="http://localhost:6778/api/authenticateuser" />
<add key="CLientIDToken" value="QbOsqf3LZAefzwwSBKHX" />
</appSettings>
Code snippet of DataPusher Method
public void DataPusher(Product Product)
{
try
{
using (var client = new WebClient())
{
string ClientToken = ConfigurationManager.AppSettings["CLientIDToken"].ToString();
Uri URI = new Uri(ConfigurationManager.AppSettings["LiveURI"].ToString());
client.Headers.Add("Content-Type:application/json");
client.Headers.Add("Accept:application/json");
client.Headers.Add("APIKEY",
GenerateToken.CreateToken(ShareObject.Username, ClientToken, DateTime.Now.Ticks));
client.UploadStringCompleted += new UploadStringCompletedEventHandler(Callback);
string keyValue = ConfigurationManager.AppSettings["keyValue"].ToString();
string IVValue = ConfigurationManager.AppSettings["IVValue"].ToString();
string SerializeData = JsonConvert.SerializeObject(Product);
byte[] buffer = EncryptionDecryptorTripleDES.Encryption(SerializeData, keyValue, IVValue);
client.UploadStringAsync(URI, Convert.ToBase64String(buffer));
}
}
catch (Exception)
{
throw;
}
}
After passing all these values we are going to call UploadStringAsync method to upload data and to receive a response we have set Callback method below is callback method code snippet which receives an error if it is error and also response values if it’s not error.
In response, we receive ProductID which is inserted on the web server and according we delete that record from SQLite database.
Code snippet of Callback Method
void Callback(object sender, UploadStringCompletedEventArgs e)
{
try
{
if (e.Error != null)
{
}
else if (e.Result != null || !string.IsNullOrEmpty(e.Result))
{
string finalData = e.Result;
if (finalData != null)
{
ProductBL.DeleteProduct(Convert.ToInt32(finalData));
}
}
}
catch (Exception)
{
throw;
}
}
After this event the next event which is to be getting called is ProgressChanged.
ProgressChanged event
This event is used for displaying processing e.g. Progress Bar as data is sync to web server.
Fig 29. Used ProgressChanged event for displaying Progress bar
In below code snippet we are setting percentage to progress bar for displaying and also along with that we are also showing a label with percentage, and finally we are also refreshing grid for removing data which is sync to server.
Code snippet of BGWorker_ProgressChanged Event
void BGWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
try
{
progressBar1.Value = e.ProgressPercentage;
lblStatus.Text = "Processing......" + progressBar1.Value.ToString() + "%";
DGData.DataSource = null;
DGData.Update();
DGData.Refresh();
DGData.DataSource = ProductBL.GetData(ShareObject.CLientIDToken);
}
catch (Exception)
{
throw;
}
}
After this event final event which gets called is RunWorkerCompleted.
In RunWorkerCompleted event we refresh DataGridView and rebind data to DataGridView this is the last event which is called BackgroundWorker.
Code snippet of BGWorkerDataPusher_RunWorkerCompleted Event
private void BGWorkerDataPusher_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
DGData.DataSource = null;
DGData.Update();
DGData.Refresh();
DGData.DataSource = ProductBL.GetData(ShareObject.CLientIDToken);
}
Summary
We have learned a lot of things in this article we have learned how to create MVC project, how to Create WEB API, How to Secure WEB API along with that we have also learned new things in windows application using SQLite Database, Consume WEBAPI.
Thanks for reading Article will keep coming with new ideas and Articles.