【ABP】从零开始学习ABP_001_新建实体功能
上一篇文章中介绍了如何下载、运行ABP Zero示例项目,这个示例项目可以直接作为模板进行二次开发,很适合做企业开发框架。
本未介绍基于ABP Zero示例项目,如何新建一个自定义的实体。
此处已EquipmentType(设备类型)为例,建立一个简单的实体。
以下是之前添加一个简单实体类的效果:
主页
公司列表
新建公司
编辑公司
删除公司
建立方法
按ABP的标准格式,完整建立一个实体,映射到数据库,作为一个基础资料,并通过前端进行增删查改功能,最小步骤如下:
- 新增实体类。
- 添加数据库映射。
- 同步到数据库。
- 新建Dto,建立Dto与实体类的映射。
- 建立实体类的功能接口(增删查改),并实现接口。
- 添加视图模型ViewModel。
- 添加控制器。
- 添加视图。
- 添加js脚本。
- 添加前端菜单(入口)。
- 添加权限管理。
1. 添加实体类
namespace oMES_APServer.Equipments
{
public class EquipmentType : MESBase.MESBaseEntity
{ }
}
这里我把MES会用到的常规属性单独建了一个基类,并继承ABP全属性基类FullAuditedEntity
using Abp.Domain.Entities;
using Abp.Domain.Entities.Auditing;
using System.ComponentModel.DataAnnotations; namespace oMES_APServer.MESBase
{
public class MESBaseEntity : FullAuditedEntity<int>, IPassivable
{ public const int MaxCodeLength = ;
public const int MaxNameLength = ;
public const int MaxBriefNameLength = ;
public const int MaxRemarkLength = ; [Required]
[StringLength(MaxCodeLength)]
public string Code { get; set; } [Required]
[StringLength(MaxNameLength)]
public string Name { get; set; } [StringLength()]
public string BriefName { get; set; } [StringLength()]
public string Remark { get; set; }
public bool IsActive { get; set; } }
}
2. 添加数据库映射
添加以下代码:为了让EFCore能够自动生成数据库表结构。
public DbSet<EquipmentType> equipmentTypes { get; set; }
modelBuilder.Entity<EquipmentType>().ToTable("EquipmentType").HasAlternateKey(x => x.Code).HasName("UK_EquipmentType_Code");
其中.HasAlternateKey表示建立唯一键,.HasName表示键的名称。
using Microsoft.EntityFrameworkCore;
using Abp.Zero.EntityFrameworkCore;
using oMES_APServer.Authorization.Roles;
using oMES_APServer.Authorization.Users;
using oMES_APServer.MultiTenancy;
using oMES_APServer.Companies;
using oMES_APServer.Equipments; namespace oMES_APServer.EntityFrameworkCore
{
public class oMES_APServerDbContext : AbpZeroDbContext<Tenant, Role, User, oMES_APServerDbContext>
{
/* Define a DbSet for each entity of the application */
public oMES_APServerDbContext(DbContextOptions<oMES_APServerDbContext> options)
: base(options)
{
} /*添加自定义实体类的数据库映射*/
public DbSet<Company> companies { get; set; }
public DbSet<Department> departments { get; set; }
public DbSet<EquipmentType> equipmentTypes { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder); modelBuilder.Entity<Company>().ToTable("Company")
.HasAlternateKey(x=>x.Code).HasName("UK_Company_Code");
modelBuilder.Entity<Department>().ToTable("Department")
.HasAlternateKey(x => x.Code).HasName("UK_Department_Code");
modelBuilder.Entity<EquipmentType>().ToTable("EquipmentType")
.HasAlternateKey(x => x.Code).HasName("UK_EquipmentType_Code");
} }
}
3. 同步到数据库。
依次执行以下两条指令:
- add-migration add-EquipmentType
- update-database
第一条表示,新建同步映射,映射名称为add-EquipmentType。
第二条表示同步数据库。
执行时,出现上述报错,不要慌,重新生成一下项目,应该有报错,解决完项目报错再执行,就可以了。
4. 新建Dto,建立Dto与实体类的映射
建立Dto
namespace oMES_APServer.Equipments.Dto
{
public class EquipmentTypeDto : MESBaseDto.MESBaseEntityDto
{ }
}
建立实体类和Dto的映射
using AutoMapper; namespace oMES_APServer.Equipments.Dto
{
public class EquipmentTypeMapProfile : Profile
{
public EquipmentTypeMapProfile()
{
CreateMap<EquipmentType, EquipmentTypeDto>();
CreateMap<EquipmentTypeDto, EquipmentType>();
CreateMap<EquipmentTypeDto, EquipmentType>()
.ForMember(x => x.CreationTime, opt => opt.Ignore());
}
}
}
引申:
ABP Zero的Dto类文件夹中,会有一个 PagedxxxResultRequestDto.cs类,这个是用于按给定条件查找数据列表,并进行分页的类。目前还没有学习到,所以仅按照现有的实体类进行仿照编程,不做额外处理。
using Abp.Application.Services.Dto; namespace oMES_APServer.Equipments.Dto
{
public class PagedEquipmentTypeResultRequestDto : PagedResultRequestDto
{ public string Code { get; set; } public string Name { get; set; } public bool? IsActive { get; set; } }
}
5. 建立实体类的功能接口(增删查改),并实现接口。
建立接口:因为ABP接口已经实现了基础功能(增删查改)的方法定义,所以直接继承IAsyncCrudAppService即可,写法参照已有的User相关类。
using Abp.Application.Services;
using oMES_APServer.Companies.Dto; namespace oMES_APServer.Equipments
{
public interface IEquipmentTypesAppService : IAsyncCrudAppService<CompanyDto, int, PagedCompanyResultRequestDto, CompanyDto, CompanyDto>
{ }
}
自定义实现基础接口:
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Abp.Application.Services;
using Abp.Application.Services.Dto;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.Extensions;
using Abp.Linq.Extensions;
using Abp.UI;
using Microsoft.EntityFrameworkCore;
using oMES_APServer.Equipments.Dto; namespace oMES_APServer.Equipments
{
public class EquipmentTypesAppService : AsyncCrudAppService<EquipmentType, EquipmentTypeDto, int, PagedEquipmentTypeResultRequestDto, EquipmentTypeDto, EquipmentTypeDto>, IEquipmentTypeAppService
{
private readonly IRepository<EquipmentType> _equipmentTypeRepository; public EquipmentTypesAppService(IRepository<EquipmentType> equipmentTypeRepository)
: base(equipmentTypeRepository)
{
_equipmentTypeRepository = equipmentTypeRepository; LocalizationSourceName = oMES_APServerConsts.LocalizationSourceName;
} public override async Task<EquipmentTypeDto> Get(EntityDto<int> input)
{
var equipmentType = await _equipmentTypeRepository
.GetAsync(input.Id); return ObjectMapper.Map<EquipmentTypeDto>(equipmentType);
} public override async Task<PagedResultDto<EquipmentTypeDto>> GetAll(PagedEquipmentTypeResultRequestDto input)
{
var equipmentTypes = Repository.GetAll()
.WhereIf(!input.Name.IsNullOrWhiteSpace(), x => x.Name.Contains(input.Name))
.WhereIf(!input.Code.IsNullOrWhiteSpace(), x => x.Code.Contains(input.Code))
.WhereIf(input.IsActive.HasValue, x => x.IsActive == input.IsActive)
.OrderBy(x => x.Code); return await Task.FromResult(new PagedResultDto<EquipmentTypeDto>(equipmentTypes.CountAsync().Result,
ObjectMapper.Map<List<EquipmentTypeDto>>(equipmentTypes)
));
} public override async Task<EquipmentTypeDto> Create(EquipmentTypeDto input)
{ //判断CODE是否已存在
var model = await Repository.GetAllIncluding().FirstOrDefaultAsync(x => x.Code == input.Code);
if (model != null)
{
throw new UserFriendlyException(L("EquipmentType code already exists"));
} //检查是否已被软删除,已经软删除的数据,无法通过
using (UnitOfWorkManager.Current.DisableFilter(AbpDataFilters.SoftDelete))
{
//判断CODE是否已存在
var model0 = await Repository.GetAllIncluding().FirstOrDefaultAsync(x => x.Code == input.Code);
if (model0 != null)
{
throw new UserFriendlyException(L("EquipmentType code is deleted"));
}
} var entity = ObjectMapper.Map<EquipmentType>(input);
await _equipmentTypeRepository.InsertAsync(entity);
return MapToEntityDto(entity);
} public override async Task<EquipmentTypeDto> Update(EquipmentTypeDto input)
{
var entity = await _equipmentTypeRepository.GetAsync(input.Id); ObjectMapper.Map(input, entity); await _equipmentTypeRepository.UpdateAsync(entity); return MapToEntityDto(entity);
} public override async Task Delete(EntityDto<int> input)
{
var entity = await _equipmentTypeRepository.GetAsync(input.Id);
await _equipmentTypeRepository.DeleteAsync(entity);
} }
}
其中,创建的代码如下:在基类中,我们设置了Code字段为唯一键,所以需要先确定Code不存在
public override async Task<EquipmentTypeDto> Create(EquipmentTypeDto input)
{ //判断CODE是否已存在
var model = await Repository.GetAllIncluding().FirstOrDefaultAsync(x => x.Code == input.Code);
if (model != null)
{
throw new UserFriendlyException(L("EquipmentType code already exists"));
} //检查是否已被软删除,已经软删除的数据,无法通过
using (UnitOfWorkManager.Current.DisableFilter(AbpDataFilters.SoftDelete))
{
//判断CODE是否已存在
var model0 = await Repository.GetAllIncluding().FirstOrDefaultAsync(x => x.Code == input.Code);
if (model0 != null)
{
throw new UserFriendlyException(L("EquipmentType code is deleted"));
}
} var entity = ObjectMapper.Map<EquipmentType>(input);
await _equipmentTypeRepository.InsertAsync(entity);
return MapToEntityDto(entity);
}
ABP的全属性类FullAuditedEntity中,预置了软删除功能,如果一条数据被软删除了(IsDeleted字段为1),那么直接查找是招不到的。
需要临时关闭软删除的过滤器,才能找到:在using中,使用正常的查询代码,就能查到已被软删除的数据。
//检查是否已被软删除,已经软删除的数据,无法通过
using (UnitOfWorkManager.Current.DisableFilter(AbpDataFilters.SoftDelete))
{
//判断CODE是否已存在
var model0 = await Repository.GetAllIncluding().FirstOrDefaultAsync(x => x.Code == input.Code);
if (model0 != null)
{
throw new UserFriendlyException(L("EquipmentType code is deleted"));
}
}
6. 添加视图模型ViewModel。
添加查询视图模型,这里没有做特殊处理,直接使用Dto
using oMES_APServer.Equipments.Dto;
using System.Collections.Generic; namespace oMES_APServer.Web.Models.EquipmentTypes
{
public class EquipmentTypeListViewModel
{
public IReadOnlyList<EquipmentTypeDto> EquipmentTypes { get; set; }
}
}
添加编辑视图模型
using oMES_APServer.Equipments.Dto; namespace oMES_APServer.Web.Models.EquipmentTypes
{
public class EditEquipmentTypeModalViewModel
{
public EquipmentTypeDto EquipmentType { get; set; }
}
}
7. 添加控制器。
控制器中添加两个方法Index和Edit.
using System.Threading.Tasks;
using Abp.Application.Services.Dto;
using Microsoft.AspNetCore.Mvc;
using oMES_APServer.Controllers;
using oMES_APServer.Equipments;
using oMES_APServer.Equipments.Dto;
using oMES_APServer.Web.Models.EquipmentTypes; namespace oMES_APServer.Web.Mvc.Controllers
{
public class EquipmentTypesController : oMES_APServerControllerBase
{ private readonly IEquipmentTypeAppService _equipmentTypeAppService; public EquipmentTypesController(IEquipmentTypeAppService equipmentTypeAppService)
{
_equipmentTypeAppService = equipmentTypeAppService;
} public async Task<IActionResult> Index()
{
var modelDto = (await _equipmentTypeAppService
.GetAll(new PagedEquipmentTypeResultRequestDto { MaxResultCount = int.MaxValue })
).Items;
var viewModel = new EquipmentTypeListViewModel
{
EquipmentTypeList = modelDto
};
return View(viewModel);
} public async Task<ActionResult> EditEquipmentTypeModal(int id)
{
var modelDto = await _equipmentTypeAppService.Get(new EntityDto(id));
var editViewModel = new EditEquipmentTypeModalViewModel
{
EquipmentType = modelDto
};
return View("_EditEquipmentTypeModal", editViewModel);
} }
}
8. 添加视图。
视图由user中相关视图复制而来,将名称user更改为equipmentType相关即可使用。
查看&新建视图
@using oMES_APServer.Web.Startup
@using oMES_APServer.Equipments
@model oMES_APServer.Web.Models.EquipmentTypes.EquipmentTypeListViewModel
@{
ViewBag.CurrentPageName = PageNames.EquipmentTypes;
}
@section scripts
{
<environment names="Development">
<script src="~/view-resources/Views/EquipmentTypes/Index.js" asp-append-version="true"></script>
</environment> <environment names="Staging,Production">
<script src="~/view-resources/Views/EquipmentTypes/Index.js" asp-append-version="true"></script>
</environment>
}
<div class="row clearfix">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="card">
<div class="header">
<h2>
@L("EquipmentType")
</h2>
<ul class="header-dropdown m-r--5">
<li class="dropdown">
<a href="javascript:void(0);" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
<i class="material-icons">more_vert</i>
</a>
<ul class="dropdown-menu pull-right">
<li><a id="RefreshButton" href="javascript:void(0);" class="waves-effect waves-block"><i class="material-icons">refresh</i>@L("Refresh")</a></li>
</ul>
</li>
</ul>
</div>
<div class="body table-responsive">
<table class="table">
<thead>
<tr>
<th>@L("Code")</th>
<th>@L("Name")</th>
<th>@L("BriefName")</th>
<th>@L("Remark")</th>
<th>@L("CreationTime")</th>
<th>@L("CreatorUserId")</th>
<th>@L("LastModificationTime")</th>
<th>@L("LastModifierUserId")</th>
</tr>
</thead>
<tbody>
@foreach (var viewModel in Model.EquipmentTypeList)
{
<tr>
<td>@viewModel.Code</td>
<td>@viewModel.Name</td>
<td>@viewModel.BriefName</td>
<td>@viewModel.Remark</td>
<td>@viewModel.CreationTime</td>
<td>@viewModel.CreatorUserId</td>
<td>@viewModel.LastModificationTime</td>
<td>@viewModel.LastModifierUserId</td> <td class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
<i class="material-icons">menu</i>
</a>
<ul class="dropdown-menu pull-right">
<li><a href="#" class="waves-effect waves-block edit-equipmentType" data-equipmentType-id="@viewModel.Id" data-toggle="modal" data-target="#EquipmentTypeEditModal"><i class="material-icons">edit</i>@L("Edit")</a></li>
<li><a href="#" class="waves-effect waves-block delete-equipmentType" data-equipmentType-id="@viewModel.Id" data-equipmentType-name="@viewModel.Name"><i class="material-icons">delete_sweep</i>@L("Delete")</a></li>
</ul>
</td>
</tr>
}
</tbody>
</table>
<button type="button" class="btn btn-primary btn-circle waves-effect waves-circle waves-float pull-right" data-toggle="modal" data-target="#EquipmentTypeCreateModal">
<i class="material-icons">add</i>
</button>
</div>
</div>
</div>
</div> <div class="modal fade" id="EquipmentTypeCreateModal" tabindex="-1" role="dialog" aria-labelledby="EquipmentTypeCreateModalLabel" data-backdrop="static">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form name="equipmentTypeCreateForm" role="form" novalidate class="form-validation">
<div class="modal-header">
<h4 class="modal-title">
<span>@L("CreateNewEquipmentType")</span>
</h4>
</div>
<div class="modal-body">
<div class="form-group form-float">
<div class="form-line">
<input class="form-control" type="text" name="Code" required maxlength="@EquipmentType.MaxCodeLength">
<label class="form-label">@L("Code")</label>
</div>
</div>
<div class="form-group form-float">
<div class="form-line">
<input class="form-control" type="text" name="Name" required maxlength="@EquipmentType.MaxNameLength">
<label class="form-label">@L("Name")</label>
</div>
</div>
<div class="form-group form-float">
<div class="form-line">
<input class="form-control" type="text" name="BriefName" maxlength="@EquipmentType.MaxBriefNameLength">
<label class="form-label">@L("BriefName")</label>
</div>
<div class="form-group form-float">
<div class="form-line">
<input class="form-control" type="text" name="Remark" maxlength="@EquipmentType.MaxRemarkLength">
<label class="form-label">@L("Remark")</label>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default waves-effect" data-dismiss="modal">@L("Cancel")</button>
<button type="submit" class="btn btn-primary waves-effect">@L("Save")</button>
</div>
</form>
</div>
</div>
</div> <div class="modal fade" id="EquipmentTypeEditModal" tabindex="-1" role="dialog" aria-labelledby="EquipmentTypeEditModalLabel" data-backdrop="static">
<div class="modal-dialog" role="document">
<div class="modal-content"> </div>
</div>
</div>
编辑视图
@using oMES_APServer.Web.Models.Common.Modals
@model oMES_APServer.Web.Models.EquipmentTypes.EditEquipmentTypeModalViewModel
@{
Layout = null;
}
@Html.Partial("~/Views/Shared/Modals/_ModalHeader.cshtml", new ModalHeaderViewModel(L("EditEquipmentType"))) <div class="modal-body">
<form name="EquipmentTypeEditForm" role="form" novalidate class="form-validation">
<input type="hidden" name="Id" value="@Model.EquipmentType.Id" />
<ul class="nav nav-tabs tab-nav-right" role="tablist">
<li role="presentation" class="active"><a href="#edit-equipmentType-details" data-toggle="tab">@L("EquipmentTypeDetails")</a></li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane animated fadeIn active" id="edit-equipmentType-details"> <div class="row clearfix" style="margin-top:10px;">
<div class="col-sm-12">
<div class="form-group form-float">
<div class="form-line">
<input id="code" type="text" name="Code" value="@Model.EquipmentType.Code" required maxlength="" minlength="" class="validate form-control">
<label for="code" class="form-label">@L("Code")</label>
</div>
</div>
</div>
</div> <div class="row clearfix" style="margin-top:10px;">
<div class="col-sm-12">
<div class="form-group form-float">
<div class="form-line">
<input id="name" type="text" name="Name" value="@Model.EquipmentType.Name" required maxlength="" minlength="" class="validate form-control">
<label for="name" class="form-label">@L("Name")</label>
</div>
</div>
</div>
</div> <div class="row clearfix" style="margin-top:10px;">
<div class="col-sm-12">
<div class="form-group form-float">
<div class="form-line">
<input id="briefname" type="text" name="BriefName" value="@Model.EquipmentType.BriefName" maxlength="" minlength="" class="validate form-control">
<label for="briefname" class="form-label">@L("BriefName")</label>
</div>
</div>
</div>
</div> <div class="row clearfix" style="margin-top:10px;">
<div class="col-sm-12">
<div class="form-group form-float">
<div class="form-line">
<input id="remark" type="text" name="Remark" value="@Model.EquipmentType.Remark" maxlength="" minlength="" class="validate form-control">
<label for="remark" class="form-label">@L("Remark")</label>
</div>
</div>
</div>
</div> </div>
</div>
</form>
</div> @Html.Partial("~/Views/Shared/Modals/_ModalFooterWithSaveAndCancel.cshtml") <script src="~/view-resources/Views/EquipmentTypes/_EditEquipmentTypeModal.js" asp-append-version="true"></script>
9. 添加js脚本。
视图中添加了js脚本,此处添加合适的js脚本,此脚本由user.js复制而来,更改为equipmentType即可使用。
添加的位置如上述视图中代码所示:"~/view-resources/Views/EquipmentTypes/_EditEquipmentTypeModal.js"
index.js如下
(function () {
$(function () { var _equipmentTypeService = abp.services.app.equipmentType;
var _$modal = $('#EquipmentTypeCreateModal');
var _$form = _$modal.find('form'); _$form.validate(); $('#RefreshButton').click(function () {
refreshequipmentTypeList();
}); //删除方法
$('.delete-equipmentType').click(function () {
var equipmentTypeId = $(this).attr("data-equipmentType-id");
var tenancyName = $(this).attr('data-equipmentType-name'); deleteequipmentType(equipmentTypeId, tenancyName);
}); //编辑方法
$('.edit-equipmentType').click(function (e) {
var equipmentTypeId = $(this).attr("data-equipmentType-id"); e.preventDefault();
$.ajax({
url: abp.appPath + 'equipmentTypes/EditEquipmentTypeModal?equipmentTypeId=' + equipmentTypeId,
type: 'POST',
contentType: 'application/html',
success: function (content) {
$('#EquipmentTypeEditModal div.modal-content').html(content);
},
error: function (e) { }
});
}); _$form.find('button[type="submit"]').click(function (e) {
e.preventDefault(); if (!_$form.valid()) {
return;
} var equipmentType = _$form.serializeFormToObject(); //serializeFormToObject is defined in main.js abp.ui.setBusy(_$modal);
_equipmentTypeService.create(equipmentType).done(function () {
_$modal.modal('hide');
location.reload(true); //reload page to see new equipmentType!
}).always(function () {
abp.ui.clearBusy(_$modal);
});
}); _$modal.on('shown.bs.modal', function () {
_$modal.find('input:not([type=hidden]):first').focus();
}); function refreshequipmentTypeList() {
location.reload(true); //reload page to see new equipmentType!
} function deleteequipmentType(equipmentTypeId, equipmentTypeName) {
abp.message.confirm(
abp.utils.formatString(abp.localization.localize('AreYouSureWantToDelete', 'oMES_APServer'), equipmentTypeName),
function (isConfirmed) {
if (isConfirmed) {
_equipmentTypeService.delete({
id: equipmentTypeId
}).done(function () {
refreshequipmentTypeList();
});
}
}
);
}
});
})();
编辑模型的脚本_EditEquipmentTypeModal.js如下
(function ($) { var _equipmentTypeService = abp.services.app.equipmentType;
var _$modal = $('#EquipmentTypeEditModal');
var _$form = $('form[name=EquipmentTypeEditForm]'); function save() { if (!_$form.valid()) {
return;
} var equipmentType = _$form.serializeFormToObject(); //serializeFormToObject is defined in main.js abp.ui.setBusy(_$form);
_equipmentTypeService.update(equipmentType).done(function () {
_$modal.modal('hide');
location.reload(true); //reload page to see edited equipmentType!
}).always(function () {
abp.ui.clearBusy(_$modal);
});
} //Handle save button click
_$form.closest('div.modal-content').find(".save-button").click(function (e) {
e.preventDefault();
save();
}); //Handle enter key
_$form.find('input').on('keypress', function (e) {
if (e.which === ) {
e.preventDefault();
save();
}
}); $.AdminBSB.input.activate(_$form); _$modal.on('shown.bs.modal', function () {
_$form.find('input[type=text]:first').focus();
});
})(jQuery);
10. 添加前端菜单(入口)。
菜单需在startup文件夹 xxxNavigationProvider类中,添加.AddItem代码。
.AddItem放置的顺序不同,界面中的显示顺序就不同。
using Abp.Application.Navigation;
using Abp.Localization;
using oMES_APServer.Authorization; namespace oMES_APServer.Web.Startup
{
/// <summary>
/// This class defines menus for the application.
/// </summary>
public class oMES_APServerNavigationProvider : NavigationProvider
{
public override void SetNavigation(INavigationProviderContext context)
{
context.Manager.MainMenu
.AddItem(
new MenuItemDefinition(
PageNames.EquipmentTypes,
L("EquipmentTypes"),
url: "EquipmentTypes",
icon: "info"
)
)
以下省略
MenuItemDefinition的各参数看名字就能理解,从上到下依次是:
菜单名称,
菜单显示名称,
url:链接,即控制器名称
icon:图标名称,会根据名称自动查找对应的图标文件。
11. 添加权限管理。
通常的权限管理方式为:人员->角色->权限。
即为人员分配角色,为角色分配权限,这样就避免了多人相同权限时,重复分配的工作。
此处将设备管理功能(菜单)分配给对应的角色。
需要添加如下代码:
1、添加权限名称
namespace oMES_APServer.Authorization
{
public static class PermissionNames
{
public const string Pages_Tenants = "Pages.Tenants";
public const string Pages_Users = "Pages.Users";
public const string Pages_Roles = "Pages.Roles";
//添加自定义权限名称
public const string Pages_Companies = "Pages.Companies";
public const string Pages_Departments = "Pages.Departments"; public const string Pages_EquipmentTypes = "Pages.EquipmentTypes";
}
}
2、系统权限列表中,添加该权限名称
using Abp.Authorization;
using Abp.Localization;
using Abp.MultiTenancy; namespace oMES_APServer.Authorization
{
public class oMES_APServerAuthorizationProvider : AuthorizationProvider
{
public override void SetPermissions(IPermissionDefinitionContext context)
{
context.CreatePermission(PermissionNames.Pages_Users, L("Users"));
context.CreatePermission(PermissionNames.Pages_Roles, L("Roles"));
context.CreatePermission(PermissionNames.Pages_Tenants, L("Tenants"), multiTenancySides: MultiTenancySides.Host); //添加自定义权限
context.CreatePermission(PermissionNames.Pages_Companies, L("Companies"));
context.CreatePermission(PermissionNames.Pages_Departments, L("Departments"));
context.CreatePermission(PermissionNames.Pages_EquipmentTypes, L("EquipmentTypes"));
} private static ILocalizableString L(string name)
{
return new LocalizableString(name, oMES_APServerConsts.LocalizationSourceName);
}
}
}
3、菜单中添加权限控制
requiredPermissionName: PermissionNames.Pages_Companies
4、控制器中添加权限控制
[AbpAuthorize(PermissionNames.Pages_EquipmentTypes)]
5、应用服务方法中添加权限控制
[AbpAuthorize(PermissionNames.Pages_EquipmentTypes)]
添加完成后,运行程序,角色管理中,就可以单独选择该功能的权限了。
12. 文本翻译。
ABP的翻译方法在xxx.Core项目Localization文件夹中
默认支持9种语言。
添加中文翻译,只需在xxx-zh-Hans.xml文件中添加相应字段即可。
这要注意一下:xml中的子项,如果name值相同的话,会报错。所以每次添加新翻译时,先检查一下name值是否重复。
如下添加即可:
到此,一个基础资料的基础功能就完成了。
之后会继续完善所有的基础功能,中间有对ABP功能的研究也会一点一点写出来。
【ABP】从零开始学习ABP_001_新建实体功能的更多相关文章
- 【ABP】从零开始学习ABP_入门介绍
本文介绍自己入坑ABP的过程,一些ABP的相关文章.QQ群,以及ABP Zero示例项目的运行. 背景 作为一个半路出家学习编程的新人,之前工作中也断断续续写过一些代码,但底层核心一直没机会学习,所以 ...
- ASP.NET从零开始学习EF的增删改查
ASP.NET从零开始学习EF的增删改查 最近辞职了,但是离真正的离职还有一段时间,趁着这段空档期,总想着写些东西,想来想去,也不是很明确到底想写个啥,但是闲着也是够 ...
- Microsoft Dynamics CRM 2011 新建实体 需要注意的细节
新建一个实体,需要红色框内的是否勾选的意义,可以进一步加深对CRM的理解.如图: 下面对部分的进行了自我的理解,不对的地方,还请大家指出来.互相学习. 1.CRM2011中,在活动方面加强的新特性包括 ...
- 从零开始学习CocoaPods安装和使用
从零开始学习CocoaPods安装和使用 转载: Code4App原创:http://code4app.com/article/cocoapods-install-usage http://m.i ...
- ABP Framework V4.4 RC 新增功能介绍
目录 新增功能概述 启动模板删除 EntityFrameworkCore.DbMigrations 项目 CMS-Kit 动态菜单管理 Razor引擎对文本模板的支持 DbContext/Entiti ...
- 结合ABP源码实现邮件发送功能
1. 前言 2. 实现过程 1. 代码图(重) 2.具体实现 2.1 定义AppSettingNames及AppSettingProvider 2.2 EmailSenderConfiguration ...
- 从零开始学习jQuery (五) 事件与事件对象
本系列文章导航 从零开始学习jQuery (五) 事件与事件对象 一.摘要 事件是脚本编程的灵魂. 所以本章内容也是jQuery学习的重点. 本文将对jQuery中的事件处理以及事件对象进行详细的讲解 ...
- 从零开始学习jQuery (二) 万能的选择器
本系列文章导航 从零开始学习jQuery (二) 万能的选择器 一.摘要 本章讲解jQuery最重要的选择器部分的知识. 有了jQuery的选择器我们几乎可以获取页面上任意的一个或一组对象, 可以明显 ...
- 从零开始学习jQuery (一) 入门篇
本系列文章导航 从零开始学习jQuery (一) 入门篇 一.摘要 本系列文章将带您进入jQuery的精彩世界, 其中有很多作者具体的使用经验和解决方案, 即使你会使用jQuery也能在阅读中发现些 ...
随机推荐
- 批量导出存储在msdb库的SSIS包
http://blog.51cto.com/ultrasql/1924464 use msdb go IF OBJECT_ID('msdb.dbo.usp_ExportSSISPkgs') IS NO ...
- 安装完 Ubuntu 16.04.1,重启出现[sda] Assuming drive cache: write through的问题
重装了一下ubuntu,安装成功后重启出现了这个问题 刚开始以为是重启慢,就没在意这么多,可是我等了半个小时,(我特么的真闲,其实是忙别的忘了),还不行,咦,然后我就去找了找问题,哈哈哈哈 看图说话, ...
- Python基础模块整理
1.shutil :可以用来对文件进行基本操作(拷贝,剪切等) 2.glob :提供了一个函数用于从目录通配符搜索中生成文件列表 3.datetime :日期和时间的处理 4.zlib ...
- 【PAT甲级】1065 A+B and C (64bit) (20 分)(大数溢出)
题意: 输入三个整数A,B,C(long long范围内),输出是否A+B>C. trick: 测试点2包括溢出的数据,判断一下是否溢出即可. AAAAAccepted code: #defin ...
- [ DLPytorch ] 批量归一化与残差网络
批量归一化 通常来说,数据标准化预处理对于浅层模型就足够有效了.随着模型训练的进行,当每层中参数更新时,靠近输出层的输出较难出现剧烈变化.但对深层神经网络来说,即使输入数据已做标准化,训练中模型参数的 ...
- windows下安装elasticsearch-6.4.3和elasticsearch-head插件
windows下安装elasticsearch-6.4.3和elasticsearch-head插件 博客分类: elasticsearch es ElasticSearch下载地址:https:/ ...
- Java连载66-数组的两种初始化方式
一.数组 1.数组中存储元素的类型是统一的,每一个元素在内存中所占用的空间大小是相同的,知道数组的首元素的内存地址,要查找的元素只要知道下标,就可以快速的计算出偏移量,通过首元素内存地址加上偏移量,就 ...
- jquery怎么获取当前标签下的子标签
1.var num1=$("ul > a:eq(0)").attr("ID");2.var num2=$("ul").children ...
- mysql cmmand not found
https://www.cnblogs.com/yangzigege/p/8337393.html
- HashMap与HashTable源码学习及效率比较分析
一.个人学习后的见解: 首先表明学习源码后的个人见解,后续一次依次进行分析: 1.线程安全:HashMap是非线程安全的,HashTable是线程安全的(HashTable中使用了synchroniz ...