之前寫到使用.net core ABP 和Angular模板構(gòu)建項目,創(chuàng)建后端服務(wù)。文章地址:http://www.reibang.com/p/fde1ea20331f
創(chuàng)建完成后的api基本是不能用的,現(xiàn)在根據(jù)我們自己的業(yè)務(wù)邏輯來實現(xiàn)后端服務(wù)橙依。
部分業(yè)務(wù)邏輯流程圖
其他功能流程省略
創(chuàng)建Dto并添加數(shù)據(jù)校驗
關(guān)于ABP的數(shù)據(jù)校驗可以參考我這篇文章:http://www.reibang.com/p/144f5cdd3ac8
ICustomValidate 接口用于自定義數(shù)據(jù)驗證,IShouldNormalize接口用于數(shù)據(jù)標(biāo)準化
這里就直接貼代碼了
namespace MZC.Blog.Notes
{
/// <summary>
/// 創(chuàng)建的時候不需要太多信息,內(nèi)容更新主要依靠update
/// 在用戶點擊創(chuàng)建的時候數(shù)據(jù)庫便創(chuàng)建數(shù)據(jù)椒功,在用戶編輯過程中自動更新保存數(shù)據(jù)。
/// </summary>
public class CreateNoteDto : IShouldNormalize
{
/// <summary>
/// 創(chuàng)建時間
/// </summary>
public DateTime? CreationTime { get; set; }
/// <summary>
/// 創(chuàng)建人
/// </summary>
public long CreatorUserId { get; set; }
/// <summary>
/// 內(nèi)容的數(shù)據(jù)類型 markdown內(nèi)容智什,html內(nèi)容动漾,或者其他
/// </summary>
public int TextType { get; set; }
public void Normalize()
{
if (!CreationTime.HasValue) CreationTime = DateTime.Now;
}
}
/// <summary>
/// 自動更新所傳的數(shù)據(jù)
/// </summary>
public class UpdateNoteDto : EntityDto<int>, IShouldNormalize
{
/// <summary>
/// 標(biāo)題
/// </summary>
public string Title { get; set; }
/// <summary>
/// 內(nèi)容
/// </summary>
public string Content { get; set; }
/// <summary>
/// 上次修改時間
/// </summary>
public DateTime? LastModificationTime { get; set; }
public virtual void Normalize()
{
if (!LastModificationTime.HasValue)
{
LastModificationTime = DateTime.Now;
}
}
}
/// <summary>
/// 發(fā)布更新時所用
/// </summary>
public class PublicNoteDto : UpdateNoteDto, ICustomValidate, IShouldNormalize
{
/// <summary>
/// 簡單描述,用于微信推送時的描述或者其他
/// </summary>
public string Des { get; set; }
/// <summary>
/// 封面圖片荠锭,可用于微信推送時或者其他
/// </summary>
[Required]
public string Img { get; set; }
/// <summary>
/// 關(guān)鍵字旱眯,可用于搜索,分類等
/// </summary>
public string Tags { get; set; }
/// <summary>
/// 是否發(fā)布
/// </summary>
public bool? IsPublic { get; set; }
public override void Normalize()
{
base.Normalize();
IsPublic = true;
}
public void AddValidationErrors(CustomValidationContext context)
{
if (string.IsNullOrEmpty(Des))
{
string error = "描述不能為空!";
context.Results.Add(new ValidationResult(error));
}
if (Des.Length < 10)
{
string error = "描述不能少于10個字删豺!";
context.Results.Add(new ValidationResult(error));
}
if (Des.Length > 200)
{
string error = "描述不能大于200個字共虑!";
context.Results.Add(new ValidationResult(error));
}
}
}
/// <summary>
/// 用于列表展示
/// </summary>
public class NoteDto : EntityDto<int>
{
/// <summary>
/// 標(biāo)題
/// </summary>
public string Title { get; set; }
/// <summary>
/// 創(chuàng)建時間
/// </summary>
public string CreationTime { get; set; }
/// <summary>
/// 點贊次數(shù)
/// </summary>
public long Like { get; set; }
/// <summary>
/// 收藏次數(shù)
/// </summary>
public long Collect { get; set; }
/// <summary>
/// 瀏覽次數(shù)
/// </summary>
public long Scan { get; set; }
/// <summary>
/// 是否發(fā)布
/// </summary>
public string IsPublic { get; set; }
}
public class GetNoteListDto: PagedResultRequestDto
{
/// <summary>
/// 用于搜索的關(guān)鍵字
/// </summary>
public string key { get; set; }
}
}
創(chuàng)建映射
創(chuàng)建NoteMapProfile.cs文件,并添加相關(guān)映射
關(guān)于ABP框架映射的更多內(nèi)容請參考我這篇文章:http://www.reibang.com/p/6ef125e873e9
namespace MZC.Blog.Notes
{
public class NoteMapProfile : Profile
{
public NoteMapProfile()
{
CreateMap<CreateNoteDto, Note>();
CreateMap<UpdateNoteDto, Note>();
CreateMap<PublicNoteDto, Note>();
//使用自定義解析
CreateMap<Note, NoteDto>().ForMember(x=>x.IsPublic,opt=> {
opt.ResolveUsing<NoteToNoteDtoResolver>();
});
CreateMap<Note, PublicNoteDto>();
}
}
/// <summary>
/// 自定義解析
/// </summary>
public class NoteToNoteDtoResolver : IValueResolver<Note, NoteDto, string>
{
public string Resolve(Note source, NoteDto destination, string destMember, ResolutionContext context)
{
return source.IsPublic ? "已發(fā)布" : "未發(fā)布";
}
}
}
使用授權(quán)
關(guān)于ABP授權(quán)詳細的介紹和使用請看我的另一篇文章:http://www.reibang.com/p/6e224f4f9705
在core項目Authorization文件夾下有模板提供的授權(quán)模塊呀页。
在PermissionNames 中定義權(quán)限妈拌,在AuthorizationProvider中添加定義的權(quán)限,然后再項目中就可以通過AbpAuthorize特性或者PermissionChecker類來驗證
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";
/// <summary>
/// 博客管理頁面權(quán)限
/// </summary>
public const string Pages_Blogs = "Pages.Blogs";
public const string Pages_Blogs_Notes = "Pages.Blogs.Notes";
public const string Blogs_Notes_Edit = "Pages.Blogs.Notes.Edit";
public const string Blogs_Notes_Delete = "Pages.Blogs.Notes.Delete";
}
public class MZCAuthorizationProvider : 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);
var BlogPermission = context.CreatePermission(PermissionNames.Pages_Blogs, L("Blogs"));
var NotePermission = BlogPermission.CreateChildPermission(PermissionNames.Pages_Blogs_Notes,L("Notes"));
NotePermission.CreateChildPermission(PermissionNames.Blogs_Notes_Edit, L("EditNotes"));
NotePermission.CreateChildPermission(PermissionNames.Blogs_Notes_Delete, L("DeleteNotes"));
}
private static ILocalizableString L(string name)
{
return new LocalizableString(name, MZCConsts.LocalizationSourceName);
}
}
完善我們的服務(wù)和接口
因為是自己的博客系統(tǒng)蓬蝶,沒必要那么麻煩就只使用了入口權(quán)限定義在類的上面尘分。
public interface INoteAppServer: IAsyncCrudAppService<NoteDto,int, GetNoteListDto, CreateNoteDto,UpdateNoteDto>
{
Task PublicNote(PublicNoteDto input);
Task<PublicNoteDto> GetNote(EntityDto<int> input);
}
[AbpAuthorize(PermissionNames.Pages_Blogs_Notes)]
public class NoteAppServer : AsyncCrudAppService<Note, NoteDto, int, GetNoteListDto, CreateNoteDto, UpdateNoteDto>, INoteAppServer
{
public NoteAppServer(IRepository<Note> repository)
: base(repository)
{
}
public override async Task<NoteDto> Create(CreateNoteDto input)
{
var note = ObjectMapper.Map<Note>(input);
var result = await Repository.InsertAsync(note);
return ObjectMapper.Map<NoteDto>(result);
}
public async Task PublicNote(PublicNoteDto input)
{
var note = Repository.Get(input.Id);
ObjectMapper.Map(input,note);
var result = await Repository.UpdateAsync(note);
}
public override async Task<NoteDto> Update(UpdateNoteDto input)
{
var note = Repository.Get(input.Id);
ObjectMapper.Map(input,note);
var result = await Repository.UpdateAsync(note);
return ObjectMapper.Map<NoteDto>(result);
}
public override async Task<PagedResultDto<NoteDto>> GetAll(GetNoteListDto input)
{
var data = Repository.GetAll().Where(m => !m.IsDeleted);
data = data.WhereIf(!string.IsNullOrEmpty(input.key), m => m.Title.Contains(input.key) || m.Tags.Contains(input.key));
int count = await data.CountAsync();
var notes = await data.OrderByDescending(q => q.CreationTime)
.PageBy(input)
.ToListAsync();
return new PagedResultDto<NoteDto>()
{
TotalCount = count,
Items = ObjectMapper.Map<List<NoteDto>>(notes)
};
}
public async Task<PublicNoteDto> GetNote(EntityDto<int> input)
{
var note = await Repository.GetAsync(input.Id);
return ObjectMapper.Map<PublicNoteDto>(note);
}
}