ASP.NET MVC-5 with AngularJS Part – 2

In this topic we will overview on AngularJS, after getting an overview we will create a ASP.Net MVC application with implementing AngularJS(v1.4.8).

If you miss the previous article in this series please go and have an overview before get into this part.

ASP.NET MVC-5 with AngularJS Part – 1

Introduction

In our previous article we have an overview on AngularJS. Now we know what AngularJS capable for, what is it, how to start with? Now it’s time to make a sample application which can perform CRUD operations using database.

Ok let’s get started.

AngularJS with Visual Studio:

Let’s open Visual Studio 2015(IDE) click : [File > New > Project] the new window will appear like below image

Fig: 1.0

ang-1

Click on ASP.Net Web Application,rename the application and hit “ok” button at bottom right. Choose empty template in next window and click on “ok” button. It will take a while to load a sample empty project.

Now the first thing we need to do is register AngularJS.Core in this application. We need to getting reference from NuGet.

To do that right click on project name and click on “Manage NuGet Packages” like below image

Fig: 1.1

ang-2

and in next window browse searching “Angular” and install the updated version of AngularJS.Core like below image

Fig: 1.2

ang-3

Or click on [ Tools > NuGet Package Manager > Package Manager Console ] and write

Install-Package AngularJS.Core

also we need to add jQuery library in our project like below.

Fig: 1.3

ang-4

Our Installation process is done. Now test it with our previous AngularJS code in comparing with jQuery section.

Data Layer:

public class GenericRepository : IRepository where T : class
{

    CRUD_SampleEntities context = null;
    private DbSet entities = null;

    public GenericRepository(CRUD_SampleEntities context)
    {
        this.context = context;
        entities = context.Set();
    }

    /// 
    /// Get Data From Database
    /// Use it when to retive data through a stored procedure
    /// 
    public IEnumerable ExecuteQuery(string spQuery, object[] parameters)
    {
        using (context = new CRUD_SampleEntities())
        {
            return context.Database.SqlQuery(spQuery, parameters).ToList();
        }
    }

    /// 
    /// Get Single Data From Database
    /// Use it when to retive single data through a stored procedure
    /// 
    public T ExecuteQuerySingle(string spQuery, object[] parameters)
    {
        using (context = new CRUD_SampleEntities())
        {
            return context.Database.SqlQuery(spQuery, parameters).FirstOrDefault();
        }
    }

    /// 
    /// Insert/Update/Delete Data To Database
    /// Use it when to Insert/Update/Delete data through a stored procedure
    /// 
    public int ExecuteCommand(string spQuery, object[] parameters)
    {
        int result = 0;
        try
        {
            using (context = new CRUD_SampleEntities())
            {
                result = context.Database.SqlQuery(spQuery, parameters).FirstOrDefault();
            }
        }
        catch { }
        return result;
    }

    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                context.Dispose();
            }
        }
        this.disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

Interfaces:

interface IRepository : IDisposable where T : class
{
    IEnumerable ExecuteQuery(string spQuery, object[] parameters);
    T ExecuteQuerySingle(string spQuery, object[] parameters);
    int ExecuteCommand(string spQuery, object[] parameters);
}

Code Explanation:

If you are new to this design pattern overview here for more.

Middle Layer:

public partial class CustomerService
{
    private GenericRepository CustRepository;

    public CustomerService()
    {
        this.CustRepository = new GenericRepository(new CRUD_SampleEntities());
    }

    public IEnumerable GetAll(object[] parameters)
    {
        string spQuery = "[Get_Customer] {0}";
        return CustRepository.ExecuteQuery(spQuery, parameters);
    }

    public Customer GetbyID(object[] parameters)
    {
        string spQuery = "[Get_CustomerbyID] {0}";
        return CustRepository.ExecuteQuerySingle(spQuery, parameters);
    }

    public int Insert(object[] parameters)
    {
        string spQuery = "[Set_Customer] {0}, {1}";
        return CustRepository.ExecuteCommand(spQuery, parameters);
    }

    public int Update(object[] parameters)
    {
        string spQuery = "[Update_Customer] {0}, {1}, {2}";
        return CustRepository.ExecuteCommand(spQuery, parameters);
    }

    public int Delete(object[] parameters)
    {
        string spQuery = "[Delete_Customer] {0}";
        return CustRepository.ExecuteCommand(spQuery, parameters);
    }
}

Our Data Layer and Service layer is ready. For creating database, please download the database script and execute it using MS SQL Server.

Lets create a MVC HomeController and generate empty view.

Fig: 1.4

ang-p2-1.

MVC HomeController:

Let’s just put this code in your home controller i’ll explain it later.

public class HomeController : Controller
{
    private CustomerService objCust;
    public HomeController()
    {
        this.objCust = new CustomerService();
    }

    // GET: Home
    public ActionResult Index()
    {
        return View();
    }

    // GET: All Customer
    [HttpGet]
    public JsonResult GetAllData()
    {
        int Count = 10; IEnumerable customers = null;
        try
        {
            object[] parameters = { Count };
            customers = objCust.GetAll(parameters);
        }
        catch { }
        return Json(customers.ToList(), JsonRequestBehavior.AllowGet);
    }

    // GET: Get Single Customer
    [HttpGet]
    public JsonResult GetbyID(int id)
    {
        object customer = null;
        try
        {
            object[] parameters = { id };
            customer = this.objCust.GetbyID(parameters);
        }
        catch { }
        return Json(customer, JsonRequestBehavior.AllowGet);
    }

    public ActionResult Insert()
    {
        return View();
    }

    // POST: Save New Customer
    [HttpPost]
    public JsonResult Insert(Customer model)
    {
        int result = 0; bool status = false;
        if (ModelState.IsValid)
        {
            try
            {
                object[] parameters = { model.CustName, model.CustEmail };
                result = objCust.Insert(parameters);
                if (result == 1)
                {
                    status = true;
                }
                return Json(new { success = status });
            }
            catch { }
        }
        return Json(new
        {
            success = false,
            errors = ModelState.Keys.SelectMany(i => ModelState[i].Errors).Select(m => m.ErrorMessage).ToArray()
        });
    }

    public ActionResult Update()
    {
        return View();
    }

    // POST: Update Existing Customer
    [HttpPost]
    public JsonResult Update(Customer model)
    {
        int result = 0; bool status = false;
        if (ModelState.IsValid)
        {
            try
            {
                object[] parameters = { model.Id, model.CustName, model.CustEmail };
                result = objCust.Update(parameters);
                if (result == 1)
                {
                    status = true;
                }
                return Json(new { success = status });
            }
            catch { }
        }
        return Json(new
        {
            success = false,
            errors = ModelState.Keys.SelectMany(i => ModelState[i].Errors).Select(m => m.ErrorMessage).ToArray()
        });
    }

    // DELETE: Delete Customer
    [HttpDelete]
    public JsonResult Delete(int id)
    {
        int result = 0; bool status = false;
        try
        {
            object[] parameters = { id };
            result = objCust.Delete(parameters);
            if (result == 1)
            {
                status = true;
            }
        }
        catch { }
        return Json(new
        {
            success = status
        });
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
    }
}

Code Explanation:

Let’s get explained the code part by part.

Get All Records: Below code sample is to get all records from database by using our middle layer/service layer. We are returning JSON data here. The format of JSON data is easy to read, follow attribute-value pairs.

Initially we are getting ten(10) records, this is plan for paging in view page.

// GET: All Customer
[HttpGet]
public JsonResult GetAllData()
{
    int Count = 10; IEnumerable customers = null;
    try
    {
        object[] parameters = { Count };
        customers = objCust.GetAll(parameters);
    }
    catch { }
    return Json(customers.ToList(), JsonRequestBehavior.AllowGet);
}

While we are returning the list data we have set “JsonRequestBehavior.AllowGet”. if we miss that, this error message will appear:

This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. 
To allow GET requests, set JsonRequestBehavior to AllowGet.

Why use it? If you read that message carefully the answer is there.This is for security reason.

Get Single Record Details: Below code sample will retrieve a single selected record details from database, which also returning JSON data format.

// GET: Get Single Customer
[HttpGet]
public JsonResult GetbyID(int id)
{
    object customer = null;
    try
    {
        object[] parameters = { id };
        customer = this.objCust.GetbyID(parameters);
    }
    catch { }
    return Json(customer, JsonRequestBehavior.AllowGet);
}

Insert Records: Below code sample will Insert/Save record details to database, which is returning a JSON result of boolean data type.

If it’s true then it indicate that data inserted to database successfully.

// POST: Save New Customer
[HttpPost]
public JsonResult Insert(Customer model)
{
    int result = 0; bool status = false;
    if (ModelState.IsValid)
    {
        try
        {
            object[] parameters = { model.CustName, model.CustEmail };
            result = objCust.Insert(parameters);
            if (result == 1)
            {
                status = true;
            }
            return Json(new { success = status });
        }
        catch { }
    }
    return Json(new
    {
        success = false,
        errors = ModelState.Keys.SelectMany(i => ModelState[i].Errors).Select(m => m.ErrorMessage).ToArray()
    });
}

Update Records: Below code sample will update existing record details to database that is selected to update, which is also returning a JSON result of boolean data type.

If it’s true then it indicate that data updated to database successfully.

// POST: Update Existing Customer
[HttpPost]
public JsonResult Update(Customer model)
{
    int result = 0; bool status = false;
    if (ModelState.IsValid)
    {
        try
        {
            object[] parameters = { model.Id, model.CustName, model.CustEmail };
            result = objCust.Update(parameters);
            if (result == 1)
            {
                status = true;
            }
            return Json(new { success = status });
        }
        catch { }
    }
    return Json(new
    {
        success = false,
        errors = ModelState.Keys.SelectMany(i => ModelState[i].Errors).Select(m => m.ErrorMessage).ToArray()
    });
}

Delete Records: Below code sample will delete existing record details to database that is selected to delete, which is also returning a JSON result of boolean data type.

If it’s true then it indicate that data deleted from database successfully.

// DELETE: Delete Customer
[HttpDelete]
public JsonResult Delete(int id)
{
    int result = 0; bool status = false;
    try
    {
        object[] parameters = { id };
        result = objCust.Delete(parameters);
        if (result == 1)
        {
            status = true;
        }
    }
    catch { }
    return Json(new
    {
        success = status
    });
}

We are done with our MVC Controller to perform CRUD operations on database. Now let’s move on to next part, the AngularJS part.

AngularJS(JavaScript) Controller:

angular.module('myFormApp', [])
.controller('CustomerController', function ($scope, $http, $location, $window) {
    $scope.custModel = {};
    $scope.message = '';
    $scope.result = "color-default";
    $scope.isViewLoading = false;
    $scope.ListCustomer = null;
    getallData();

    //******=========Get All Customer=========******
    function getallData() {
        //debugger;
        $http.get('/Home/GetAllData')
            .success(function (data, status, headers, config) {
                $scope.ListCustomer = data;
            })
            .error(function (data, status, headers, config) {
                $scope.message = 'Unexpected Error while loading data!!';
                $scope.result = "color-red";
                console.log($scope.message);
            });
    };

    //******=========Get Single Customer=========******
    $scope.getCustomer = function (custModel) {
        $http.get('/Home/GetbyID/' + custModel.Id)
        .success(function (data, status, headers, config) {
            //debugger;
            $scope.custModel = data;
            getallData();
            console.log(data);
        })
        .error(function (data, status, headers, config) {
            $scope.message = 'Unexpected Error while loading data!!';
            $scope.result = "color-red";
            console.log($scope.message);
        });
    };

    //******=========Save Customer=========******
    $scope.saveCustomer = function () {
        $scope.isViewLoading = true;

        $http({
            method: 'POST',
            url: '/Home/Insert',
            data: $scope.custModel
        }).success(function (data, status, headers, config) {
            if (data.success === true) {
                $scope.message = 'Form data Saved!';
                $scope.result = "color-green";
                getallData();
                $scope.custModel = {};
                console.log(data);
            }
            else {
                $scope.message = 'Form data not Saved!';
                $scope.result = "color-red";
            }
        }).error(function (data, status, headers, config) {
            $scope.message = 'Unexpected Error while saving data!!' + data.errors;
            $scope.result = "color-red";
            console.log($scope.message);
        });
        getallData();
        $scope.isViewLoading = false;
    };

    //******=========Edit Customer=========******
    $scope.updateCustomer = function () {
        //debugger;
        $scope.isViewLoading = true;
        $http({
            method: 'POST',
            url: '/Home/Update',
            data: $scope.custModel
        }).success(function (data, status, headers, config) {
            if (data.success === true) {
                $scope.custModel = null;
                $scope.message = 'Form data Updated!';
                $scope.result = "color-green";
                getallData();
                console.log(data);
            }
            else {
                $scope.message = 'Form data not Updated!';
                $scope.result = "color-red";
            }
        }).error(function (data, status, headers, config) {
            $scope.message = 'Unexpected Error while updating data!!' + data.errors;
            $scope.result = "color-red";
            console.log($scope.message);
        });
        $scope.isViewLoading = false;
    };

    //******=========Delete Customer=========******
    $scope.deleteCustomer = function (custModel) {
        //debugger;
        var IsConf = confirm('You are about to delete ' + custModel.CustName + '. Are you sure?');
        if (IsConf) {
            $http.delete('/Home/Delete/' + custModel.Id)
            .success(function (data, status, headers, config) {
                if (data.success === true) {
                    $scope.message = custModel.CustName + ' deleted from record!!';
                    $scope.result = "color-green";
                    getallData();
                    console.log(data);
                }
                else {
                    $scope.message = 'Error on deleting Record!';
                    $scope.result = "color-red";
                }
            })
            .error(function (data, status, headers, config) {
                $scope.message = 'Unexpected Error while deleting data!!';
                $scope.result = "color-red";
                console.log($scope.message);
            });
        }
    };
})
.config(function ($locationProvider) {
    $locationProvider.html5Mode(true);
});

Code Explanation:

$http is core AngularJS service that can communicate with the remote HTTP servers. HTTP methods that participate used to communicate:

  • $http.get: get data
  • $http.post: post new data
  • $http.put: update existing data
  • $http.delete: delete existing data

Know more about $http service here

Get All Record: Using $http.get method we are retrieving all records from database.

//******=========Get All Customer=========******
function getallData() {
    //debugger;
    $http.get('/Home/GetAllData')
        .success(function (data, status, headers, config) {
            $scope.ListCustomer = data;
        })
        .error(function (data, status, headers, config) {
            $scope.message = 'Unexpected Error while loading data!!';
            $scope.result = "color-red";
            console.log($scope.message);
        });
};

Get Single Record: Here we are retriving existing customer records from database.The $scope.getCustomer methos is getting called while edit button is getting hit/click.

//******=========Get Single Customer=========******
$scope.getCustomer = function (custModel) {
    $http.get('/Home/GetbyID/' + custModel.Id)
    .success(function (data, status, headers, config) {
        //debugger;
        $scope.custModel = data;
        getallData();
        console.log(data);
    })
    .error(function (data, status, headers, config) {
        $scope.message = 'Unexpected Error while loading data!!';
        $scope.result = "color-red";
        console.log($scope.message);
    });
};

Using $http.get method we are retrieving selected customer record from database by passing the Customer ID to MVC Controller update method.

In return we are getting the query data and AngularJS $scope.custModel is binding the data to input model using ng-model, we know AngularJS support Two-way Data Binding.

Know more about Two-way Data Binding here

Save Record: Here we are saving customer records.The $scope.saveCustomer methos is getting called from UI when we submitting the form with customer information by clicking the submit button.

Using $http.post we are passing the customer object to our MVC controller.

//******=========Save Customer=========******
$scope.saveCustomer = function () {
    $scope.isViewLoading = true;

    $http({
        method: 'POST',
        url: '/Home/Insert',
        data: $scope.custModel
    }).success(function (data, status, headers, config) {
        if (data.success === true) {
            $scope.message = 'Form data Saved!';
            $scope.result = "color-green";
            getallData();
            $scope.custModel = {};
            console.log(data);
        }
        else {
            $scope.message = 'Form data not Saved!';
            $scope.result = "color-red";
        }
    }).error(function (data, status, headers, config) {
        $scope.message = 'Unexpected Error while saving data!!' + data.errors;
        $scope.result = "color-red";
        console.log($scope.message);
    });
    getallData();
    $scope.isViewLoading = false;
};

The controller is doing the rest with a retun status of saved? or Not. After successful insertion we have reload(calling getallData() method again) the data table.

Edit Record: Here we are Updating existing customer records to database.The $scope.updateCustomer methos is getting called while update button is getting hit/click.

Like save record, same thing also happening here. The main different in saving and updating is the Cutomer ID. This time we are passing Customer ID with customer object which is getting from a hidden input field.

Using $http.post we are passing the customer object to our MVC controller.

//******=========Edit Customer=========******
$scope.updateCustomer = function () {
    //debugger;
    $scope.isViewLoading = true;
    $http({
        method: 'POST',
        url: '/Home/Update',
        data: $scope.custModel
    }).success(function (data, status, headers, config) {
        if (data.success === true) {
            $scope.custModel = null;
            $scope.message = 'Form data Updated!';
            $scope.result = "color-green";
            getallData();
            console.log(data);
        }
        else {
            $scope.message = 'Form data not Updated!';
            $scope.result = "color-red";
        }
    }).error(function (data, status, headers, config) {
        $scope.message = 'Unexpected Error while updating data!!' + data.errors;
        $scope.result = "color-red";
        console.log($scope.message);
    });
    $scope.isViewLoading = false;
};

The controller is doing the rest with a retun status of updated? or Not. After successful updating we have reload(calling getallData() method again) the data table.

Delete Record: Here we are Deleting existing customer records from database.The $scope.deleteCustomer methos is getting called while delete button is getting hit/click.

//******=========Delete Customer=========******
$scope.deleteCustomer = function (custModel) {
    //debugger;
    var IsConf = confirm('You are about to delete ' + custModel.CustName + '. Are you sure?');
    if (IsConf) {
        $http.delete('/Home/Delete/' + custModel.Id)
        .success(function (data, status, headers, config) {
            if (data.success === true) {
                $scope.message = custModel.CustName + ' deleted from record!!';
                $scope.result = "color-green";
                getallData();
                console.log(data);
            }
            else {
                $scope.message = 'Error on deleting Record!';
                $scope.result = "color-red";
            }
        })
        .error(function (data, status, headers, config) {
            $scope.message = 'Unexpected Error while deleting data!!';
            $scope.result = "color-red";
            console.log($scope.message);
        });
    }
};

Let’s get into UI/View section. Here’s the Index view where we perform CRUD operations graphically.

Html View:

@{
    ViewBag.Title = "Index";
}

Create Customer

loading...
{{message}}

Customer name is Required Minimum length required is 5 Minimum length required is 15
EmailId is Required! Invalid EmailId!

All Customers

{{custModel.Id}} {{custModel.CustName}} {{custModel.CustEmail}}
JavaScript{ }

Code Explanation:

Below code sample is a table with repeating table row(

). Here ng-repeat is diplaying single record(custModel ) with it’s template once per record from ListCustomer, or simply working as a repeater of table row.

Know more about ng-repeat here


{{custModel.Id}} {{custModel.CustName}} {{custModel.CustEmail}}

We are almost done. Let’s style our UI with CSS, below is css that we used to style the UI.

Form Style:

#content label {
    width: 150px;
}

.btn {
    margin-left: 140px;
}

#content input[type=submit] {
    width: 85px;
    padding: 5px 15px;
    background: #ff6a00;
    border: 0 none;
    cursor: pointer;
    color: #fff;
}

.error {
    color: red;
}

.color-default {
    color: #000;
}

.color-red {
    color: red;
}

.color-green {
    color: green;
}

#content input.ng-dirty.ng-invalid {
    border: 1px solid red;
    background-color: rgb(255, 244, 244);
}

[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
  display: none !important;
}

Hide Directive Flash(ng-cloak):

While loading our page you may noticed that Angular html template are visible/flash. It is happen while the browser in its compilation process of Angular html template, usually it flash while the page is loading. Which can hide using “ng-cloak/data-ng-cloak” directive.

Know more about ng-cloak here

We also need to add css class in our application start point.


                        

below is the css class of using ng-cloak.

[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
  display: none !important;
}

Let’s put a breakpoint on Updater() method in HomeController and run it, after submitting the form it’ll hits the breakpoint.

Fig: 1.5

ang-p2-2

In debug mode we can see the model is populated with form data. We can also debug using browser by putting debugger in our script.

$scope.updateCustomer = function () {
  debugger;
};

 

Fig: 1.6

ang-p2-3

In debug mode in our browser we can see the $scope.custModel is populated with form data,which is going to update the selected record in database.

Finally Output:

ang-p2-op

[Browser: Inspect > Console]

ang-p2-opc

[Browser: Inspect > Network]

ang-p2-opn

Source Code: I’ve uploaded the full source code to download/clone , Hope this will help 🙂

Author:

Since March 2011, have 8+ years of professional experience on software development, currently working as Senior Software Engineer at s3 Innovate Pte Ltd.

One thought on “ASP.NET MVC-5 with AngularJS Part – 2”

Leave a Reply