在之前的一个开发项目中,因为公司战略发展,引用了这个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的约定大于规范的开发思路

 var TopeveryBase = Base.extend({
/*构造方法*/
constructor: function () {
},
/*初始化表格*/
initGrid: function (options) {
options = $.extend({}, { id: "grid", width: "100%", height: "600", method: "post", singleSelect: true }, options || {});
if (options.url == null) {
options.url = $("#" + options.id).attr("url");
}
if (typeof (options.url) == "undefined") {
options.url = $("#" + options.id).attr("turl");
}
if ($("#" + options.id).attr("singleSelect") === "false") {
options.singleSelect = true;
}
var gridParm = {
idField: "id",
fitColumns: true,
loadMsg: false,
nowrap: false,
queryParams: options.queryParams,
method: options.method,
singleSelect: options.singleSelect,
iconCls: "icon-save",
striped: true,
height: options.height,
animate: true,
collapsible: true,
border: true,
rownumbers: true, //行号
pagination: options.pagination || true, //分页控件
pageSize: 10,
pageList: [1, 10, 20, 50, 100, 250, 500, 1000],
sortName: "Id",
sortOrder: "desc",
toolbar: '#toolbarWrap',
onLoadSuccess: function (data) {
$(this).datagrid('doCellTip', { 'max-width': '400px', 'delay': 500 });
$(this).datagrid("clearSelections").datagrid("clearChecked");
},
loader: function (param, success, error) {
if (typeof (param.sort) == "undefined") {
param.sort = "Id";
}
if (typeof (param.order) == "undefined") {
param.order = "desc";
}
var postParm = {
PageIndex: param.page,
PageCount: param.rows,
sort: param.sort,
order: param.order
};
if (options.queryParams != null) {
postParm = $.extend({}, postParm, options.queryParams);
}
postParm = $.extend({}, postParm);
var formpostdata = topevery.form2Json("selectFrom");
postParm = $.extend({}, postParm, formpostdata);
/* 获取详情*/
easyuiBase.ajax({
type: "post",
url: options.url,
data: JSON.stringify(postParm),
loading: false
}, function (data) {
if (data.Success) {
var array = new Object();
array.rows = data.Result.Rows;
array.total = data.Result.Total;
success(array);
} else {
error();
}
}, true);
}
};
for (var i = 0; i < $(".easyui-textbox").length; i++) {
$("#" + $('.easyui-textbox').eq(i)[0].id + "").textbox({
inputEvents: $.extend({}, $.fn.textbox.defaults.inputEvents, {
keyup: function (event) {
if (event.keyCode === 13) {
User.loadInfo();
}
}
})
});
};
if (options.columns != null) {
gridParm.columns = options.columns;
}
$("#" + options.id).datagrid(gridParm);
},
/**
*
* @param {} id 修改时所用查询编号
* @param {} 加载修改查看 callback 回调函数
* @param {} 新增修改之后 callback1 回调函数
* @param {} options 参数集合
* @returns {}
*/
View: function (id, callback, callback1, options) {
if (id > 0) {
options = $.extend({}, { id: "edit", btn: "save", sumbit: "sumbitForm", grid: "grid" }, options || {});
} else {
options = $.extend({}, { id: "add", btn: "save", sumbit: "sumbitForm", grid: "grid" }, options || {});
}
var urlstring = $("#" + options.id).attr("url").split(',');
//geturl 获取修改需要加载信息
if (options.geturl == null) {
if (urlstring.length > 0) {
options.geturl = urlstring[1];
}
}
///新增or修改url
if (options.url == null) {
options.url = urlstring[0];
}
$("#" + options.sumbit).form("reset");
if (id !== "undefined" && id != null) {
//修改时 数据加载到页面
easyuiBase.ajax({
type: "POST",
url: options.geturl,
data: JSON.stringify({ Id: id }),
loading: false
}, function (data) {
if (data.Success) {
var row = data.Result;
$("#" + options.sumbit).form("load", row);
callback(row);
} else {
error();
}
});
}
//弹出层dialog Id
if (options.name == null) {
options.name = $("#" + options.id).attr("name");
}
$("#" + options.name).dialog('open');
$("#" + options.btn).click(function () {
if ($("#" + options.sumbit).form('validate') === false) {
return;
}
easyuiBase.ajax({
type: "post",
url: options.url,
data: JSON.stringify(easyuiBase.form2Json(options.sumbit)),
loading: false
}, function (data) {
if (data.Success) {
if (data.Result.IsSuccess) {
$("#" + options.name).dialog('close');
try {
topeveryMessage.show(data.Result.Message);
} catch (e) {
}
$("#" + options.sumbit).form("reset");
$("#" + options.grid).datagrid("load");
$("#" + options.btn).unbind();
if (callback1 !== "undefined" && callback1 != null) {
callback1(data.Result);
}
} else {
try {
topeveryMessage.show(data.Result.Message);
} catch (e) { }
}
} else {
error();
}
});
});
},
//删除
delData: function (options, callback) {
options = $.extend({}, { id: "delete", grid: "grid" }, options || {});
var urlstring = $("#" + options.id).attr("url");
///删除url
if (options.url == null) {
options.url = urlstring;
}
var arrRows = $('#' + options.grid).datagrid('getSelections');
if (arrRows.length === 0) {
$.messager.alert('提示', '请选择一条需要删除的记录!', 'info');
} else {
var ids = [];
$.each(arrRows, function () {
ids.push(this.Id);
});
easyuiBase.ajax({
type: "post",
url: options.url,
data: JSON.stringify({ "Ids": ids.join() }),
contentType: "application/json",
loading: false
}, function (data) {
if (data.Success) {
if (data.Result.IsSuccess) {
try {
$("#" + options.grid).datagrid('reload');
} catch (e) { }
callback();
topeveryMessage.show(data.Result.Message);
} else {
try {
topeveryMessage.show(data.Result.Message);
} catch (e) { }
}
} else {
error();
}
}, true);
}
},
///搜索
loadInfo: function (options) {
options = $.extend({}, { grid: "grid" }, options || {});
$('#' + options.grid).datagrid('load'); //点击搜索
},
//清空
empty: function (options) {
options = $.extend({}, { sumbit: "selectFrom", grid: "grid", tree: "tree" }, options || {});
$("#" + options.sumbit).form("reset");
$("#" + options.grid).datagrid("load");
$('#' + options.tree).find('.tree-node-selected').removeClass('tree-node-selected');
}
});

TopeveryBase

 var DirectoryManageList;
var base;
var load;
var defaultDeptId;
var tree;
$(function () {
DirectoryManageList = TopeveryBase.extend({
});
load = function (row) {
$("#LoginPassword1").textbox("setValue", row.LoginPassword);
}
base = new DirectoryManageList();
var columns = [
[
{ field: "Id", checkbox: true },
{ width: 100, title: '用户名', field: 'Name', align: 'center' },
{ width: 100, title: '登录名', field: 'LoginName', align: 'center' },
{ width: 100, title: '电话', field: 'TelNum', align: 'center' },
{
width: 100, title: '默认部门', field: 'DefaultDeptName', align: 'center'
},
{ width: 100, title: '邮件', field: 'Email', align: 'center' },
{ width: 80, title: '手机', field: 'MobileNum', align: 'center' },
{
title: '操作',
field: 'Action',
width: '15%',
align: 'center',
formatter: function (value, row, index) {
var c = ' <a href="#" class="easyui-modifyoperate" onclick="base.View(' + row.Id + ',load)">修改</a>';
var d = ' <a href="#" class="easyui-modifyoperate" onclick="base.View(' + row.Id + ',load)">部门角色权限</a>';
return c + "&nbsp"+d;
}
}
]
];
base.initGrid({ columns: columns });
$('#DefaultDeptId').combotree({
url: "/Dept/GetDeptList",
panelHeight: 'auto',
panelMaxHeight: 150,
loadFilter: function (data) {
var object = new Array;
object.push({ id: 0, text: " ", children: data, state: "0", attributes: "" });
return object;
}
}),
$('#tree').tree({
url: "/Dept/GetDeptList",
loadFilter: function (data) {
var object = new Array;
object.push({ id: 0, text: "部门树", children: data, state: "0", attributes: "" });
return object;
},
onClick: function (node) { //单击事件
defaultDeptId = node.id;
$("#defaultDeptId").val(defaultDeptId);
base.loadInfo();
}
});
});

实例Js

@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 = ; 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 - ) * pageCount).Take(pageCount);
var row = await query.ToListAsync();
var data = row.MapTo<List<TF>>();
return new PagedResultOutputDto<TF>(count, data);
}
 /// <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.Id
where userDept.DeptId == input.DeptId
select 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;
}

4.最后总结是,也许我自己也不知道我的目的是什么,弄这个的意义是什么,但是做自己想做的,想到了就去做吧。

5.发现问题,然后思考问题,最后去解决这个问题!

百度云地址:http://pan.baidu.com/s/1c2cjpLm  提取码:4b66

ABP框架实战 1.基础信息维护的更多相关文章

  1. ABP框架实践基础篇之开发UI层

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 说明 其实最开始写的,就是这个ABP框架实践基础篇.在写这篇博客之前,又回头复习了一下ABP框架的理论,如果你还没学习,请查看AB ...

  2. ABP框架搭建项目系列教程基础版完结篇

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 经过前面十二篇的基础教程,现在终于该做个总结了. 回顾 第一篇,我们建议新手朋友们先通过ABP官网的启动模板生成解决方案,因为这样 ...

  3. 小白学 Python 爬虫(40):爬虫框架 Scrapy 入门基础(七)对接 Selenium 实战

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  4. 小白学 Python 爬虫(41):爬虫框架 Scrapy 入门基础(八)对接 Splash 实战

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  5. ABP框架之——数据访问基础架构

    大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享阅读心得,希望我的文章能成为你成长路上的一块垫脚石,我们一起精进. 几乎所有的业务应用程序都要适用一种数据库基础架构,用来实现数据访问逻辑,以便从数 ...

  6. ABP框架之——数据访问基础架构(下)

    大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的一块垫脚石,我们一起精进. EF Core集成 EF Core是微软的ORM,可以使用它与主流的数据库提供商 ...

  7. 查看abp框架异常信息

    abp框架中经常出现{"message":"An error has occurred."}的异常,并且也进入不到方法中,如果想查看详细信息,可以采用下面方法 ...

  8. ABP框架展示异常信息

    接触ABP框架有一段时间了,也遇到了一些问题,看了官网文档,但是或许是看的不够细致的原因,实际开发中还是遇到了一些问题,耗费了时间去处理,回头一看,原来文档中早已提及. 开发环境:ABP+MPA模式+ ...

  9. ABP框架和NET CORE实战

    http://www.fishpro.com.cn/2017/09/ ABP实战系列 ABP实战 ABP-第一个Asp.net core 示例(7)AutoMapper的使用 我们为什么需要使用DDD ...

随机推荐

  1. 微信小程序 网络请求之re.request 和那些坑

    微信小程序有四种网络请求类型,下面只详细介绍普通HTTPS请求(wx.request) 普通HTTPS请求(wx.request) 上传文件(wx.uploadFile) 下载文件(wx.downlo ...

  2. BZOJ 1033: [ZJOI2008]杀蚂蚁antbuster(模拟)

    坑爹的模拟题QAQ DEBUG多了1kb QAQ 按题意做就行了 注意理解题意啊啊啊啊 尼玛输出忘换行wa了3次QAQ CODE: #include<cstdio>#include< ...

  3. OpenCv 2.4.9 (一) Mat基础结构&如何遍历图片

    前言 因为对图像方面感兴趣,所以有空学学OpenCV的使用,并且希望以此为引子,带领自己入门图像领域. 先post上几个参考网站,上面有完整源码: http://docs.opencv.org/2.4 ...

  4. css4激动人心的新特性及浏览器支持度

    CSS3的选择器提供了很多像:nth-child这样有用的选择器,并且得到浏览器支持.CSS的第四代 选择器CSS4选择器),经我们带来了更多有用的选择器. 1.否定伪类:not 否定伪类选择器其实在 ...

  5. HTML 5入门知识(三)

    <canvas>标签 在网页中使用canvas元素,像使用其他HTML标签一样简单,然后利用JavaScript脚本调用绘图API,绘制各种图形.canvas拥有多种绘制路径.矩形.圆形. ...

  6. 【DOORS】如何基于DOORS实施需求管理

    引言 IBM Rational DOORS,简称DOORS,是被业界广泛认可的需求管理工具,在国内外需求管理领域具有较高的市场占有率.需求管理作为传统的工程领域,理论发展相对成熟和健全.随着越来越多的 ...

  7. Oracle 重建控制文件

    前些天在做Oracle数据库恢复测试时,因为一些异常操作导致控制文件出了问题,数据库无法正常使用,这里记录一下重建控制文件的操作 一.使用sysdba用户登入数据库 此时普通用户已无法链接数据库 二. ...

  8. HTML5周记(一)

    各位开发者朋友和技术大神大家好!博主刚开始学习html5 ,自本周开始会每周更新技术博客,与大家分享每周所学.鉴于博主水品有限,如发现有问题的地方欢迎大家指正,有更好的意见和建议可在评论下方发表,我会 ...

  9. 1593: [Usaco2008 Feb]Hotel 旅馆

    1593: [Usaco2008 Feb]Hotel 旅馆 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 391  Solved: 228[Submit ...

  10. 1230: [Usaco2008 Nov]lites 开关灯

    1230: [Usaco2008 Nov]lites 开关灯 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1162  Solved: 589[Sub ...