ABP框架实战 1.基础信息维护
在之前的一个开发项目中,因为公司战略发展,引用了这个ABP开源框架作为新项目的基础版本,由于客户的要求需要迁移旧系统数据,以及其他的一些原因,数据库采用了Oracle数据库管理。所以引用了Dapper这个ORM框架作为数据访问的扩展,在前期的开发过程中,碰到过很多的坑,但是通过学习阳光铭睿,
tkb至简这两位博主写的一系列文章,以及其他同事的帮助下,慢慢的熟悉了ABP框架的一些原理以及思路。
下面简单介绍一下这个Abp框架以及一些学习的资料:
ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称。
ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WEB应用程序框架和项目模板。
ASP.NET Boilerplate 基于DDD的经典分层架构思想,实现了众多DDD的概念(但没有实现所有DDD的概念)。
ABP的官方网站:http://www.aspnetboilerplate.com
ABP在Github上的开源项目:https://github.com/aspnetboilerplate
阳光铭睿:http://www.cnblogs.com/mienreal/p/4528470.html
tkb至简:http://www.cnblogs.com/farb/p/ABPTheory.html
1.在历经了7个月(1607-1701)的时间,项目前两期的开发工作也算是全部的完成了,幸运的我一直留到了最后,负责后续功能以及App对接的开发,以及试运行问题过程中客户提出问题的维护。
2.在后面的某个日期中,全体这个项目的参与人员进行了一次会议总结,总体来说还算不错吧。
3.在后来的某一天,自己想要在最基础的框架上面弄一个基础的框架管理,关于简单的用户-部门-角色-权限管理这一块,可能还有很多地方没有弄完善的地方,目前还存在一部分的,但是简单来说也能满足一些简单的管理需求吧。(因为在这个项目开发过程中,这一块的数据管理是用的之前公司成熟的一套PMI框架,引用的单点登录,所以只能够参照他的思路来弄)
项目总体框架:
这里链接一个同事写的一篇文章吧,上面有关于这个项目框架的一些详细介绍http://www.cnblogs.com/yuanbeier/articles/6394484.html
下面讲一下自己弄这个的开发过程吧。
a.建立PDM,数据对应关系
b.生成数据库,以及实体,其实这里在ABP最初始的做法是采用Code First模式先建立实体在生成数据结构,个人觉得看自己习惯吧。
c.创立对应的Application Services, Controller,View,Js
d.然后就是具体的编码业务完成了,这个前段采用最快速的easyui开发,在这里参考了之前一个同事写的一个基类,然后在其思路上重新了写了一个基类,在这里的思路也正是考虑到ABP的约定大于规范的开发思路
![](/assets/blank.gif)
![](/assets/blank.gif)
1 var TopeveryBase = Base.extend({ 2 /*构造方法*/ 3 constructor: function () { 4 }, 5 /*初始化表格*/ 6 initGrid: function (options) { 7 options = $.extend({}, { id: "grid", width: "100%", height: "600", method: "post", singleSelect: true }, options || {}); 8 if (options.url == null) { 9 options.url = $("#" + options.id).attr("url"); 10 } 11 if (typeof (options.url) == "undefined") { 12 options.url = $("#" + options.id).attr("turl"); 13 } 14 if ($("#" + options.id).attr("singleSelect") === "false") { 15 options.singleSelect = true; 16 } 17 var gridParm = { 18 idField: "id", 19 fitColumns: true, 20 loadMsg: false, 21 nowrap: false, 22 queryParams: options.queryParams, 23 method: options.method, 24 singleSelect: options.singleSelect, 25 iconCls: "icon-save", 26 striped: true, 27 height: options.height, 28 animate: true, 29 collapsible: true, 30 border: true, 31 rownumbers: true, //行号 32 pagination: options.pagination || true, //分页控件 33 pageSize: 10, 34 pageList: [1, 10, 20, 50, 100, 250, 500, 1000], 35 sortName: "Id", 36 sortOrder: "desc", 37 toolbar: '#toolbarWrap', 38 onLoadSuccess: function (data) { 39 $(this).datagrid('doCellTip', { 'max-width': '400px', 'delay': 500 }); 40 $(this).datagrid("clearSelections").datagrid("clearChecked"); 41 }, 42 loader: function (param, success, error) { 43 if (typeof (param.sort) == "undefined") { 44 param.sort = "Id"; 45 } 46 if (typeof (param.order) == "undefined") { 47 param.order = "desc"; 48 } 49 var postParm = { 50 PageIndex: param.page, 51 PageCount: param.rows, 52 sort: param.sort, 53 order: param.order 54 }; 55 if (options.queryParams != null) { 56 postParm = $.extend({}, postParm, options.queryParams); 57 } 58 postParm = $.extend({}, postParm); 59 var formpostdata = topevery.form2Json("selectFrom"); 60 postParm = $.extend({}, postParm, formpostdata); 61 /* 获取详情*/ 62 easyuiBase.ajax({ 63 type: "post", 64 url: options.url, 65 data: JSON.stringify(postParm), 66 loading: false 67 }, function (data) { 68 if (data.Success) { 69 var array = new Object(); 70 array.rows = data.Result.Rows; 71 array.total = data.Result.Total; 72 success(array); 73 } else { 74 error(); 75 } 76 }, true); 77 } 78 }; 79 for (var i = 0; i < $(".easyui-textbox").length; i++) { 80 $("#" + $('.easyui-textbox').eq(i)[0].id + "").textbox({ 81 inputEvents: $.extend({}, $.fn.textbox.defaults.inputEvents, { 82 keyup: function (event) { 83 if (event.keyCode === 13) { 84 User.loadInfo(); 85 } 86 } 87 }) 88 }); 89 }; 90 if (options.columns != null) { 91 gridParm.columns = options.columns; 92 } 93 $("#" + options.id).datagrid(gridParm); 94 }, 95 /** 96 * 97 * @param {} id 修改时所用查询编号 98 * @param {} 加载修改查看 callback 回调函数 99 * @param {} 新增修改之后 callback1 回调函数 100 * @param {} options 参数集合 101 * @returns {} 102 */ 103 View: function (id, callback, callback1, options) { 104 if (id > 0) { 105 options = $.extend({}, { id: "edit", btn: "save", sumbit: "sumbitForm", grid: "grid" }, options || {}); 106 } else { 107 options = $.extend({}, { id: "add", btn: "save", sumbit: "sumbitForm", grid: "grid" }, options || {}); 108 } 109 var urlstring = $("#" + options.id).attr("url").split(','); 110 //geturl 获取修改需要加载信息 111 if (options.geturl == null) { 112 if (urlstring.length > 0) { 113 options.geturl = urlstring[1]; 114 } 115 } 116 ///新增or修改url 117 if (options.url == null) { 118 options.url = urlstring[0]; 119 } 120 $("#" + options.sumbit).form("reset"); 121 if (id !== "undefined" && id != null) { 122 //修改时 数据加载到页面 123 easyuiBase.ajax({ 124 type: "POST", 125 url: options.geturl, 126 data: JSON.stringify({ Id: id }), 127 loading: false 128 }, function (data) { 129 if (data.Success) { 130 var row = data.Result; 131 $("#" + options.sumbit).form("load", row); 132 callback(row); 133 } else { 134 error(); 135 } 136 }); 137 } 138 //弹出层dialog Id 139 if (options.name == null) { 140 options.name = $("#" + options.id).attr("name"); 141 } 142 $("#" + options.name).dialog('open'); 143 $("#" + options.btn).click(function () { 144 if ($("#" + options.sumbit).form('validate') === false) { 145 return; 146 } 147 easyuiBase.ajax({ 148 type: "post", 149 url: options.url, 150 data: JSON.stringify(easyuiBase.form2Json(options.sumbit)), 151 loading: false 152 }, function (data) { 153 if (data.Success) { 154 if (data.Result.IsSuccess) { 155 $("#" + options.name).dialog('close'); 156 try { 157 topeveryMessage.show(data.Result.Message); 158 } catch (e) { 159 } 160 $("#" + options.sumbit).form("reset"); 161 $("#" + options.grid).datagrid("load"); 162 $("#" + options.btn).unbind(); 163 if (callback1 !== "undefined" && callback1 != null) { 164 callback1(data.Result); 165 } 166 } else { 167 try { 168 topeveryMessage.show(data.Result.Message); 169 } catch (e) { 170 171 } 172 } 173 } else { 174 error(); 175 } 176 }); 177 }); 178 }, 179 //删除 180 delData: function (options, callback) { 181 options = $.extend({}, { id: "delete", grid: "grid" }, options || {}); 182 var urlstring = $("#" + options.id).attr("url"); 183 ///删除url 184 if (options.url == null) { 185 options.url = urlstring; 186 } 187 var arrRows = $('#' + options.grid).datagrid('getSelections'); 188 if (arrRows.length === 0) { 189 $.messager.alert('提示', '请选择一条需要删除的记录!', 'info'); 190 } else { 191 var ids = []; 192 $.each(arrRows, function () { 193 ids.push(this.Id); 194 }); 195 easyuiBase.ajax({ 196 type: "post", 197 url: options.url, 198 data: JSON.stringify({ "Ids": ids.join() }), 199 contentType: "application/json", 200 loading: false 201 }, function (data) { 202 if (data.Success) { 203 if (data.Result.IsSuccess) { 204 try { 205 $("#" + options.grid).datagrid('reload'); 206 } catch (e) { 207 208 } 209 callback(); 210 topeveryMessage.show(data.Result.Message); 211 } else { 212 try { 213 topeveryMessage.show(data.Result.Message); 214 } catch (e) { 215 216 } 217 } 218 } else { 219 error(); 220 } 221 }, true); 222 } 223 }, 224 ///搜索 225 loadInfo: function (options) { 226 options = $.extend({}, { grid: "grid" }, options || {}); 227 $('#' + options.grid).datagrid('load'); //点击搜索 228 }, 229 //清空 230 empty: function (options) { 231 options = $.extend({}, { sumbit: "selectFrom", grid: "grid", tree: "tree" }, options || {}); 232 $("#" + options.sumbit).form("reset"); 233 $("#" + options.grid).datagrid("load"); 234 $('#' + options.tree).find('.tree-node-selected').removeClass('tree-node-selected'); 235 } 236 });
TopeveryBase
![](/assets/blank.gif)
![](/assets/blank.gif)
1 var DirectoryManageList; 2 var base; 3 var load; 4 var defaultDeptId; 5 var tree; 6 $(function () { 7 DirectoryManageList = TopeveryBase.extend({ 8 }); 9 load = function (row) { 10 $("#LoginPassword1").textbox("setValue", row.LoginPassword); 11 } 12 base = new DirectoryManageList(); 13 var columns = [ 14 [ 15 { field: "Id", checkbox: true }, 16 { width: 100, title: '用户名', field: 'Name', align: 'center' }, 17 { width: 100, title: '登录名', field: 'LoginName', align: 'center' }, 18 { width: 100, title: '电话', field: 'TelNum', align: 'center' }, 19 { 20 width: 100, title: '默认部门', field: 'DefaultDeptName', align: 'center' 21 }, 22 { width: 100, title: '邮件', field: 'Email', align: 'center' }, 23 { width: 80, title: '手机', field: 'MobileNum', align: 'center' }, 24 { 25 title: '操作', 26 field: 'Action', 27 width: '15%', 28 align: 'center', 29 formatter: function (value, row, index) { 30 var c = ' <a href="#" class="easyui-modifyoperate" οnclick="base.View(' + row.Id + ',load)">修改</a>'; 31 var d = ' <a href="#" class="easyui-modifyoperate" οnclick="base.View(' + row.Id + ',load)">部门角色权限</a>'; 32 return c + " "+d; 33 } 34 } 35 ] 36 ]; 37 base.initGrid({ columns: columns }); 38 $('#DefaultDeptId').combotree({ 39 url: "/Dept/GetDeptList", 40 panelHeight: 'auto', 41 panelMaxHeight: 150, 42 loadFilter: function (data) { 43 var object = new Array; 44 object.push({ id: 0, text: " ", children: data, state: "0", attributes: "" }); 45 return object; 46 } 47 }), 48 $('#tree').tree({ 49 url: "/Dept/GetDeptList", 50 loadFilter: function (data) { 51 var object = new Array; 52 object.push({ id: 0, text: "部门树", children: data, state: "0", attributes: "" }); 53 return object; 54 }, 55 onClick: function (node) { //单击事件 56 defaultDeptId = node.id; 57 $("#defaultDeptId").val(defaultDeptId); 58 base.loadInfo(); 59 } 60 }); 61 });
实例Js
![](/assets/blank.gif)
![](/assets/blank.gif)
@using System.Web.Optimization <div style="width: 10%; float: left; height: 100%; background-color: #fff;"><ul id="tree"></ul> </div> <table style="width: 90%!important; float: left;" singleSelect="false" id="grid" url="UserR/GetListAsync"></table> <div id="toolbarWrap"><div class="toolbar-area"><div class="searching-area"><form name="selectFrom" id="selectFrom"><table><tr><td><input class="easyui-textbox" style="width: 120px; height: 30px;" id="Name1" name="Name" data-options="prompt:'用户名'" /><input class="easyui-textbox" style="width: 120px; height: 30px;" id="LoginName1" name="LoginName" data-options="prompt:'登录名'" /><input id="defaultDeptId" name="defaultDeptId" style="display: none;" /><a href="#" class="search-btn easyui-normalyellowbutton" onclick="base.loadInfo();">查询</a><a href="#" class="search-btn easyui-normalyellowbutton" onclick="base.empty();">清空</a></td></tr></table></form></div></div><div id="toolbar" class="toolbar operate-area-new"><a href="#" onclick="base.View();" class="easyui-normalbluebutton">新增用户</a><a href="#" onclick="base.delData();" class="easyui-normalbluebutton">删除用户</a><input type="hidden" id="edit" name="NewModifView" url="UserW/UserAddEditAsync,UserR/GetOneAsync"><input type="hidden" id="add" name="NewModifView" url="UserW/UserAddEditAsync"><input type="hidden" id="delete" url="UserW/DeleteUserAsync"></div> </div> <div class="easyui-dialog" title="新增" data-options="iconCls:'pag-list',modal:true,collapsible:false,minimizable:false,maximizable:false,resizable:false,closed:true" id="NewModifView" style="width: 700px; height: 380px; display: none;"><form id="sumbitForm" name="sumbitForm"><div class="house-lost-register-form"><input id="Id" name="Id" style="display: none;" /><p><label>用户名:</label><input type="text" class="easyui-textbox" maxlength="20" style="width: 215px; height: 30px;" id="Name" name="Name" required="required" missingMessage="用户名不能为空" /><label>登录名:</label><input type="text" class="easyui-textbox" style="width: 215px; height: 30px;" id="LoginName" name="LoginName" required="required" missingMessage="登录名不能为空" /></p><p><label>登录密码:</label><input type="text" class="easyui-textbox" style="width: 215px; height: 30px;" id="LoginPassword" name="LoginPassword" required="required" missingMessage="登录密码不能为空" /><label>重复登录密码:</label><input type="text" class="easyui-textbox" style="width: 215px; height: 30px;" id="LoginPassword1" name="LoginPassword1" required="required" missingMessage="重复登录密码不能为空" validType="equalTo['#LoginPassword']" invalidMessage="两次输入密码不匹配" /></p><p><label>默认部门:</label><input type="text" class="easyui-combotree" style="width: 215px; height: 30px;" id="DefaultDeptId" name="DefaultDeptId" /><label>电话:</label><input type="text" class="easyui-textbox" style="width: 215px; height: 30px;" id="TelNum" name="TelNum" /></p><p><label>邮件:</label><input type="text" class="easyui-textbox" style="width: 215px; height: 30px;" id="Email" name="Email" /><label>手机:</label><input type="text" class="easyui-textbox" style="width: 215px; height: 30px;" id="MobileNum" name="MobileNum" /></p><div style="padding-top: 20px; text-align: center;" id="ToView"><a href="#" class="easyui-normalbluebutton" id="save">确认</a></div></div></form> </div>@Scripts.Render("~/js/User/IndexTest.js")
View
如果是简单的增删改查,就能够通过简单的一个页面就可以完成了。
/// <summary>/// 去掉集合2中Id集合2中的数据/// </summary>/// <typeparam name="TF"></typeparam>/// <returns></returns>public IQueryable<TF> NotShorthand<TF>(List<IdInput> list, IRepository<TF> iRepository) where TF : class, IEntity<int> {var idlist = new int[list.Count];for (var i = 0; i < list.Count; i++){idlist.SetValue(list[i].Id, i);}var query = from t in iRepository.GetAll()where !(idlist).Contains(t.Id)select t;return query;}/// <summary>/// 排序 分页封装/// </summary>/// <typeparam name="T"></typeparam>/// <typeparam name="TF"></typeparam>/// <returns></returns>public async Task<PagedResultOutputDto<TF>> GetListAsync<T,TF>(IQueryable<T> query,int pageIndex,int pageCount,string sort){query = !string.IsNullOrWhiteSpace(sort) ? query.OrderBy(sort) : query.OrderBy("Id desc");var count = query.Count();query = query.Skip((pageIndex - 1) * pageCount).Take(pageCount);var row = await query.ToListAsync();var data = row.MapTo<List<TF>>();return new PagedResultOutputDto<TF>(count, data);}
![](/assets/blank.gif)
![](/assets/blank.gif)
/// <summary>/// 根据部门Id获取可以调入的人员/// </summary>/// <param name="input"></param>/// <returns></returns>public async Task<PagedResultOutputDto<UserListOutputDto>> GetNotUserAsync(DeptListInput input){var query1 = (from userDept in _userDeptRepository.GetAll()join dept in _deptRepository.GetAll() on userDept.DeptId equals dept.Idwhere userDept.DeptId == input.DeptIdselect new IdInput { Id = userDept.UserId }).ToList();var query = NotShorthand(query1, _userRepository);if (!string.IsNullOrWhiteSpace(input.Name)){query = query.Where(x => x.Name.Contains(input.Name));}var list = await GetListAsync<Zero.Core.Authorization.User, UserListOutputDto>(query, input.PageIndex, input.PageCount, input.Sorting);return list;}
View Code
4.最后总结是,也许我自己也不知道我的目的是什么,弄这个的意义是什么,但是做自己想做的,想到了就去做吧。
5.发现问题,然后思考问题,最后去解决这个问题!
百度云地址:http://pan.baidu.com/s/1c2cjpLm 提取码:4b66
转载于:https://www.cnblogs.com/wuyongfu/p/6666547.html
ABP框架实战 1.基础信息维护相关推荐
- 史上最全 Appium 自动化测试从基础到框架实战精华学习笔记(一)
本文为霍格沃兹测试学院学员学习笔记,进阶学习文末加群. 对测试人来说,Appium 是非常重要的一个开源跨平台自动化测试工具,它允许测试人员在不同的平台(iOS.Android 等)使用同一套 API ...
- 史上最全 Appium 自动化测试从入门到框架实战精华学习笔记(二)
本系列文章汇总了从 Appium 自动化测试从基础到框架高级实战中,所涉及到的方方面面的知识点精华内容(如下所示),希望对大家快速总结和复习有所帮助. Appium 自动化测试从基础到框架实战 App ...
- ABP框架搭建项目系列教程基础版
我现在要着手一个新的项目,也打算用这个框架,所以想要将我一步一步用这个框架的做项目的步骤和想法跟大家分享出来. 经过前面十二篇的基础教程,现在终于该做个总结了. 第一篇,我们建议新手朋友们先通过ABP ...
- ABP 详解系列4:ABP框架的基础配置及依赖注入讲解
ABP框架的基础配置及依赖注入讲解 这篇文章主要介绍了ABP框架的基础配置及依赖注入讲解,是ABP框架上手使用的基本,要的朋友可以参考下 配置ABP 配置是通过在自己模块的PreInitialize方 ...
- ABP框架之——数据访问基础架构
几乎所有的业务应用程序都要适用一种数据库基础架构,用来实现数据访问逻辑,以便从数据库读取或写入数据,我们还需要处理数据库事务,以确保数据源中的一致性. ABP框架可以与任何数据库兼容,同时它提供了EF ...
- ABP框架展示异常信息
接触ABP框架有一段时间了,也遇到了一些问题,看了官网文档,但是或许是看的不够细致的原因,实际开发中还是遇到了一些问题,耗费了时间去处理,回头一看,原来文档中早已提及. 开发环境:ABP+MPA模式+ ...
- abp项目怎样发布到服务器,ABP框架的基础配置及依赖注入讲解
配置ABP 配置是通过在自己模块的PreInitialize方法中来实现的 代码示例如下: ? 和orchard类似,abp框架一开始就被设计成模块化的,不同的模块可以通过abp框架来进行配置.举个例 ...
- (Java每日一谈:第四日——幸福的四象限)主流框架:Dubbo基础实战篇--Dubbo快速入门
在昨天的Dubbo基础篇中,小编对Dubbo的相关基础理论知识进行了一个详细的解释,如果大家对这一块的知识感到好奇,推荐大家可以去阅读一下小编昨天写的Dubbo相关知识点,今天小编会进行Dubbo实用 ...
- 从零起步(无需数学和Python基础)编码实现AI框架之第六节课:使用Matrix编写AI框架实战及测试
从零起步(无需数学和Python基础)编码实现AI框架之第六节课:使用Matrix编写AI框架实战及测试 本节课使用Matrix编写AI框架实战:编码实现Forward Propagation.Bac ...
- 应用程序框架实战二十二 : DDD分层架构之仓储(层超类型基础篇)
前一篇介绍了仓储的基本概念,并谈了我对仓储的一些认识,本文将实现仓储的基本功能. 仓储代表聚合在内存中的集合,所以仓储的接口需要模拟得像一个集合.仓储中有很多操作都是可以通用的,可以把这部分操作抽取到 ...
最新文章
- 不是python对文件的读操作方法的是-一文读懂Python对文件的各种操作方式-阿里云开发者社区...
- python现在第几版-多版本Python共存的配置方法
- 并发新特性—Executor 框架与线程池
- 如何保留linux中yum安装后的rpm软件包
- java servlet_Java Servlet的前100个问题
- docker web程序本地化_想要成为前端Star 吗?一首歌时间将React / Vue 应用Docker 化...
- 异步通知《来自Linux驱动程序开发实例》
- 导入要素到要素类(C++)ArcEngine开发
- php pdo 存储过程的返回所有结果,PHP_PDO 调用存储过程,返回参数问题
- android studio技巧之设置monitor窗口模式查看logcat
- 华为HG255d刷石像鬼OpenWrt,体验强大的QOS功能
- [摘]研究方法 - 实证研究
- 【数字图像处理matlab】RGB转HIS,HIS转RGB
- 一位前端新人的面试经验
- Codevs 1183 泥泞的道路
- 手机通过页面调用摄相头或选择照片压缩后并显示
- 个人微信支付宝接入GOGO支付免签系统详细教程(图文)
- 数字信号处理基础----采样定理
- 如何禁用Windows更新
- 九部比《五十度灰》更血脉喷张的电影,个个看完都会让人欲罢不能!