MVC项目实践,在三层架构下实现SportsStore-11,使用Knockout实现增删改查

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 实现增删改查

MVC项目实践,在三层架构下实现SportsStore-11,使用Knockout实现增删改查

 

在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实现增删改查

MVC项目实践,在三层架构下实现SportsStore-11,使用Knockout实现增删改查,布布扣,bubuko.com

MVC项目实践,在三层架构下实现SportsStore-11,使用Knockout实现增删改查

上一篇:HTML5新标签解释及用法


下一篇:silverlight 用户浏览器未安装SL插件问题