MVC 5 Scaffolder + EntityFramework+UnitOfWork Pattern 代码生成工具集成Visual Studio 2013

MVC 5 Scaffolder + EntityFramework+UnitOfWork Pattern 代码生成工具

经过一个多星期的努力总算完成了单表,多表关联(一对多,多对一)的增删改查的代码生成,基本上可以实现不用添加任何代码完成对数据表的操作。

下个阶段打算集成.net 4.5的认证和授权已经用户注册和角色管理

一旦有更好的方式我会把它集成到模板中实现自动生成。所以很希望得到大家的帮助。在这里我先抛砖引玉了。

asp.net MVC 5 Scaffolding多层架构代码生成向导开源项目(邀请你的参与)

Demo和所有源代码代码在 https://github.com/neozhu/MVC5-Scaffolder

先看一下我的Demo实例

实体类的结构

Order 与 OrderDetail 一对多,OrderDetail 与 Product 多对一,Order与Product则是多对多的关系。

实现的操作界面如下图

查询界面

功能:

1/新增操作 : 页面跳转到新增页面

2/删除操作 : 选择记录或单击行上的删除 弹出确认框 是否删除改记录

3/编辑操作 : 单击行上的编辑图标页面跳转到编辑页面

4/查询操作 : 在Search 文本框中输入关键字会根据后台每个字段的查询,选择需要显示的字段

5/Table功能 :字段显示勾选,分页显示,所有功能都是服务端实现

新增页面

功能:

布局:上部表头,下部的Tab为表体明细

一对多 :表体用table显示

多对一 :用Dropdownlist进行选择

表体明细的操作 :使用popup modal的方式操作

单击保存后,系统会自动合并表头表体一起提交到后台进行保存

编辑页面

功能:

加载数据:会根据主从关系把表头/表体的数据一次性加载

编辑数据:对表体明细的的操作类似新增页面,但对表体进行删除操作时会进行提示是否真的要删除后台数据。

保存数据:一次性提交所有表头/表体数据到后台进行操作。

上述这些功能完全可以代码生成 不需要做任何修改

项目结构

View层的代码

Index :查询Table List

Create :新增页面

Edit : 编辑页面

EditForm :Partial View内嵌在Create 和Edit页面中

_OrderDetailForm : pupup 子表维护表单页面

Create,和Edit页面通过Ajax Post 把数据提交到后台的Controller进行操作

代码如下

<script type="text/javascript">

        var orderid = 0;
        var ObjectState = "Added";

        var $orderdetailstable = {};
        $(document).ready(function () {

            $(‘form‘).submit(function () {
                var token = $(‘[name=__RequestVerificationToken]‘).val();
                var serializedForm = $(this).serialize();
                var actionurl = $(this).attr(‘action‘);

                var orderdetails = $orderdetailstable.bootstrapTable(‘getData‘);

                var newitem = {
                    OrderDetails: orderdetails,

                    Id: orderid,
                    Customer: $(‘#Customer‘, ‘form‘).val(),
                    ShippingAddress: $(‘#ShippingAddress‘, ‘form‘).val(),
                    OrderDate: $(‘#OrderDate‘, ‘form‘).val(),
                    ObjectState: ObjectState
                };
                $.ajax({
                    url: actionurl,
                    type: "POST",
                    dataType: "json",
                    contentType: "application/json; charset=utf-8",
                    data: JSON.stringify(newitem),
                    success: function (result) {
                        if (result.success) {
                            self.location = "/Orders/Index";
                        } else {
                            alert(result.err);
                        }

                    },
                    error: function (result) {
                        console.log(result.statusText + result.responseText);
                        alert(result.statusText + result.responseText);
                    }
                });
                return false;

            });
        });
    </script>

通过Jquery 获取表头和表体数据 序列化成Json对象然后Post到后台

Controller层代码

这里就只贴Create方法的代码

public class OrdersController : Controller
    {
        //private StoreContext db = new StoreContext();
        private readonly IOrderService _orderService;
        private readonly IUnitOfWorkAsync _unitOfWork;

        public OrdersController(IOrderService orderService, IUnitOfWorkAsync unitOfWork)
        {
            _orderService = orderService;
            _unitOfWork = unitOfWork;
        }

        // GET: Orders/Index
        public ActionResult Index()
        {

            var orders = _orderService.Queryable().AsQueryable();
            return View(orders);
        }

        // Get :Orders/PageList
        // For Index View Boostrap-Table load  data
        [HttpGet]
        public ActionResult PageList(int offset = 0, int limit = 10, string search = "", string sort = "", string order = "")
        {
            int totalCount = 0;
            int pagenum = offset / limit + 1;
            var orders = _orderService.Query(new OrderQuery().WithAnySearch(search)).OrderBy(n => n.OrderBy(sort, order)).SelectPage(pagenum, limit, out totalCount);
            var rows = orders.Select(n => new { Id = n.Id, Customer = n.Customer, ShippingAddress = n.ShippingAddress, OrderDate = n.OrderDate }).ToList();
            var pagelist = new { total = totalCount, rows = rows };
            return Json(pagelist, JsonRequestBehavior.AllowGet);
        }

        // GET: Orders/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Order order = _orderService.Find(id);
            if (order == null)
            {
                return HttpNotFound();
            }
            return View(order);
        }

        // GET: Orders/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: Orders/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        //[ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "OrderDetails,Id,Customer,ShippingAddress,OrderDate")] Order order)
        {
            if (ModelState.IsValid)
            {
                order.ObjectState = ObjectState.Added;
                foreach (var item in order.OrderDetails)
                {
                    item.OrderId = order.Id;
                    item.ObjectState = ObjectState.Added;
                }
                _orderService.InsertOrUpdateGraph(order);
                _unitOfWork.SaveChanges();
                if (Request.IsAjaxRequest())
                {
                    return Json(new { success = true }, JsonRequestBehavior.AllowGet);
                }
                DisplaySuccessMessage("Has append a Order record");
                return RedirectToAction("Index");
            }

            if (Request.IsAjaxRequest())
            {
                var modelStateErrors = String.Join("", this.ModelState.Keys.SelectMany(key => this.ModelState[key].Errors.Select(n => n.ErrorMessage)));
                return Json(new { success = false, err = modelStateErrors }, JsonRequestBehavior.AllowGet);
            }
            DisplayErrorMessage();
            return View(order);
        }

        // GET: Orders/Edit/5
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Order order = _orderService.Find(id);
            if (order == null)
            {
                return HttpNotFound();
            }
            return View(order);
        }

        // POST: Orders/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        //[ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "OrderDetails,Id,Customer,ShippingAddress,OrderDate")] Order order)
        {
            if (ModelState.IsValid)
            {
                order.ObjectState = ObjectState.Modified;
                foreach (var item in order.OrderDetails)
                {
                    item.OrderId = order.Id;
                    //set ObjectState with conditions
                    if (item.Id <= 0)
                        item.ObjectState = ObjectState.Added;
                    else
                        item.ObjectState = ObjectState.Modified;
                }

                _orderService.InsertOrUpdateGraph(order);

                _unitOfWork.SaveChanges();
                if (Request.IsAjaxRequest())
                {
                    return Json(new { success = true }, JsonRequestBehavior.AllowGet);
                }
                DisplaySuccessMessage("Has update a Order record");
                return RedirectToAction("Index");
            }
            if (Request.IsAjaxRequest())
            {
                var modelStateErrors = String.Join("", this.ModelState.Keys.SelectMany(key => this.ModelState[key].Errors.Select(n => n.ErrorMessage)));
                return Json(new { success = false, err = modelStateErrors }, JsonRequestBehavior.AllowGet);
            }
            DisplayErrorMessage();
            return View(order);
        }

        // GET: Orders/Delete/5
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Order order = _orderService.Find(id);
            if (order == null)
            {
                return HttpNotFound();
            }
            return View(order);
        }

        // POST: Orders/Delete/5
        [HttpPost, ActionName("Delete")]
        //[ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            Order order = _orderService.Find(id);
            _orderService.Delete(order);
            _unitOfWork.SaveChanges();
            if (Request.IsAjaxRequest())
            {
                return Json(new { success = true }, JsonRequestBehavior.AllowGet);
            }
            DisplaySuccessMessage("Has delete a Order record");
            return RedirectToAction("Index");
        }

        // Get Detail Row By Id For Edit
        // Get : Orders/EditOrderDetail/:id
        [HttpGet]
        public ActionResult EditOrderDetail(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            var orderdetailRepository = _unitOfWork.Repository<OrderDetail>();
            var orderdetail = orderdetailRepository.Find(id);

            var orderRepository = _unitOfWork.Repository<Order>();
            var productRepository = _unitOfWork.Repository<Product>();

            if (orderdetail == null)
            {
                ViewBag.OrderId = new SelectList(orderRepository.Queryable(), "Id", "Customer");
                ViewBag.ProductId = new SelectList(productRepository.Queryable(), "Id", "Name");

                //return HttpNotFound();
                return PartialView("_OrderDetailEditForm", new OrderDetail());
            }
            else
            {
                ViewBag.OrderId = new SelectList(orderRepository.Queryable(), "Id", "Customer", orderdetail.OrderId);
                ViewBag.ProductId = new SelectList(productRepository.Queryable(), "Id", "Name", orderdetail.ProductId);

            }
            return PartialView("_OrderDetailEditForm", orderdetail);

        }

        // Get Create Row By Id For Edit
        // Get : Orders/CreateOrderDetail
        [HttpGet]
        public ActionResult CreateOrderDetail()
        {
            var orderRepository = _unitOfWork.Repository<Order>();
            ViewBag.OrderId = new SelectList(orderRepository.Queryable(), "Id", "Customer");
            var productRepository = _unitOfWork.Repository<Product>();
            ViewBag.ProductId = new SelectList(productRepository.Queryable(), "Id", "Name");
            return PartialView("_OrderDetailEditForm");

        }

        // Post Delete Detail Row By Id
        // Get : Orders/DeleteOrderDetail/:id
        [HttpPost, ActionName("DeleteOrderDetail")]
        public ActionResult DeleteOrderDetailConfirmed(int id)
        {
            var orderdetailRepository = _unitOfWork.Repository<OrderDetail>();
            orderdetailRepository.Delete(id);
            _unitOfWork.SaveChanges();
            if (Request.IsAjaxRequest())
            {
                return Json(new { success = true }, JsonRequestBehavior.AllowGet);
            }
            DisplaySuccessMessage("Has delete a Order record");
            return RedirectToAction("Index");
        }

        // Get : Orders/GetOrderDetailsByOrderId/:id
        [HttpGet]
        public ActionResult GetOrderDetailsByOrderId(int id)
        {
            var orderdetails = _orderService.GetOrderDetailsByOrderId(id);
            if (Request.IsAjaxRequest())
            {
                return Json(orderdetails.Select(n => new { OrderCustomer = n.Order.Customer, ProductName = n.Product.Name, Id = n.Id, ProductId = n.ProductId, Qty = n.Qty, Price = n.Price, Amount = n.Amount, OrderId = n.OrderId }), JsonRequestBehavior.AllowGet);
            }
            return View(orderdetails);

        }

        private void DisplaySuccessMessage(string msgText)
        {
            TempData["SuccessMessage"] = msgText;
        }

        private void DisplayErrorMessage()
        {
            TempData["ErrorMessage"] = "Save changes was unsuccessful.";
        }

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

Popup Modal编辑子表数据代码

<script type="text/javascript">

    var currentrowindex = -1;

    function deleteOrderDetail(id) {
        var url = ‘@Url.Action("DeleteOrderDetail")‘;
        bootbox.dialog({
            message: "Are you sure delete " + id,
            title: "Delete OrderDetail ",
            buttons: {
                Cancel: {
                    label: "Cancel",
                    className: "btn-default",
                    callback: function () {

                    }
                },
                OK: {
                    label: "OK",
                    className: "btn-success",
                    callback: function () {
                        $.post(url, { id: id }, function (data) {
                            $orderdetailstable.bootstrapTable(‘remove‘, { field: ‘Id‘, values: [id] });
                            //console.log(‘remove‘ + row.Id);
                        });
                    }
                }
            }
        });
    }

    function orderdetailsrowindexFormatter(value, row, index) {
        return index + 1;
    }
    function orderdetailsactionFormatter(value, row, index) {
        return [
            ‘<a class="edit" id="orderdetailsedit" href="javascript:void(0)" title="Add">‘,
            ‘<i class="glyphicon glyphicon-edit"></i>‘,
            ‘</a>  ‘,
            ‘ <a class="remove" id="orderdetailsremove" href="javascript:void(0)" title="Remove">‘,
            ‘<i class="glyphicon glyphicon-remove"></i>‘,
            ‘</a>‘
        ].join(‘‘);
    }

    window.actionEvents = {
        ‘click #orderdetailsedit‘: function (e, value, row, index) {
            currentrowindex = index;
            var url = "/Orders/EditOrderDetail"
            $.get(url + ‘/‘ + row.Id, function (data) {
                $(‘#orderdetailformModal-body‘).html(data);
                if (row.Id > 0) {
                    //var id = $(‘#Id‘,‘#orderdetailformModal-body‘);
                    //id.val(row.Id);
                    //var productid = $(‘#ProductId‘,‘#orderdetailformModal-body‘);
                    //productid.val(row.ProductId);
                    //var qty = $(‘#Qty‘,‘#orderdetailformModal-body‘);
                    //qty.val(row.Qty);
                    //var price = $(‘#Price‘,‘#orderdetailformModal-body‘);
                    //price.val(row.Price);
                    //var amount = $(‘#Amount‘,‘#orderdetailformModal-body‘);
                    //amount.val(row.Amount);
                    //var orderid = $(‘#OrderId‘,‘#orderdetailformModal-body‘);
                    //orderid.val(row.OrderId);
                } else {
                    var id = $(‘#Id‘, ‘#orderdetailformModal-body‘);
                    id.val(row.Id);
                    var productid = $(‘#ProductId‘, ‘#orderdetailformModal-body‘);
                    productid.val(row.ProductId);
                    var qty = $(‘#Qty‘, ‘#orderdetailformModal-body‘);
                    qty.val(row.Qty);
                    var price = $(‘#Price‘, ‘#orderdetailformModal-body‘);
                    price.val(row.Price);
                    var amount = $(‘#Amount‘, ‘#orderdetailformModal-body‘);
                    amount.val(row.Amount);
                    var orderid = $(‘#OrderId‘, ‘#orderdetailformModal-body‘);
                    orderid.val(row.OrderId);

                }
                $(‘#orderdetailformModal‘).modal(‘toggle‘);
            });
        },
        ‘click #orderdetailsremove‘: function (e, value, row, index) {
            if (row.Id > 0) {
                deleteOrderDetail(row.Id);
            } else {
                $orderdetailstable.bootstrapTable(‘remove‘, {
                    field: ‘$index‘,
                    values: [index]
                });
            }
        }
    };

    $(function () {
        $orderdetailstable = $(‘#orderdetails-table‘).bootstrapTable({
            data: []
        });
        if (ObjectState == "Modified") {
            orderid = $(‘#Id‘).val();
            var url = ‘/Orders/GetOrderDetailsByOrderId/‘ + orderid;
            $.get(url, function (data) {
                //console.log(data);
                $orderdetailstable.bootstrapTable(‘load‘, data)
            })

        }

        $(‘#addorderdetailsbutton‘).on(‘click‘, function (e) {
            if ($("form").valid()) {
                currentrowindex = -1;
                var url = "/Orders/CreateOrderDetail"
                $.get(url, function (data) {
                    //console.log(data);
                    var index = -1;
                    $(‘#orderdetailformModal-body‘).html(data);
                    $(‘#Id‘, ‘#orderdetailformModal-body‘).val(0);
                    $(‘#OrderId‘, ‘#orderdetailformModal-body‘).val(orderid);
                    $(‘#orderdetailformModal‘).modal(‘toggle‘);
                });
            }
            e.preventDefault();
            //Return false regardless of validation to stop form submitting
            //prior to ajax doing its thing
            return false;
        })

        $(‘#orderdetailconfirmbutton‘).on(‘click‘, function (e) {
            $("form").removeData("validator");
            $("form").removeData("unobtrusiveValidation");
            $.validator.unobtrusive.parse("form");
            if (!$(‘form‘).valid()) {
                e.preventDefault();
                return false;
            }
            var ordercustomer = $(‘#OrderId :selected‘, ‘#orderdetailformModal-body‘).text();
            var productname = $(‘#ProductId :selected‘, ‘#orderdetailformModal-body‘).text();
            var id = $(‘#Id‘, ‘#orderdetailformModal-body‘).val();
            var productid = $(‘#ProductId :selected‘, ‘#orderdetailformModal-body‘).val();

            var qty = $(‘#Qty‘, ‘#orderdetailformModal-body‘).val();
            var price = $(‘#Price‘, ‘#orderdetailformModal-body‘).val();
            var amount = $(‘#Amount‘, ‘#orderdetailformModal-body‘).val();
            var orderid = $(‘#OrderId :selected‘, ‘#orderdetailformModal-body‘).val();

            var orderdetail = {
                OrderCustomer: ordercustomer,
                ProductName: productname,
                Id: id,
                ProductId: productid,

                Qty: qty,
                Price: price,
                Amount: amount,
                OrderId: orderid,

                ObjectState: ‘Added‘
            }
            if (currentrowindex == ‘-1‘) {
                $orderdetailstable.bootstrapTable(‘append‘, orderdetail);
            } else {
                $orderdetailstable.bootstrapTable(‘updateRow‘, { index: currentrowindex, row: orderdetail });
            }

            $(‘#orderdetailformModal‘).modal(‘toggle‘);
        });

    });

</script>

  

所有代码都是根据Entity 类型 和字段名进行生成,理论上针对业务系统都可以模板化,只要模式定下来什么代码都可以生成。

时间: 2024-10-05 23:50:25

MVC 5 Scaffolder + EntityFramework+UnitOfWork Pattern 代码生成工具集成Visual Studio 2013的相关文章

MVC 5 Scaffolder + EntityFramework+UnitOfWork Pattern 代码生成工具

MVC 5 Scaffolder + EntityFramework+UnitOfWork Pattern 代码生成工具集成Visual Studio 2013 MVC 5 Scaffolder + EntityFramework+UnitOfWork Pattern 代码生成工具 经过一个多星期的努力总算完成了单表,多表关联(一对多,多对一)的增删改查的代码生成,基本上可以实现不用添加任何代码完成对数据表的操作. 下个阶段打算集成.net 4.5的认证和授权已经用户注册和角色管理 一旦有更好的

BEGINNING SHAREPOINT&#174; 2013 DEVELOPMENT 第3章节--SharePoint 2013 开发人员工具 使用Visual Studio 2012开发SharePoint

BEGINNING SHAREPOINT? 2013 DEVELOPMENT 第3章节--SharePoint 2013 开发人员工具 使用Visual Studio 2012开发SharePoint应用程序 VS2012带有标准系列的工程级和项目级模板,使得SP开发更加简单更加强大.使用SP2010你可以应用VS2010做大量开发,使用VS2012,现在你可以有很多新的功能和选择. 微软带了标准系列的工程级模板,开箱即用,附带额外系列的工程项目模板来帮助你进行开发.例如,你可以创建SP2013

Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用

Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用 Grunt和Gulp是Javascript世界里的用来做自动压缩.Typescript编译.代码质量lint工具.css预处理器的构建工具,它帮助开发者处理客户端开发中的一些烦操重复性的工作.Grunt和Gulp都在Visual studio 2015中得到支持.ASP.NET 项目模板默认使用Gulp. Grunt和Gulp Grunt和Gulp有什么区别?Gulp虽然是稍微晚一点登场的,但是它因crisp pe

【MVC 4】4.MVC 基本工具(Visual Studio 的单元测试、使用Moq)

 作者:[美]Adam Freeman      来源:<精通ASP.NET MVC 4> 3.Visual Studio 的单元测试 有很多.NET单元测试包,其中很多是开源和免费的.本文打算使用 Visual Studio 附带的内建单元测试支持,但其他一些.NET单元测试包也是可用的. 为了演示Visual Studio的单元测试支持,本例打算对示例项目添加一个 IDiscountHelper 接口的新实现. 在 Models 文件夹下新建类文件 MinimumDiscountHelpe

MVC 基本工具(Visual Studio 的单元测试、使用Moq)

3.Visual Studio 的单元测试 有很多.NET单元测试包,其中很多是开源和免费的.本文打算使用 Visual Studio 附带的内建单元测试支持,但其他一些.NET单元测试包也是可用的. 为了演示Visual Studio的单元测试支持,本例打算对示例项目添加一个 IDiscountHelper 接口的新实现. 在 Models 文件夹下新建类文件 MinimumDiscountHelper.cs : namespace EssentiaTools.Models { public

ASP.NET5之客户端开发:Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用

Grunt和Gulp是Javascript世界里的用来做自动压缩.Typescript编译.代码质量lint工具.css预处理器的构建工具,它帮助开发者处理客户端开发中的一些烦操重复性的工作.Grunt和Gulp都在Visual studio 2015中得到支持.ASP.NET 项目模板默认使用Gulp. Grunt和Gulp Grunt和Gulp有什么区别?Gulp虽然是稍微晚一点登场的,但是它因crisp performance和优雅的语法受到欢迎.与Grunt不同,Grunt往往在硬盘上是

Win10开发必备工具:Visual Studio 2015正式版下载

7月21日凌晨最新消息,面向大众用户的Visual Studio 2015集成开发工具正式版免费试用版已经推出.本文帮大家汇总一下简体中文社区版.专业版以及企业版在线安装版以及ISO离线安装镜像下载地址. Visual Studio Community 2015简体中文版(社区版,针对个人免费): http://download.microsoft.com/download/B/4/8/B4870509-05CB-447C-878F-2F80E4CB464C/vs2015.com_chs.iso

尝试linux下的debug工具: Visual studio

参考: https://blogs.msdn.microsoft.com/vcblog/2016/03/30/visual-c-for-linux-development/linux下面 sudo apt-get install openssh-server g++ gdb gdbserverWIndoiws下面 Launch the Visual Studio 2017 installer and start a new installation or Modify an existing o

Visual Studio 2013 IIS Express使用域名调试mvc程序

1.编辑applicationhost.config文件 启动vs2013,在右下角IIS Express图标中右击,显示如图,点击框中菜单. 找到你的启动项,点击1,然后点击2,这是应该会有编辑器打开applicationhost.config文件.如果没有自行复制打开,进行编辑. 使用查找,输入你的启动项项目,然后在bindings中进行编辑,如我的要修改为*:80:xinxinran.me 2.修改hosts文件. 修改C:\Windows\System32\drivers\etc\hos