上一篇文章中介绍了如何下载、运行ABP Zero示例项目,这个示例项目可以直接作为模板进行二次开发,很适合做企业开发框架。

本未介绍基于ABP Zero示例项目,如何新建一个自定义的实体。

此处已EquipmentType(设备类型)为例,建立一个简单的实体。

以下是之前添加一个简单实体类的效果:

主页

公司列表

新建公司

编辑公司

删除公司


建立方法

按ABP的标准格式,完整建立一个实体,映射到数据库,作为一个基础资料,并通过前端进行增删查改功能,最小步骤如下:

  1. 新增实体类。
  2. 添加数据库映射。
  3. 同步到数据库。
  4. 新建Dto,建立Dto与实体类的映射。
  5. 建立实体类的功能接口(增删查改),并实现接口。
  6. 添加视图模型ViewModel。
  7. 添加控制器。
  8. 添加视图。
  9. 添加js脚本。
  10. 添加前端菜单(入口)。
  11. 添加权限管理。

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. 同步到数据库。

依次执行以下两条指令:

  1. add-migration add-EquipmentType
  2. 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功能的研究也会一点一点写出来。

最新文章

  1. 【容器云】传统金融企业的 Docker 实践
  2. C++STL学习笔记_(1)deque双端数组知识
  3. Hadoop学习笔记1-如何简单布署hadoop
  4. freemarker如何遍历HashMap
  5. Linux下循环、选择、顺序操作
  6. Flex4 DataGrid实现可复制单元格,同时解决自定义GridItemRenderer出现1009错误的方法
  7. MySql相关及如何删除MySql服务
  8. Difference Between Primes
  9. java web 之 WebRoot和WebContent目录
  10. 【linux kernel】 softirq 软中断讨论
  11. MVC模式学习笔记
  12. Canvas的下雪效果
  13. C#使用WebClient下载文件到本地目录
  14. jenkins X实践系列(3) —— jenkins X 安装拾遗
  15. 重写select样式
  16. 关键字提取算法TF-IDF和TextRank(python3)————实现TF-IDF并jieba中的TF-IDF对比,使用jieba中的实现TextRank
  17. SMB扫描
  18. 第二十七天- 网络通信协议 TCP UDP 缓冲区
  19. 使用phpstorm+wamp实现php代码实时调试审计
  20. Android开发学习笔记-md5加密算法

热门文章

  1. 安洵杯iamthinking(tp6反序列化链)
  2. Perl 笔记
  3. java中对于多态的一个实例分析
  4. js里常见的三种请求方式$.ajax、$.post、$.get分析
  5. lora
  6. HDFS核心类FileSystem的使用
  7. Pycharm 在 import requests 时报错
  8. Redis数据库与python的交互
  9. ADO.Net实体数据模型添加DB-First/Code First报错
  10. 避免学习Linux走弯路