MVC專案實踐,在三層架構下實現SportsStore-11,使用Knockout實現增刪改查

Darren Ji發表於2014-07-10

SportsStore是《精通ASP.NET MVC3框架(第三版)》中演示的MVC專案,在該專案中涵蓋了MVC的眾多方面,包括:使用DI容器、URL優化、導航、分頁、購物車、訂單、產品管理、影象上傳......是不錯的MVC實踐專案,但該專案不是放在多層框架下開發的,離真實專案還有一段距離。本系列將嘗試在多層框架下實現SportsStore專案,並用自己的方式實現一些功能。


本篇為"在三層架構下實現SportsStore"系列的第十一篇,包括:

 

■ 13、使用Knockout實現增刪改查
    □ 13.1 關於Knockout
    □ 13.2 實現增刪改查

 

  13、使用Knockout實現增刪改查

  13.1 關於Knockout


在ASP.NET MVC中,拿一個強型別檢視頁來說,檢視View和Model有著比較強的耦合。Knockout的出現就是為了解耦View和Model。Knockout是一個Javascript庫,他通過建立View Model,實現了View和Model之間的解耦,這符合基於UI的設計模式"MVVM":

● Model: 應用程式的領域模型(Domain Model),在Knockout中,經常使用Ajax對領域模型進行讀寫。
● View: 動態顯示或更新View Model的UI
● View Model: 在UI層的JavaScript物件,UI層的Model。

 

關於Knockout,請參考官網。http://knockoutjs.com/index.html

 

  13.2 實現增刪改查

52

 

在ProductManage控制器中實現增刪改查的邏輯:

using System.Linq;
using System.Web.Mvc;
using MySportsStore.IBLL;
using MySportsStore.Model;
using Ninject;

namespace MySportsStore.WebUI.Controllers
{
    public class ProductManageController : BaseController
    {
        [Inject]
        public IProductService ProductService { get; set; }

        public ProductManageController()
        {
            this.AddDisposableObject(ProductService);
        }

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

        public JsonResult GetProducts() 
        {
            return Json(ProductService.LoadEntities(p => true), JsonRequestBehavior.AllowGet);
        }

        public JsonResult AddProduct(Product product)
        {
            ProductService.AddEntity(product);
            return Json(product, JsonRequestBehavior.AllowGet);
        }

        public JsonResult EditProduct(Product product)
        {
            ProductService.UpdateEntity(product);
            return Json(ProductService.LoadEntities(p => true), JsonRequestBehavior.AllowGet);
        }

        public JsonResult DeleteProduct(int id)
        {
            var dbProduct = ProductService.LoadEntities(p => p.Id == id).FirstOrDefault();
            if (ProductService.DeleteEntity(dbProduct) > 0)
            {
                return Json(new {msg = true},JsonRequestBehavior.AllowGet);
            }
            return Json(new { msg = false }, JsonRequestBehavior.AllowGet);
        }
    }
}

在ProductManage/Index.cshtml檢視中:
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <style type="text/css">
        //省去樣式
    </style>
    <script src="~/Scripts/jquery-1.8.2.min.js"></script>
    <script src="~/Scripts/knockout-3.1.0.js"></script>
    <script type="text/javascript">
        $(function() {
            var viewModel = new ProductViewModel();
            ko.applyBindings(viewModel);
        });

        function ProductViewModel() {
            var self = this;

            //讓屬性observalbe
            self.Id = ko.observable("");
            self.Name = ko.observable("");
            self.Description = ko.observable("");
            self.Price = ko.observable("");
            self.Category = ko.observable("");

            var Product = {
                Id: self.Id,
                Name: self.Name,
                Description: self.Description,
                Price: self.Price,
                Category: self.Category
            };

            self.Product = ko.observable();
            self.Products = ko.observableArray();

            //初始化產品列表
            $.ajax({
                url: '@Url.Action("GetProducts","ProductManage")',
                cache: false,
                type: 'GET',
                contentType: 'application/json; charset=utf-8',
                data: {},
                success: function(data) {
                    self.Products(data);
                }
            });

            //初始化之後計算總價,增加一個計算屬性
            self.Total = ko.computed(function() {
                var sum = 0;
                var arr = self.Products();
                for (var i = 0; i < arr.length; i++) {
                    sum += arr[i].Price;
                }
                return sum;
            });

            //新增
            self.create = function() {
                if (Product.Name() != "" && Product.Price() != "" && Product.Description() != "" && Product.Category() != "") {
                    $.ajax({
                        url: '@Url.Action("AddProduct","ProductManage")',
                        cache: false,
                        type: 'POST',
                        contentType: 'application/json; charset=utf-8',
                        data: ko.toJSON(Product),
                        success: function(data) {
                            self.Products.push(data);

                            //清空
                            self.Name("");
                            self.Description("");
                            self.Price("");
                            self.Category("");
                        }
                    }).fail(function(xhr, textStatus, err) {
                        alert(err);
                    });
                } else {
                    alert("不能為空~~");
                }
            };

            //刪除
            self.delete = function(Product) {
                if (confirm('確定要刪除 "' + Product.Name + '" 嗎')) {
                    //var id = Product.Id;
                    $.ajax({
                        url: '@Url.Action("DeleteProduct","ProductManage")',
                        cache: false,
                        type: 'GET',
                        contentType: 'application/json; charset=utf-8',
                        //data: ko.toJSON(id),
                        data: {id : Product.Id },
                        success: function(data) {
                            if (data.msg == true) {
                                self.Products.remove(Product);
                            } else {
                                alert("伺服器內部錯誤~~");
                            }
                        }
                    }).fail(function(xhr, textStatus, err) {
                        alert("出錯了~~");
                    });
                }
            };

            //顯示更新介面
            self.edit = function(Product) {
                self.Product(Product);
            };

            //更新
            self.update = function() {
                var Product = self.Product();

                $.ajax({
                    url: '@Url.Action("EditProduct","ProductManage")',
                    cache: false,
                    type: 'POST',
                    contentType: 'application/json; charset=utf-8',
                    data: ko.toJSON(Product),
                    success: function(data) {
                        self.Products.removeAll();
                        self.Products(data);
                        self.Product(null);
                        alert("更新成功~~");
                    }
                });
            };

            //重置
            self.reset = function() {
                self.Name("");
                self.Price("");
                self.Category("");
                self.Description("");
            };

            //取消產品細節
            self.cancel = function() {
                self.Product(null);
            };
        }

        //格式化價格
        function formatCurrency(value) {
            return "" + value.toFixed(2);
        }
    </script>
</head>
<body>
    <div id="body">
        <h3>產品管理</h3>
        <table id="products1" data-bind="">
            <thead>
                <tr>
                    <th>編號</th>
                    <th>產品名稱</th>
                    <th>產品描述</th>
                    <th>產品類別</th>
                    <th>價格</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody data-bind="foreach: Products">
                <tr>
                    <td data-bind="text: Id"></td>
                    <td data-bind="text: Name"></td>
                    <td data-bind="text: Description"></td>
                    <td data-bind="text: Category"></td>
                    <td data-bind="text: formatCurrency(Price)"></td>
                    <td>
                        <button data-bind="click: $root.edit">編輯</button>
                        <button data-bind="click: $root.delete">刪除</button>
                    </td>
                </tr>
            </tbody>
            <tfoot>
                <tr>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td>總計:</td>
                    <td data-bind="text: formatCurrency($root.Total())"></td>
                    <td></td>
                </tr>
            </tfoot>
        </table>
        <br/>
        <br/>
        <div style="border-top: solid 2px #282828; width: 430px; height: 10px"> </div>
        
        <div data-bind="if: Product">
            <div><h2>更新產品</h2></div>
            <div>
                <label for="productId" data-bind="visible: false">編號</label>
                <label data-bind="text: Product().Id, visible: false"></label>
            </div>
            <div>
                <label for="name">產品名稱</label>
                <input data-bind="value: Product().Name" type="text" title="Name"/>
            </div>
            <div>
                <label for="description">產品描述</label>
                <input data-bind="value: Product().Description" type="text" title="Description"/>
            </div>
            <div>
                <label for="category">產品類別</label>
                <input data-bind="value: Product().Category" type="text" title="Category"/>
            </div>
            <div>
                <label for="price">產品價格</label>
                <input data-bind="value: Product().Price" type="text" title="Price"/>
            </div>
            <br/>
            <div>
                <button data-bind="click: $root.update">更新</button>
                <button data-bind="click: $root.cancel">取消</button>
            </div>
        </div>

        <div data-bind="ifnot: Product()">
            <div>
                <h2>新增產品</h2>
            </div>
            <div>
                <label for="name">產品名稱</label>
                <input data-bind="value: $root.Name" type="text" title="Name" />
            </div>
            <div>
                <label for="description">產品描述</label>
                <input data-bind="value: $root.Description" type="text" title="Description" />
            </div>
            <div>
                <label for="category">產品類別</label>
                <input data-bind="value: $root.Category" type="text" title="Category" />
            </div>
            <div>
                <label for="price">產品價格</label>
                <input data-bind="value: $root.Price" type="text" title="Price" />
            </div>
            <div>
                <button data-bind="click: $root.create">新增</button>
                <button data-bind="click: $root.reset">重置</button>
            </div>
        </div>
        
    </div>  

</body>
</html>

 

原始碼在這裡

 

“MVC專案實踐,在三層架構下實現SportsStore”系列包括:

MVC專案實踐,在三層架構下實現SportsStore,從類圖看三層架構

MVC專案實踐,在三層架構下實現SportsStore-01,EF Code First建模、DAL層等

MVC專案實踐,在三層架構下實現SportsStore-02,DbSession層、BLL層

MVC專案實踐,在三層架構下實現SportsStore-03,Ninject控制器工廠等

MVC專案實踐,在三層架構下實現SportsStore-04,實現分頁

MVC專案實踐,在三層架構下實現SportsStore-05,實現導航

MVC專案實踐,在三層架構下實現SportsStore-06,實現購物車

MVC專案實踐,在三層架構下實現SportsStore-07,實現訂單提交

MVC專案實踐,在三層架構下實現SportsStore-08,部署到IIS伺服器

MVC專案實踐,在三層架構下實現SportsStore-09,ASP.NET MVC呼叫ASP.NET Web API的查詢服務

MVC專案實踐,在三層架構下實現SportsStore-10,連線字串的加密和解密

MVC專案實踐,在三層架構下實現SportsStore-11,使用Knockout實現增刪改查

相關文章