series

  1. Develop blog projects based on ABP vNext and.NET Core – build projects using ABP CLI
  2. Develop blog projects based on ABP vNext and.NET Core – slim the project down and make it run
  3. Development blog project based on ABP vNext and.NET Core – Refinement and beautification, Swagger enter
  4. Develop blog project based on ABP vNext and.NET Core – data access and code priority
  5. Development blog project based on ABP vNext and.NET Core – add, delete, change and check custom warehouse
  6. Develop blog project based on ABP vNext and.NET Core – Uniform specification API, wrapper back model
  7. Develop blog projects based on ABP vNext and.NET Core – say Swagger, grouping, description, little green lock
  8. Develop blog projects based on ABP vNext and.NET Core – access GitHub and protect your API with JWT
  9. Develop blog project based on ABP vNext and.NET Core – exception handling and logging
  10. Develop blog projects based on ABP vNext and.NET Core – using Redis to cache data
  11. Develop blog project based on ABP vNext and.NET Core – integrate Hangfire for timed task processing
  12. Develop blog projects based on ABP vNext and.NET Core – Use AutoMapper to map objects
  13. Developing blog projects based on ABP vNext and.NET Core – Best Practices for Timed Tasks (Part 1)
  14. Developing blog projects based on ABP vNext and.NET Core – Best Practices for Timed Tasks (Part 2)
  15. Developing blog projects based on ABP vNext and.NET Core – Best Practices for Timed Tasks (PART 3)
  16. Blog Development project based on ABP vNext and.NET Core
  17. Abp vNext and.NET Core
  18. Blog Development project based on ABP vNext and.NET Core
  19. Blog Development project based on ABP vNext and.NET Core
  20. Blog Development project based on ABP vNext and.NET Core
  21. Abp vNext and.NET Core Development Blog Project – Blazor
  22. Abp vNext and.NET Core Development Blog Project – Blazor – Part 2
  23. Abp vNext and.NET Core Development Blog Project – Blazor
  24. Abp vNext and.NET Core Development Blog Project – Blazor
  25. Abp vNext and.NET Core Development Blog Project – Blazor
  26. Abp vNext and.NET Core Development Blog Project – Blazor – Part 6
  27. Abp vNext and.NET Core Development Blog Project – Blazor
  28. Abp vNext and.NET Core Development Blog Project – Blazor Series (8)
  29. Abp vNext and.NET Core Development Blog Project – Blazor Series (9)
  30. Abp vNext and.NET Core development blog project – Final release project

The previous article completed the article details page data query and clear the cache function.

This article continues to complete the classification, label, friendship link background operation interface, or the same sentence, these pure CRUD content, it is better to do it by yourself, this will no longer be tedious, directly paste code for reference.

classification

Add an interface: query classification list QueryCategoriesForAdminAsync (), the new classification InsertCategoryAsync (…). UpdateCategoryAsync(…) DeleteCategoryAsync(…)

#region Categories

/// <summary>
///Querying a Category List
/// </summary>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryCategoryForAdminDto>>> QueryCategoriesForAdminAsync();

/// <summary>
///The new classification
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task<ServiceResult> InsertCategoryAsync(EditCategoryInput input);

/// <summary>
///Update the classification
/// </summary>
/// <param name="id"></param>
/// <param name="input"></param>
/// <returns></returns>
Task<ServiceResult> UpdateCategoryAsync(int id, EditCategoryInput input);

/// <summary>
///Delete the classification
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
Task<ServiceResult> DeleteCategoryAsync(int id);

#endregion Categories
Copy the code

Query classification list need to return model class QueryCategoryForAdminDto. Cs.

//QueryCategoryForAdminDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{
    public class QueryCategoryForAdminDto : QueryCategoryDto
    {
        /// <summary>
        ///A primary key
        /// </summary>
        public int Id { get; set; }}}Copy the code

New category and update category input parameter editCategoryInput. cs, inherit CategoryDto directly.

//EditCategoryInput.cs
namespace Meowv.Blog.Application.Contracts.Blog.Params
{
    public class EditCategoryInput : CategoryDto{}}Copy the code

Implement these interfaces separately.

/// <summary>
///Querying a Category List
/// </summary>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryCategoryForAdminDto>>> QueryCategoriesForAdminAsync()
{
    var result = new ServiceResult<IEnumerable<QueryCategoryForAdminDto>>();

    var posts = await _postRepository.GetListAsync();

    var categories = _categoryRepository.GetListAsync().Result.Select(x => new QueryCategoryForAdminDto
    {
        Id = x.Id,
        CategoryName = x.CategoryName,
        DisplayName = x.DisplayName,
        Count = posts.Count(p => p.CategoryId == x.Id)
    });

    result.IsSuccess(categories);
    return result;
}
Copy the code
/// <summary>
///The new classification
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public async Task<ServiceResult> InsertCategoryAsync(EditCategoryInput input)
{
    var result = new ServiceResult();

    var category = ObjectMapper.Map<EditCategoryInput, Category>(input);
    await _categoryRepository.InsertAsync(category);

    result.IsSuccess(ResponseText.INSERT_SUCCESS);
    return result;
}
Copy the code

An AutoMapper configuration is required to convert EditCategoryInput to Category, ignoring the Id field.

CreateMap<EditCategoryInput, Category>().ForMember(x => x.Id, opt => opt.Ignore());
Copy the code
/// <summary>
///Update the classification
/// </summary>
/// <param name="id"></param>
/// <param name="input"></param>
/// <returns></returns>
public async Task<ServiceResult> UpdateCategoryAsync(int id, EditCategoryInput input)
{
    var result = new ServiceResult();

    var category = await _categoryRepository.GetAsync(id);
    category.CategoryName = input.CategoryName;
    category.DisplayName = input.DisplayName;

    await _categoryRepository.UpdateAsync(category);

    result.IsSuccess(ResponseText.UPDATE_SUCCESS);
    return result;
}
Copy the code
/// <summary>
///Delete the classification
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<ServiceResult> DeleteCategoryAsync(int id)
{
    var result = new ServiceResult();

    var category = await _categoryRepository.FindAsync(id);
    if (null == category)
    {
        result.IsFailed(ResponseText.WHAT_NOT_EXIST.FormatWith("Id", id));
        return result;
    }

    await _categoryRepository.DeleteAsync(id);

    result.IsSuccess(ResponseText.DELETE_SUCCESS);
    return result;
}
Copy the code

Add an interface to blogController.admin.cs.

#region Categories

/// <summary>
///Querying a Category List
/// </summary>
/// <returns></returns>
[HttpGet]
[Authorize]
[Route("admin/categories")]
[ApiExplorerSettings(GroupName = Grouping.GroupName_v2)]
public async Task<ServiceResult<IEnumerable<QueryCategoryForAdminDto>>> QueryCategoriesForAdminAsync()
{
    return await _blogService.QueryCategoriesForAdminAsync();
}

/// <summary>
///The new classification
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost]
[Authorize]
[Route("category")]
[ApiExplorerSettings(GroupName = Grouping.GroupName_v2)]
public async Task<ServiceResult> InsertCategoryAsync([FromBody] EditCategoryInput input)
{
    return await _blogService.InsertCategoryAsync(input);
}

/// <summary>
///Update the classification
/// </summary>
/// <param name="id"></param>
/// <param name="input"></param>
/// <returns></returns>
[HttpPut]
[Authorize]
[Route("category")]
[ApiExplorerSettings(GroupName = Grouping.GroupName_v2)]
public async Task<ServiceResult> UpdateCategoryAsync([Required] int id, [FromBody] EditCategoryInput input)
{
    return await _blogService.UpdateCategoryAsync(id, input);
}

/// <summary>
///Delete the classification
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpDelete]
[Authorize]
[Route("category")]
[ApiExplorerSettings(GroupName = Grouping.GroupName_v2)]
public async Task<ServiceResult> DeleteCategoryAsync([Required] int id)
{
    return await _blogService.DeleteCategoryAsync(id);
}

#endregion Categories
Copy the code

The label

Add interface: QueryTagsForAdminAsync(), InsertTagAsync(…) UpdateTagAsync(…) DeleteTagAsync(…)

#region Tags

/// <summary>
///Querying the tag List
/// </summary>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryTagForAdminDto>>> QueryTagsForAdminAsync();

/// <summary>
///The new labels
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task<ServiceResult> InsertTagAsync(EditTagInput input);

/// <summary>
///Update the label
/// </summary>
/// <param name="id"></param>
/// <param name="input"></param>
/// <returns></returns>
Task<ServiceResult> UpdateTagAsync(int id, EditTagInput input);

/// <summary>
///Remove the label
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
Task<ServiceResult> DeleteTagAsync(int id);

#endregion Tags
Copy the code

The model class queryTagForadMindto.cs needs to be returned to query the tag list.

//QueryTagForAdminDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{
    public class QueryTagForAdminDto : QueryTagDto
    {
        /// <summary>
        ///A primary key
        /// </summary>
        public int Id { get; set; }}}Copy the code

The input parameter editTagInput. cs, which is required to add and update labels, is inherited from TagDto.

//EditTagInput.cs
namespace Meowv.Blog.Application.Contracts.Blog.Params
{
    public class EditTagInput : TagDto{}}Copy the code

Implement these interfaces separately.

/// <summary>
///Querying the tag List
/// </summary>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryTagForAdminDto>>> QueryTagsForAdminAsync()
{
    var result = new ServiceResult<IEnumerable<QueryTagForAdminDto>>();

    var post_tags = await _postTagRepository.GetListAsync();

    var tags = _tagRepository.GetListAsync().Result.Select(x => new QueryTagForAdminDto
    {
        Id = x.Id,
        TagName = x.TagName,
        DisplayName = x.DisplayName,
        Count = post_tags.Count(p => p.TagId == x.Id)
    });

    result.IsSuccess(tags);
    return result;
}
Copy the code
/// <summary>
///The new labels
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
public async Task<ServiceResult> InsertTagAsync(EditTagInput input)
{
    var result = new ServiceResult();

    var tag = ObjectMapper.Map<EditTagInput, Tag>(input);
    await _tagRepository.InsertAsync(tag);

    result.IsSuccess(ResponseText.INSERT_SUCCESS);
    return result;
}
Copy the code

An AutoMapper configuration is required to convert EditCategoryInput to a Tag, ignoring the Id field.

CreateMap<EditTagInput, Tag>().ForMember(x => x.Id, opt => opt.Ignore());
Copy the code
/// <summary>
///Update the label
/// </summary>
/// <param name="id"></param>
/// <param name="dto"></param>
/// <returns></returns>
public async Task<ServiceResult> UpdateTagAsync(int id, EditTagInput input)
{
    var result = new ServiceResult();

    var tag = await _tagRepository.GetAsync(id);
    tag.TagName = input.TagName;
    tag.DisplayName = input.DisplayName;

    await _tagRepository.UpdateAsync(tag);

    result.IsSuccess(ResponseText.UPDATE_SUCCESS);
    return result;
}
Copy the code
/// <summary>
///Remove the label
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<ServiceResult> DeleteTagAsync(int id)
{
    var result = new ServiceResult();

    var tag = await _tagRepository.FindAsync(id);
    if (null == tag)
    {
        result.IsFailed(ResponseText.WHAT_NOT_EXIST.FormatWith("Id", id));
        return result;
    }

    await _tagRepository.DeleteAsync(id);
    await _postTagRepository.DeleteAsync(x => x.TagId == id);

    result.IsSuccess(ResponseText.DELETE_SUCCESS);
    return result;
}
Copy the code

Add an interface to blogController.admin.cs.

#region Tags

/// <summary>
///Querying the tag List
/// </summary>
/// <returns></returns>
[HttpGet]
[Authorize]
[Route("admin/tags")]
[ApiExplorerSettings(GroupName = Grouping.GroupName_v2)]
public async Task<ServiceResult<IEnumerable<QueryTagForAdminDto>>> QueryTagsForAdminAsync()
{
    return await _blogService.QueryTagsForAdminAsync();
}

/// <summary>
///The new labels
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost]
[Authorize]
[Route("tag")]
[ApiExplorerSettings(GroupName = Grouping.GroupName_v2)]
public async Task<ServiceResult> InsertTagAsync([FromBody] EditTagInput input)
{
    return await _blogService.InsertTagAsync(input);
}

/// <summary>
///Update the label
/// </summary>
/// <param name="id"></param>
/// <param name="input"></param>
/// <returns></returns>
[HttpPut]
[Authorize]
[Route("tag")]
[ApiExplorerSettings(GroupName = Grouping.GroupName_v2)]
public async Task<ServiceResult> UpdateTagAsync([Required] int id, [FromBody] EditTagInput input)
{
    return await _blogService.UpdateTagAsync(id, input);
}

/// <summary>
///Remove the label
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpDelete]
[Authorize]
[Route("tag")]
[ApiExplorerSettings(GroupName = Grouping.GroupName_v2)]
public async Task<ServiceResult> DeleteTagAsync([Required] int id)
{
    return await _blogService.DeleteTagAsync(id);
}

#endregion Tags
Copy the code

Friends of the chain

Add interface: query friends QueryFriendLinksForAdminAsync chain list (), new friend chain InsertFriendLinkAsync (…). UpdateFriendLinkAsync(…) Delete friendChain DeleteFriendLinkAsync(…)

#region FriendLinks

/// <summary>
///Query the list of friends
/// </summary>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryFriendLinkForAdminDto>>> QueryFriendLinksForAdminAsync();

/// <summary>
///New friend chain
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task<ServiceResult> InsertFriendLinkAsync(EditFriendLinkInput input);

/// <summary>
///Update friends chain
/// </summary>
/// <param name="id"></param>
/// <param name="input"></param>
/// <returns></returns>
Task<ServiceResult> UpdateFriendLinkAsync(int id, EditFriendLinkInput input);

/// <summary>
///Delete friend chain
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
Task<ServiceResult> DeleteFriendLinkAsync(int id);

#endregion FriendLinks
Copy the code

Query friends chain list need to return model class QueryFriendLinkForAdminDto. Cs.

//QueryFriendLinkForAdminDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{
    public class QueryFriendLinkForAdminDto : FriendLinkDto
    {
        /// <summary>
        ///A primary key
        /// </summary>
        public int Id { get; set; }}}Copy the code

Friendfriendlinkinput. cs is the editFriendLinkinput. cs input parameter to create and update friendlinks.

//EditFriendLinkInput .cs
namespace Meowv.Blog.Application.Contracts.Blog.Params
{
    public class EditFriendLinkInput : FriendLinkDto{}}Copy the code

Implement these interfaces separately.

/// <summary>
///Query the list of friends
/// </summary>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryFriendLinkForAdminDto>>> QueryFriendLinksForAdminAsync()
{
    var result = new ServiceResult<IEnumerable<QueryFriendLinkForAdminDto>>();

    var friendLinks = await _friendLinksRepository.GetListAsync();

    var dto = ObjectMapper.Map<List<FriendLink>, IEnumerable<QueryFriendLinkForAdminDto>>(friendLinks);

    result.IsSuccess(dto);
    return result;
}
Copy the code
/// <summary>
///New friend chain
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public async Task<ServiceResult> InsertFriendLinkAsync(EditFriendLinkInput input)
{
    var result = new ServiceResult();

    var friendLink = ObjectMapper.Map<EditFriendLinkInput, FriendLink>(input);
    await _friendLinksRepository.InsertAsync(friendLink);

    // Clear the cache
    await _blogCacheService.RemoveAsync(CachePrefix.Blog_FriendLink);

    result.IsSuccess(ResponseText.INSERT_SUCCESS);
    return result;
}
Copy the code
/// <summary>
///Update friends chain
/// </summary>
/// <param name="id"></param>
/// <param name="input"></param>
/// <returns></returns>
public async Task<ServiceResult> UpdateFriendLinkAsync(int id, EditFriendLinkInput input)
{
    var result = new ServiceResult();

    var friendLink = await _friendLinksRepository.GetAsync(id);
    friendLink.Title = input.Title;
    friendLink.LinkUrl = input.LinkUrl;

    await _friendLinksRepository.UpdateAsync(friendLink);

    // Clear the cache
    await _blogCacheService.RemoveAsync(CachePrefix.Blog_FriendLink);

    result.IsSuccess(ResponseText.UPDATE_SUCCESS);
    return result;
}
Copy the code
/// <summary>
///Delete friend chain
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<ServiceResult> DeleteFriendLinkAsync(int id)
{
    var result = new ServiceResult();

    var friendLink = await _friendLinksRepository.FindAsync(id);
    if (null == friendLink)
    {
        result.IsFailed(ResponseText.WHAT_NOT_EXIST.FormatWith("Id", id));
        return result;
    }

    await _friendLinksRepository.DeleteAsync(id);

    // Clear the cache
    await _blogCacheService.RemoveAsync(CachePrefix.Blog_FriendLink);

    result.IsSuccess(ResponseText.DELETE_SUCCESS);
    return result;
}
Copy the code

There are two AutoMapper configurations in querying the friend list and adding a friend list.

CreateMap<FriendLink, QueryFriendLinkForAdminDto>();

CreateMap<EditFriendLinkInput, FriendLink>().ForMember(x => x.Id, opt => opt.Ignore());
Copy the code

Add an interface to blogController.admin.cs.

#region FriendLinks

/// <summary>
///Query the list of friends
/// </summary>
/// <returns></returns>
[HttpGet]
[Authorize]
[Route("admin/friendlinks")]
[ApiExplorerSettings(GroupName = Grouping.GroupName_v2)]
public async Task<ServiceResult<IEnumerable<QueryFriendLinkForAdminDto>>> QueryFriendLinksForAdminAsync()
{
    return await _blogService.QueryFriendLinksForAdminAsync();
}

/// <summary>
///New friend chain
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost]
[Authorize]
[Route("friendlink")]
[ApiExplorerSettings(GroupName = Grouping.GroupName_v2)]
public async Task<ServiceResult> InsertFriendLinkAsync([FromBody] EditFriendLinkInput input)
{
    return await _blogService.InsertFriendLinkAsync(input);
}

/// <summary>
///Update friends chain
/// </summary>
/// <param name="id"></param>
/// <param name="input"></param>
/// <returns></returns>
[HttpPut]
[Authorize]
[Route("friendlink")]
[ApiExplorerSettings(GroupName = Grouping.GroupName_v2)]
public async Task<ServiceResult> UpdateFriendLinkAsync([Required] int id, [FromBody] EditFriendLinkInput input)
{
    return await _blogService.UpdateFriendLinkAsync(id, input);
}

/// <summary>
///Delete friend chain
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpDelete]
[Authorize]
[Route("friendlink")]
[ApiExplorerSettings(GroupName = Grouping.GroupName_v2)]
public async Task<ServiceResult> DeleteFriendLinkAsync([Required] int id)
{
    return await _blogService.DeleteFriendLinkAsync(id);
}

#endregion
Copy the code

Next

By the end of this article, the back-end API portion of the abP vNext and.NET Core development blog project series has been fully developed.

This blog project series is I write code while recording the results, not after the completion of the development and then take out to write, involving things is not a lot, for beginners should be enough, if you gain from it, please share more forward.

Here, I hope you can pay attention to my wechat public account: “A Xing Plus”, the article will be first published in the public account.

Now with the API, you can choose to develop the front end interface in a familiar way. For example, the current online version of my blog uses ASP.NET Core Web. If you are interested, you can go to the release branch.

As for the front-end part, I saw some people calling vUE. To be honest, the front-end technology is not very good, and its main purpose is back-end development, which may not reach the expected effect.

So I am ready to enter the pit Blazor 😂, next learn now sell now, learn together do projects together progress, come on 💪

Open source: github.com/Meowv/Blog/…


It is better to study with the following courses

gk.link/a/10iQ7