返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期

用户实体

用户实体代表应用的一个用户,它派生自AbpUser类,如下所示:

public class User : AbpUser<Tenant, User>
{
//add your own user properties here
}

这个类是在安装模块零时创建的。用户存储在数据库的AbpUsers表中。您可以将自定义属性添加到User类(并为更改创建数据库迁移)。

AbpUser类定义了一些基本属性。一些属性是:

  • UserName:用户的登录名,对于一个租户来说应该是唯一的。
  • EmailAddress:用户的邮箱地址。对于租户来说应该是唯一的。
  • Password:用户的哈希密码。
  • IsActive:如果用户可以登录到该应用,那么此值为true。
  • NameSurname:用户的名和姓。

还有一些属性,如角色 权限租户设置, IsEmailConfirmed等。检查AbpUser类以获取更多信息。

AbpUser类是从FullAuditedEntity继承的。这意味着它具有创建,修改和删除审计属性。这也是 软删除。所以,当我们删除一个用户时,它不会从数据库中删除,只是标记为已删除。

AbpUser类实现了 IMayHaveTenant 过滤器,以便在多租户应用程序中正常工作。

最后,用户的Id被定义为long

用户管理器

UserManager是 为用户执行域逻辑的服务:

public  class UserManager:AbpUserManager <Tenant,Role,User>
{ // ...
}

您可以注入并使用UserManager创建,删除,更新用户,授予权限,更改用户角色等等。你可以在这里添加你自己的方法。此外,您可以 根据自己的需要重写AbpUserManager基类的任何方法。

UserManager被设计为一次为单个租户工作。它适用于当前租户作为默认。我们来看看UserManager的一些用法:

public class MyTestAppService : ApplicationService
{
private readonly UserManager _userManager; public MyTestAppService(UserManager userManager)
{
_userManager = userManager;
} public void TestMethod_1()
{
//Find a user by email for current tenant
var user = _userManager.FindByEmail("sampleuser@aspnetboilerplate.com");
} public void TestMethod_2()
{
//Switch to tenant 42
CurrentUnitOfWork.SetFilterParameter(AbpDataFilters.MayHaveTenant, AbpDataFilters.Parameters.TenantId, ); //Find a user by email for the tenant 42
var user = _userManager.FindByEmail("sampleuser@aspnetboilerplate.com");
} public void TestMethod_3()
{
//Disabling MayHaveTenant filter, so we can reach to all users
using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.MayHaveTenant))
{
//Now, we can search for a user name in all tenants
var users = _userManager.Users.Where(u => u.UserName == "sampleuser").ToList(); //Or we can add TenantId filter if we want to search for a specific tenant
var user = _userManager.Users.FirstOrDefault(u => u.TenantId == && u.UserName == "sampleuser");
}
}
}

用户登录

模块零定义了LoginManager,它具有 用于登录到应用程序的LoginAsync方法。它检查所有登录逻辑并返回登录结果。LoginAsync方法也会自动保存到数据库的所有登录尝试(即使是失败的尝试)。您可以使用UserLoginAttempt实体来查询它。

关于IdentityResults

UserManager的某些方法返回IdentityResult,而不是在某些情况下抛出异常。这是ASP.NET Identity Framework的本质。模块零也跟着它。所以,我们应该检查这个返回的结果对象,以确定操作是否成功。

Module-zero定义了CheckErrors扩展方法,该方法自动检查错误并在必要时抛出异常(一个本地化的 UserFriendlyException)。用法示例:

(await UserManager.CreateAsync(user)).CheckErrors();

为了获得一个本地化的异常,我们应该提供一个ILocalizationManager实例:

(await UserManager.CreateAsync(user)).CheckErrors(LocalizationManager);

外部认证

module-zero的登录方法从数据库中的AbpUsers表中对用户进行身份验证。某些应用程序可能需要从某些外部来源(如活动目录,来自另一个数据库的表或甚至远程服务)对用户进行身份验证。

对于这种情况,UserManager定义了一个名为“外部认证源”的扩展点。我们可以创建一个派生自 IExternalAuthenticationSource的类并注册到配置中。有DefaultExternalAuthenticationSource类来简化IExternalAuthenticationSource的实现。我们来看一个例子:

public class MyExternalAuthSource : DefaultExternalAuthenticationSource<Tenant, User>
{
public override string Name
{
get { return "MyCustomSource"; }
} public override Task<bool> TryAuthenticateAsync(string userNameOrEmailAddress, string plainPassword, Tenant tenant)
{
//TODO: authenticate user and return true or false
}
}

在TryAuthenticateAsync方法中,我们可以从某个源检查用户名和密码,如果给定用户通过此源验证,则返回true。此外,我们可以覆盖CreateUser和UpdateUser方法来控制用户创建和更新此源。

当用户通过外部源进行身份验证时,module-zero会检查数据库中是否存在此用户(AbpUsers表)。如果不是,则调用CreateUser创建用户,否则调用UpdateUser以允许认证源更新现有的用户信息。

我们可以在一个应用程序中定义多个外部认证源。AbpUser实体具有AuthenticationSource属性,该属性显示哪个源验证了此用户。

要注册我们的认证源,我们可以在我们的模块的PreInitialize中使用这样的代码 :

Configuration.Modules.Zero()。UserManagement.ExternalAuthenticationSources.Add < MyExternalAuthSource >();

LDAP / Active Directory

LdapAuthenticationSource是外部认证的实现,使用户可以使用其LDAP(活动目录)用户名和密码登录。

如果我们想使用LDAP认证,我们首先添加 Abp.Zero.Ldap nuget包到我们的项目(一般是核心(域)项目)。那么我们应该为我们的应用程序扩展LdapAuthenticationSource,如下所示:

public  class MyLdapAuthenticationSource:LdapAuthenticationSource <Tenant,User>
{ public MyLdapAuthenticationSource(ILdapSettings settings,IAbpZeroLdapModuleConfig ldapModuleConfig)
:base(settings,ldapModuleConfig)
{
}
}

最后,我们应该将模块依赖关系设置为AbpZeroLdapModule, 并使用上面创建的认证来启用 LDAP:

[DependsOn(typeof(AbpZeroLdapModule))]
public class MyApplicationCoreModule:AbpModule
{ public override void PreInitialize()
{ Configuration.Modules.ZeroLdap()。Enable(typeof(MyLdapAuthenticationSource));
}
...
}

完成这些步骤之后,将为您的应用程序启用LDAP模块。但LDAP验证默认情况下不启用。我们可以使用设置启用它。

设置

LdapSettingNames类定义了用于设置名称的常量。您可以在更改设置(或获取设置)时使用这些常量名称。LDAP设置是每个租户(对于多租户应用程序)。因此,不同的租户有不同的设置(请参阅github上的设置定义 )。

正如您在MyLdapAuthenticationSource 构造函数中所看到的,LdapAuthenticationSource期望 ILdapSettings作为构造函数参数。此接口用于获取LDAP设置,如域,用户名和密码以连接到Active Directory。默认实现(LdapSettings类)从设置管理器获取这些设置。

如果你使用设置管理器,那么没有问题。您可以使用设置管理器API更改LDAP设置。如果需要,可以将初始/种子数据添加到数据库,以默认启用LDAP身份验证。

注意:如果您没有定义域,用户名和密码,那么如果您的应用程序在具有相应权限的域中运行,那么LDAP身份验证适用于当前域。

自定义设置

如果你想定义另一个设置源,你可以实现一个自定义的ILdapSettings类,如下所示:

public class MyLdapSettings : ILdapSettings
{
public async Task<bool> GetIsEnabled(int? tenantId)
{
return true;
} public async Task<ContextType> GetContextType(int? tenantId)
{
return ContextType.Domain;
} public async Task<string> GetContainer(int? tenantId)
{
return null;
} public async Task<string> GetDomain(int? tenantId)
{
return null;
} public async Task<string> GetUserName(int? tenantId)
{
return null;
} public async Task<string> GetPassword(int? tenantId)
{
return null;
}
}

然后在模块中的PreInitialize方法里将它注册到IOC中:

[DependsOn(typeof(AbpZeroLdapModule))]
public class MyApplicationCoreModule : AbpModule
{
public override void PreInitialize()
{
IocManager.Register<ILdapSettings, MyLdapSettings>(); //change default setting source
Configuration.Modules.ZeroLdap().Enable(typeof (MyLdapAuthenticationSource));
} ...
}

实战

bootstrap table引入

这里开始bootstrap table,引入项目有两种方法,一种是直接去官网下载

地址:http://bootstrap-table.wenzhixin.net.cn/

另一种是Nuget引入.

然后就是把js引用到项目中来,其实Bootstrap js 还有jQuery我们在模板页已经引进了,这里只需要引入bootstrap table相关的js以及中文包就可以了

<link href="~/Scripts/Content/bootstrap-table/bootstrap-table.css" rel="stylesheet" />
<script src="~/Scripts/Content/bootstrap-table/bootstrap-table.js"></script>
<script src="~/Scripts/Content/bootstrap-table/locale/bootstrap-table-zh-CN.js"></script>

前提是创建控制器userinfo,添加index视图里面处理,创建视图的时候自动选择_Layout作为模板页.引入需要的文件之后,我们最重要的就是定义一个空的table,如上的  <table id="tb_departments"></table>  。当然Bootstrap table还提供了一种简介的用法,直接在table标签里面定义类似“data-...”等相关属性,就不用再js里面注册了,但我觉得这种用法虽然简单,但不太灵活,遇到父子表等这些高级用法的时候就不太好处理了,所以咱们还是统一使用在js里面初始化的方式来使用table组件。

    $(function () {

        //1.初始化Table
var oTable = new TableInit();
oTable.Init(); //2.初始化Button的点击事件
var oButtonInit = new ButtonInit();
oButtonInit.Init(); });
var Url = "@Url.Action("GetUsersList")";
var TableInit = function () {
var oTableInit = new Object();
//初始化Table
oTableInit.Init = function () {
$('#tb_departments').bootstrapTable({
// url: '../User/GetUsersList',
url: Url, //请求后台的URL(*)
method: 'get', //请求方式(*)
toolbar: '#toolbar', //工具按钮用哪个容器
striped: true, //是否显示行间隔色
cache: false, //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
pagination: true, //是否显示分页(*)
sortable: false, //是否启用排序
sortOrder: "asc", //排序方式
queryParams: oTableInit.queryParams,//传递参数(*)
sidePagination: "server", //分页方式:client客户端分页,server服务端分页(*)
pageNumber: 1, //初始化加载第一页,默认第一页
pageSize: 2, //每页的记录行数(*)
pageList: [10, 25, 50, 100], //可供选择的每页的行数(*)
search: true, //是否显示表格搜索,此搜索是客户端搜索,不会进服务端,所以,个人感觉意义不大
strictSearch: true,
showColumns: true, //是否显示所有的列
showRefresh: true, //是否显示刷新按钮
minimumCountColumns: 2, //最少允许的列数
clickToSelect: true, //是否启用点击选中行
height: 500, //行高,如果没有设置height属性,表格自动根据记录条数觉得表格高度
uniqueId: "ID", //每一行的唯一标识,一般为主键列
showToggle: true, //是否显示详细视图和列表视图的切换按钮
cardView: false, //是否显示详细视图
detailView: false, //是否显示父子表
columns: [{
checkbox: true
}, {
field: 'UserName',
title: '姓名'
}, {
field: 'Email',
title: '邮箱'
}, {
field: 'Phone',
title: '手机'
}, {
field: 'Address',
title: '地址'
}, ]
});
}; //得到查询的参数
oTableInit.queryParams = function (params) {
var temp = { //这里的键的名字和控制器的变量名必须一直,这边改动,控制器也需要改成一样的
limit: params.limit, //页面大小
offset: params.offset, //页码
departmentname: $("#txt_search_departmentname").val(),
statu: $("#txt_search_statu").val()
};
return temp;
};
return oTableInit;
};

表格的初始化也很简单,定义相关的参数即可。上面一些博主觉得重要的参数都加了注释,并且初始化Table必须的几个参数也用(*)做了标记,如果你的表格也有太多的页面需求,直接用必须的参数就能解决。同样,在columns参数里面其实也有很多的参数需要设置,比如列的排序,对齐,宽度等等。这些比较简单,不会涉及表格的功能,看看API就能搞定。

这里需要注意的是@Url.Action,var Url = "@Url.Action("GetUsersList")";/ UserInfo/ GetUsersList,直接指定后台的控制器里面的方法.

   public class UserInfoController : Controller
{
private readonly IUserService _iUsersService; public UserInfoController(IUserService iUsersService)
{ _iUsersService = iUsersService; }
// GET: Admin/UserInfo
public ActionResult Index()
{
return View();
} [DisableAbpAntiForgeryTokenValidation]
[HttpGet]
[DontWrapResult] //不需要AbpJsonResult
public JsonResult GetUsersList()
{
string pageNumber = string.IsNullOrWhiteSpace(Request["pageNumber"]) ? "" : Request["pageNumber"];
string pageSize = string.IsNullOrWhiteSpace(Request["pageSize"]) ? "" : Request["pageSize"];
List<UserInfoDto> Userlist = new List<UserInfoDto>();
Userlist = _iUsersService.GetAllList().ToList();
int totaldata = Userlist.Count();
Userlist = Userlist.Skip(int.Parse(pageNumber) * int.Parse(pageSize)).Take(int.Parse(pageSize)).ToList();
var result = new { total = totaldata, rows = Userlist };
return Json(result, JsonRequestBehavior.AllowGet);
}
}

注意事项

这里有一点需要注意:如果是服务端分页,返回的结果必须包含total、rows两个参数。漏写或错写都会导致表格无法显示数据。相反,如果是客户端分页,这里要返回一个集合对象到前端。当然我这里为了快捷,我没有去服务里面处理分页,直接在这里分页,这种做法其实很low,按照之前的做法会专门封装一个分页DTO,然后添加自定义排序字段.我这里就不去处理了,有兴趣的自己去弄一下,这些会在我下一个项目里面详细讲.这里我再网上找一张一图片来看一下具体代码的应用.

crud功能

其实这些信息在API里面应该都有,自己看一下就可以了.

我这里分页和菜单是自己写的,crud的功能都是有的.

var ButtonInit = function () {
var oInit = new Object();
var postdata = {}; oInit.Init = function () {
//初始化页面上面的按钮事件
//查询角色
$("#btn_query").click(function () {
var actionUrl = "@Url.Action("GetUsersList")";
m_pagerow = ;
$("#tb_departments").bootstrapTable('refresh', { url: actionUrl }); });
//新增角色
$("#btn_add").click(function () { $("#id").val("");
$("#txt_Surname").val("");
$("#txt_Name").val("");
$("#txt_UserName").val("");
$("#txt_isDeleted").val(""); $("#myModalLabel").text("新增");
$('#myModal').modal();
});
//新增角色
$("#btn_submit").click(function () { var actionUrl = "@Url.Action("Create")";
var UserName = $("#txt_Surname").val();
var Email = $("#txt_Name").val();
var Phone = $("#txt_UserName").val();
var isnull = $("#txt_isDeleted").val();
var isDeleted = true;
if (isnull=="") {
isDeleted = false;
}
var Id = $("#id").val() == "" ? : $("#id").val();
debugger;
$.ajax({
type: 'post',
dataType: "Json",
url: actionUrl,
data: { Id: Id, UserName: UserName, Email: Email, Phone: Phone, isDeleted: isDeleted },
beforeSend: function (XMLHttpRequest) {
},
success: function (data, textStatus) { //请求成功后处理函数。
toastr.warning('操作成功!');
var actionUrl = "@Url.Action("GetUsersList")";
m_pagerow = ;
$("#tb_departments").bootstrapTable('refresh', { url: actionUrl });
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
}
});
});
//编辑角色
$("#btn_edit").click(function () {
debugger;
var arrselections = $("#tb_departments").bootstrapTable('getSelections');
if (arrselections.length > ) {
toastr.warning('只能选择一行进行编辑');
return;
}
if (arrselections.length <= ) {
toastr.warning('请选择有效数据');
return;
}
$("#id").val(arrselections[].Id);
$("#txt_Surname").val(arrselections[].UserName);
$("#txt_Name").val(arrselections[].Email);
$("#txt_UserName").val(arrselections[].Phone);
$("#txt_isDeleted").val(arrselections[].Id); $("#myModalLabel").text("修改");
$('#myModal').modal();
//ShowModal(actionUrl, param, "编辑角色");
});
//删除角色
$("#btn_delete").click(function () {
var actionUrl = "@Url.Action("DelUserById")";
var arrselections = $("#tb_departments").bootstrapTable('getSelections');
if (arrselections.length > ) {
toastr.warning('只能选择一行进行编辑');
return;
}
if (arrselections.length <= ) {
toastr.warning('请选择有效数据');
return;
}
var Id = arrselections[].Id;
debugger;
$.ajax({
type: 'post',
dataType: "Json",
url: actionUrl,
data: { Id:Id},
beforeSend: function (XMLHttpRequest) {
},
success: function (data, textStatus) { //请求成功后处理函数。
toastr.warning('操作成功!');
var actionUrl = "@Url.Action("GetUsersList")";
m_pagerow = ;
$("#tb_departments").bootstrapTable('refresh', { url: actionUrl });
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
}
});
});
//权限授权
$("#btn_authorize").click(function () {
var arrselections = $("#tb_departments").bootstrapTable('getSelections');
if (arrselections.length > ) {
toastr.warning('只能选择一个角色进行授权');
return;
}
if (arrselections.length <= ) {
toastr.warning('请选择有效数据');
return;
}
var actionUrl = "@Url.Action("AuthorizePermission")";
var param = { id: arrselections[].Id };
ShowModal_Authorize(actionUrl, param, "权限授权");
});
//模态框中“权限授权”保存
var $modal = $("#authorizeModal");
$("#btnSave", $modal).click(function () {
var actionUrl = "@Url.Action("AuthorizePermission")";
SaveModal_Authorize(actionUrl);
});
//模态框中“新增编辑角色”保存
var $formmodal = $("#modal-form");
$("#btnSave", $formmodal).click(function () {
var $tb = $("#tb_departments");
SaveModal($tb);
}); /*******弹出表单*********/
function ShowModal(actionUrl, param, title) {
debugger;
var $modal = $("#modal-form");
//表单初始化
$(".modal-title", $modal).html(title);
$("#modal-content", $modal).attr("action", actionUrl); $.ajax({
type: "GET",
url: actionUrl,
data: param,
beforeSend: function () {
},
success: function (result) {
debugger;
$("#modal-content").html(result);
$('#modal-form').modal('show');
},
error: function () { },
complete: function () { }
});
} }; return oInit;
};

自定义菜单以及弹样式及功能.

<section class="content-header">
<h1>
用户明细
<small>advanced cxdmles</small>
</h1>
<ol class="breadcrumb">
<li><a href="#"><i class="fa fa-dashboard"></i> 主页</a></li>
<li><a href="#">用户管理</a></li>
<li class="active">用户列表</li>
</ol> </section>
<section class="content">
<div class="panel-body" style="padding-bottom:0px;">
<div class="panel panel-default">
<div class="panel-heading">查询条件</div>
<div class="panel-body">
<form id="formSearch" class="form-horizontal">
<div class="form-group" style="margin-top:15px">
<label class="control-label col-sm-1" for="txt_search_departmentname">姓名</label>
<div class="col-sm-3">
<input type="text" class="form-control" id="txt_search_departmentname">
</div>
<label class="control-label col-sm-1" for="txt_search_statu">昵称</label>
<div class="col-sm-3">
<input type="text" class="form-control" id="txt_search_statu">
</div>
<div class="col-sm-4" style="text-align:left;">
<button type="button" style="margin-left:50px" id="btn_query" class="btn btn-primary">查询</button>
</div>
</div>
</form>
</div>
</div> <div id="toolbar" class="btn-group">
<button id="btn_add" type="button" class="btn btn-success">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>新增
</button>
<button id="btn_edit" type="button" class="btn btn-warning">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>修改
</button>
<button id="btn_delete" type="button" class="btn btn-danger">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>删除
</button>
<button id="btn_authorize" type="button" class="btn btn-info ">
<span class="glyphicon glyphicon-lock" aria-hidden="true"></span>授权
</button> </div>
<table id="tb_departments"></table>
</div> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel"></h4>
</div>
<div class="modal-body"> <div class="form-group">
<label for="txt_departmentname">姓名</label>
<input type="text" name="id" class="form-control" id="id" placeholder="id" style="display:none">
<input type="text" name="txt_departmentname" class="form-control" id="txt_Surname" placeholder="真实姓名">
</div>
<div class="form-group">
<label for="txt_parentdepartment">邮箱</label>
<input type="text" name="txt_parentdepartment" class="form-control" id="txt_Name" placeholder="姓名">
</div>
<div class="form-group">
<label for="txt_departmentlevel">手机</label>
<input type="text" name="txt_departmentlevel" class="form-control" id="txt_UserName" placeholder="部门级别">
</div>
<div class="form-group">
<label for="txt_departmentlevel">是否启用</label>
<div class="checkbox">
<label>
<input type="checkbox" disabled="disabled">
</label>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span>关闭</button>
<button type="button" id="btn_submit" class="btn btn-primary" data-dismiss="modal"><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>保存</button>
</div>
</div>
</div>
</div> </section>

控制器方法

这里的菜单其实也是bootstrap 样式.表单也是.看下控制器方法.都很简单.

        public ActionResult Create()
{
var model = new UserInfoDto();
return PartialView(model);
}
[HttpPost]
public ActionResult Create(UserInfoDto roleVm)
{
var result = _iUsersService.AddUserList(roleVm);
return Json(result);
}
[DisableAbpAntiForgeryTokenValidation]
[HttpPost]
[DontWrapResult]
public ActionResult DelUserById(string Id)
{
var result = _iUsersService.DelUsers(Id);
return Json(result);
}

Service方法

Service方法.无需细说,一看就懂,注意递归

    public class UserService : IUserService
{
private readonly IRepository<Users, int> _userRepository;
public ILogger Logger { get; set; }
public UserService(IRepository<Users, int> userRepository)
{
Logger = NullLogger.Instance;
_userRepository = userRepository;
}
public async Task AddUserList(UserInfoDto model)
{
var user = model.MapTo<Users>();
await _userRepository.InsertAsync(user);
} public async Task DelUsers(string id)
{
try
{
Users user = _userRepository.Get(Int32.Parse(id));
await _userRepository.DeleteAsync(user);
}
catch (Exception ex)
{ throw;
}
}
public async Task<ListResultDto<UserInfoDto>> GetUsers()
{
var users = await _userRepository.GetAllListAsync(); return new ListResultDto<UserInfoDto>(
users.MapTo<List<UserInfoDto>>()
);
}
public List<UserInfoDto> GetAllList()
{
var users = _userRepository.GetAllListAsync();
return new List<UserInfoDto>(
users.MapTo<List<UserInfoDto>>()
);
}
}

效果

自此,用户列表.

返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期

ABP+AdminLTE+Bootstrap Table权限管理系统第十一节--Bootstrap Table用户管理列表以及Module Zero之用户管理的更多相关文章

  1. ABP+AdminLTE+Bootstrap Table权限管理系统第十一节--bootstrap table之用户管理列表

    这张开始bootstrap table,引入项目有两种方法,一种是直接去官网下载 地址:http://bootstrap-table.wenzhixin.net.cn/ 另一种是Nuget引入. 然后 ...

  2. ABP+AdminLTE+Bootstrap Table权限管理系统第五节--WBEAPI及SwaggerUI

    一,Web API ABP的动态WebApi实现了直接对服务层的调用(其实病没有跨过ApiController,只是将ApiController公共化,对于这一点的处理类似于MVC,对服务端的 调用没 ...

  3. ABP+AdminLTE+Bootstrap Table权限管理系统第六节--abp控制器扩展及json封装

    一,控制器AbpController 说完了Swagger ui 我们再来说一下abp对控制器的处理和json的封装. 首先我们定义一个控制器,在新增控制器的时候,控制器会自动继承自AbpContro ...

  4. ABP+AdminLTE+Bootstrap Table权限管理系统第十节--AdminLTE模板菜单处理

    上节我们把布局页,也有的临时的菜单,但是菜单不是应该动态加载的么?,所以我们这节来写菜单.首先我们看一下AdminLTE源码里面的菜单以及结构. <aside class="main- ...

  5. ABP+AdminLTE+Bootstrap Table权限管理系统第七节--登录逻辑及abp封装的Javascript函数库

    经过前几节,我们已经解决数据库,模型,DTO,控制器和注入等问题.那么再来看一下登录逻辑.这里算是前面几节的一个初次试水. 首先我们数据库已经有的相应的数据. 模型和DTO已经建好,所以我们直接在服务 ...

  6. ABP+AdminLTE+Bootstrap Table权限管理系统第七节--登录逻辑及几种abp封装的Javascript函数库

    返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期         简介 经过前几节,我们已经解决数据库,模型,DTO,控制器和注入等问题.那么再来看一下登录逻辑.这 ...

  7. ABP+AdminLTE+Bootstrap Table权限管理系统第六节--abp控制器扩展及json封装以及6种处理时间格式化的方法

    返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 一,控制器AbpController 说完了Swagger ui 我们再来说一下abp对控制器的处理和json的封 ...

  8. ABP+AdminLTE+Bootstrap Table权限管理系统第四节--仓储,服务,服务接口及依赖注入

    在ABP框架中,仓储,服务,这块算是最为重要一块之一了.ABP框架提供了创建和组装模块的基础,一个模块能够依赖于另一个模块,一个程序集可看成一个模块, 一个模块可以通过一个类来定义这个模块,而给定义这 ...

  9. ABP+AdminLTE+Bootstrap Table权限管理系统一期

       学而时习之,不亦说乎,温顾温知新,可以为师矣. 这也是算是一种学习的方法和态度吧,经常去学习和总结,在博客园看了很多大神的文章,写下一点对于ABP(ABP是“ASP.NET Boilerplat ...

随机推荐

  1. .NET MVC 后台接受base64的上传图片

    #region 配合前端的多张图片上传 #region 上传图片方法 /// <summary> /// 接口方法 /// </summary> /// <param n ...

  2. C语言四舍五入

    //今天遇到了四舍五入的问题,这些问题如果不看别人的真的难想出这么巧妙的方法啊.努力积累,早日成为大佬. int i = (int)(a + 0.5) ////小数部分大于0.4,加上0.5就会超过整 ...

  3. 串口-CreateFile的使用

    在32位的windows系统中,串口和其他通信设备是作为文件处理的.对串口的操作和对文件的操作是完全一样的.通信以调用CreateFile()开始. 函数原型如下: HANDLE CreateFile ...

  4. February 8th, 2018 Week 6th Thursday

    When you fall in love, friends, let yourself fall. 当你坠入爱河,我的朋友,你就放手去爱吧. To love someone is like movi ...

  5. 解决 Mac 突然没有声音

    前言 偶尔早上上班时发现Mac突然没有声音了,不明所以.虽然重启也可以,但是也不免太麻烦了.也许是人品不太好,遇到过多次这种情况,就在快要砸了的自己mac的时候,脑中灵光一闪,难道这是因为核心音频守护 ...

  6. 启用crontab

    1.登录到root用户. 2.在root下输入:crontab -e 3.可能会提示你: no crontab for root - using an empty one 然后会叫你“Select a ...

  7. C++添加热键和捕获组合键

    一.热键注册 步骤一:声明一个全局量int hotkeyId=1: 步骤二:窗体创建的时候注册: int result= RegisterHotKey(this->GetHWND(), hotk ...

  8. 转://Linux MultiPath多路径软件实施说明

    Multipath的工作原理 当multipath启动的时候,它通过系统命令scsi_id -eg -s /block/sdX得到proc/partitions 里面所有块设备的 UUID(unive ...

  9. 键值对的算子讲解 PairRDDFunctions

    1:groupByKey def groupByKey(): RDD[(K, Iterable[V])] 根据key进行聚集,value组成一个列表,没有进行聚集,所以在有shuffle操作时候避免使 ...

  10. P2626 斐波那契数列(升级版)(合数的质数分解, 大数为素数的概率十分小的利用)

    题目背景 大家都知道,斐波那契数列是满足如下性质的一个数列: f(1)=1f(1) = 1 f(1)=1 f(2)=1f(2) = 1f(2)=1 f(n)=f(n−1)+f(n−2)f(n) = f ...