AngularJs và Asp.net Mvc

Đối với những lập trình web, có lẽ chúng ta đã được nghe khá nhiều về angularjs, một javascript framework nổi tiếng do Google phát triển. Đây là thư viện đã được sử dụng rộng rãi trong các ứng dụng nền web. Điểm mạnh của nó là có thể phát triển theo mô hình MVC bên phía frontend giúp cấu trúc ứng dụng tốt hơn, dễ bảo trì hơn, có thể unit test, áp dụng dependency injection, mở rộng html syntax với directive, cơ chế two-way- binding và rất nhiều ưu điểm khác mà các bạn đã được biết hoặc nghe và đọc rất nhiều trên các tài liệu. Trong phạm vi bài viết này tôi mong muốn giới thiệu tới các bạn việc sử dụng angualarjs trong web asp.net MVC. Mục đích để các bạn bắt đầu với angularjs có thể ứng dụng nó trong một web asp.net mvc đơn giản. Tôi sẽ tạo một ứng dụng tính giá trị biểu thức từ một chuỗi được nhập vào bởi người dùng, chúng ta sẽ lưu biểu thức và kết quả tính toán của biểu thức đó vào trong Sql server. Nội dung bài biết giả định rằng các bạn đã có kiến thức cơ bản về asp.net mvc và angularjs.

1. Tạo project asp.net mvc 4 với visual studio 2013

create_project.jpg


2. Sử dụng Entityframework để thao tác với dữ liệu

install_EF.jpg

3. Tạo một project để thao tác với DB

namespace Exercise2.Data.Entities
{
    public class Expression
    {
        public int Id { get; set; }

        public string ExpressionText { get; set; }

        public float Result { get; set; }
    }
}

Ở đây tôi sẽ tạo một class Expression cái mà sẽ mapping với table trong Db. Tạo một class Exercise context kế thừa lớp DbContext (một class trong Entity Framwork hỗ trợ việc query data) để thực hiện việc kết nối và thao tác trực tiếp với sql server

    namespace Exercise2.Data
    {
        public class ExerciseContext : DbContext
        {

            public ExerciseContext()
                : base("name=ExpressionConnectString")
            {

            }

            public DbSet<Expression> Expressions { get; set; }
        }
    }

4. Tạo các action trong HomeController để truy vấn dữ liệu

        private readonly ExerciseContext _exerciseContext = new ExerciseContext();
        public JsonResult GetAllExpressions()
        {
            return Json(_exerciseContext.Expressions.OrderByDescending(item => item.Id),
                JsonRequestBehavior.AllowGet);
        }

        public JsonResult CaculateExpressions(string expresstionText)
        {
            try
            {
                expresstionText = expresstionText.Trim();
                // check expression whether is valid or not
                if (Common.IsValidExpression(expresstionText))
                {
                    object result = Common.CaculateExpression(expresstionText);
                    float caculatedResult;
                    if (float.TryParse(result.ToString(), out caculatedResult))
                    {
                        return Json(caculatedResult, JsonRequestBehavior.AllowGet);
                    }
                }

                return Json(new { message = "Expression is invalid", error = 1 });
            }
            catch (Exception ex)
            {
                return Json(new { message = ex.Message, error = 1 });
            }

        }

        public JsonResult SaveExpression(string expresstionText, float result)
        {
            try
            {
                var expresstion = new Expression { ExpressionText = expresstionText, Result = result };
                _exerciseContext.Expressions.Add(expresstion);
                _exerciseContext.SaveChanges();

                return Json(new { message = "Save expression successfuly", error = 0 });
            }
            catch (Exception ex)
            {
                return Json(new { message = ex.Message, error = 1 });
            }

        }

        public JsonResult DeleteExpression(int? id)
        {
            try
            {
                var currentExpression = _exerciseContext.Expressions.Find(id);
                if (currentExpression != null)
                {
                    _exerciseContext.Expressions.Remove(currentExpression);
                    _exerciseContext.SaveChanges();
                    return Json(new { message = "Delete expression successfuly", error = 0 });
                }

                return Json(new { message = "The item does not exist", error = 1 });
            }
            catch (Exception)
            {
                return Json(new { message = "Delete error", error = 1 });
            }

        }

Như vậy chúng ta đã tạo những action cơ bản cho việc thao tác với cơ sở dữ liệu trong controller của mvc. Bước tiếp theo chúng ta sẽ sử dụng angularjs để gọi những action này.

5. Xây dựng view với angualar js

Trước tiên chúng ta cần import angualarjs library tới layout.cshml


<script src="~/Scripts/angularJs/angular.min.js"></script>

Trong ứng dụng này cần tới phân trang, vì vậy tôi sử dụng thêm một directive có sẵn cho việc này đó là ui-bootstrap, chúng ta cần import chúng tới layout

<script src="~/Scripts/angular-ui/ui-bootstrap-tpls.min.js"></script>
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />

Tất nhiên các bạn có thể tự viết một directive phân trang cho riêng mình, các bạn có thể tìm hiểu sâu hơn về directive tại trang angularjs.org. Tiếp theo để khởi tạo angular app chúng ta cần tạo một file thông thường đặt tên app.js. Trong demo này tôi đặt tất cả code angualarjs trong thư mục Scripts/app. Trong app.js đơn giản tôi chỉ khai báo một angualar module và inject một module phụ thuộc là ui.boostrap

var exercise2 = angular.module("exercise2", ['ui.bootstrap']);

Tiếp đến chúng ta sẽ tạo một controller để thao tác với view

app.controller("expressionController", function ($scope, $http) {

$scope.expressions = [];

$scope.currentExpression = { expressionText: "", result: 0 };

$scope.errorMessage = "";

$scope.filteredItems = [];

$scope.currentPage = 1;

$scope.numPerPage = 10;

$scope.maxSize = 5;

function fetchData() {

    $http.get("/home/GetAllExpressions").success(function(data) {

        $scope.expressions = data;

    });
}

function clearErrorMessage() {
    $scope.errorMessage = "";
};

fetchData();

$scope.caculateExpresstion = function() {

    $http.post("/home/CaculateExpressions",

        { expresstionText: $scope.currentExpression.expressionText }

    ).success(function (data) {

        if (data.error === 1) {

            $scope.errorMessage = data.message;

        } else {

            $scope.currentExpression.result = data;

            clearErrorMessage();

        }

    }).error(function(error) {

        $scope.errorMessage = error.message;

    });

};

Ở đây tôi sẽ tạo các function để gọi các action trong home controller (code mvc). Như các bạn đã biết $scope và $http là 2 services được xây dựng sẵn bởi angularjs library. $Scope để quản lý các models, những object có thể truyền giữa view và controller, còn $http giúp client có thể giao tiếp với server với đầy đủ các http method: GET, POST, PUT và DELETE. Như hình bên dưới tôi có thể gọi api lấy tất cả các biểu thức như sau:

$http.get("/home/GetAllExpressions").success(function(data) {
    $scope.expressions = data;
});

Trong đó, home là tên controller, GetAllExpression là action phía server. Chúng ta cũng gọi tương tự nếu dùng Web Api của .Net. Để sử dụng những function trong angular controller tất nhiên chúng ta cũng cần tham chiếu nó trong view

<script src="~/Scripts/app/app.js"></script>
<script src="~/Scripts/app/expressionCtr.js"></script>

Tại home.cshtml cần chỉ định controller mà nó sử dụng, ta dùng cú pháp như sau:

<div class="app-container" ng-controller="expressionController">

Dưới đây là cách binding data mà tôi đã sử dụng:

<div class="app-container" ng-controller="expressionController">
    <p class="app-heading">@ViewBag.Message</p>
    <h2 class="error-message" ng-show="errorMessage.length > 0">
        {{errorMessage}}
    </h2>
    <label>Expression:</label><input type="text" ng-model="currentExpression.expressionText"/>

    <input type="button" value="Caculate" ng-click="caculateExpresstion()" class="btn"/>
    <div class="caculate-result">
        <p>Caculated Result: {{currentExpression.result}}</p>
        <input type="button" value="Save" ng-click="saveExpression()" ng-show="currentExpression.result>0" class="btn"/>
    </div>
    <div class="expression-list">
        <table>
            <tr>
                <th>No</th>
                <th>Expression</th>
                <th>Result</th>
                <th>Action</th>
            </tr>
            <tr ng-repeat="item in filteredItems">
                <td>{{$index+1}}</td>
                <td>{{item.ExpressionText}}</td>
                <td>{{item.Result | number:2}}</td>
                <td><a href="#" ng-click="deleteExpression(item.Id)">Delete</a></td>
            </tr>
        </table>
        <pagination ng-model="currentPage"
                    total-items="expressions.length"
                    max-size="maxSize"
                    boundary-links="true">
        </pagination>

    </div>

</div>

Trên đây là những chia sẻ rất cơ bản để có thể ứng dụng angular trong web asp.net mvc. Với mong muốn chia sẽ những hiểu biết của mình và angularjs và asp.net mvc tới các bạn yêu thích chúng. Chúc các bạn thành công.

Link code: https://drive.google.com/file/d/0B0YcdbjNGk5NTEQxY3hyNjFuZU0/view?usp=sharing


All Rights Reserved