Click here to Skip to main content
12,634,422 members (25,711 online)
Click here to Skip to main content
Add your own
alternative version

Stats

7K views
26 bookmarked
Posted

.Net application that works online and offline [Smart Client Concept]

, 3 Oct 2016 CPOL
Rate this:
Please Sign up or sign in to vote.
In this article, we are going learn to create an application that works online and offline.

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.

  1. Asp.net MVC web application
  2. 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
    {
        //
        // GET: /Login/
        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());
        }

    
        // POST api/product
        [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]; //Hash 1 (Received in API request)

string hash2 = parts[1]; //Hash 2

//Hash 2 Decryption
string DecryHash1 = EncryptionDecryptorTripleDES.Decryption(hash2, keyValue, IVValue);

//Spliting Values
string[] datapart = DecryHash1.Split(new char[] { ':' });

// 1) Hash 2 Contains Username
string username = datapart[0];

// 2) Hash 2 Contains Ticks
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);
//Comparing Current Date with date sent
if (currentdate.Date == DateTime.Now.Date)
{
    //Hash 1 Decryption
    string DecryAPIKEY = EncryptionDecryptorTripleDES.Decryption(Windows_APIKEY, keyValue, IVValue);

    // DecryHash2 Contains ClientToken
    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
    {
        //
        // GET: /Dashboard/
        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());
        }

    
        // POST api/authenticateuser
        [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.

  1. CheckUserExists method is used for checking the user is already exists in SQLite database or not.
  2. 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;

            //Local Database check
            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

  1. Timer
  2. 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;
                // Calling Business Layer
                ProductBL.AddProduct(objproduct);
                // Binding data to DataGridView
                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()
{
    //getting data from database
    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");

            //Token APIKEY
            client.Headers.Add("APIKEY",
            GenerateToken.CreateToken(ShareObject.Username, ClientToken, DateTime.Now.Ticks));

            //Setting Call back method
            client.UploadStringCompleted += new UploadStringCompletedEventHandler(Callback);

            //key and IV
            string keyValue = ConfigurationManager.AppSettings["keyValue"].ToString();
            string IVValue = ConfigurationManager.AppSettings["IVValue"].ToString();

            //Serializing Object
            string SerializeData = JsonConvert.SerializeObject(Product);
            //Encrypting Serialized Object
            byte[] buffer = EncryptionDecryptorTripleDES.Encryption(SerializeData, keyValue, IVValue);

            //Converting bytes To Base64String and then Upload data    
            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))
        {
           //getting ProductID in Response
            string finalData = e.Result;

            if (finalData != null)
            {
                //Deleting Product by ProductID
                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
    {
        //Setting Values to display
        progressBar1.Value = e.ProgressPercentage;
        //displaying Percentage in label  
        lblStatus.Text = "Processing......" + progressBar1.Value.ToString() + "%";
        //Refreshing DataGridView
        DGData.DataSource = null;
        DGData.Update();
        DGData.Refresh();
        //Rebinding DataGridView
        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.

 

 

 

 

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

saineshwar bageri
Software Developer Mahaonline LTD
India India
Indian Software Developer and MVP from c-sharpcorner working on .Net Web Technology
( Asp.net , C# , Sqlserver , MVC , Windows ,Console Application, javascript , jquery , json , ORM Dapper) and also freelance developer.

You may also be interested in...

Pro
Pro

Comments and Discussions

 
QuestionGreat work. Pin
Member WilliD5-Oct-16 11:18
professionalMember WilliD5-Oct-16 11:18 
AnswerRe: Great work. Pin
saineshwar bageri5-Oct-16 18:33
membersaineshwar bageri5-Oct-16 18:33 
QuestionGood Pin
keyur soni4-Oct-16 1:35
memberkeyur soni4-Oct-16 1:35 
AnswerRe: Good Pin
saineshwar bageri4-Oct-16 1:45
membersaineshwar bageri4-Oct-16 1:45 
Questionnot bad for first try Pin
maxoptimus4-Oct-16 0:01
membermaxoptimus4-Oct-16 0:01 
AnswerRe: not bad for first try Pin
saineshwar bageri4-Oct-16 0:10
membersaineshwar bageri4-Oct-16 0:10 
GeneralRe: not bad for first try Pin
maxoptimus4-Oct-16 1:07
membermaxoptimus4-Oct-16 1:07 
QuestionCan I get the source code ? Pin
Asutosha30-Sep-16 20:59
professionalAsutosha30-Sep-16 20:59 
AnswerRe: Can I get the source code ? Pin
saineshwar bageri3-Oct-16 21:47
membersaineshwar bageri3-Oct-16 21:47 
Questionhi Pin
Member 1134936030-Sep-16 9:15
memberMember 1134936030-Sep-16 9:15 
AnswerRe: hi Pin
saineshwar bageri3-Oct-16 21:48
membersaineshwar bageri3-Oct-16 21:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.161208.2 | Last Updated 4 Oct 2016
Article Copyright 2016 by saineshwar bageri
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid