series
- Develop blog projects based on ABP vNext and.NET Core – build projects using ABP CLI
- Develop blog projects based on ABP vNext and.NET Core – slim the project down and make it run
- Development blog project based on ABP vNext and.NET Core – Refinement and beautification, Swagger enter
- Develop blog project based on ABP vNext and.NET Core – data access and code priority
- Development blog project based on ABP vNext and.NET Core – add, delete, change and check custom warehouse
- Develop blog project based on ABP vNext and.NET Core – Uniform specification API, wrapper back model
- Develop blog projects based on ABP vNext and.NET Core – say Swagger, grouping, description, little green lock
- Develop blog projects based on ABP vNext and.NET Core – access GitHub and protect your API with JWT
- Develop blog project based on ABP vNext and.NET Core – exception handling and logging
- Develop blog projects based on ABP vNext and.NET Core – using Redis to cache data
- Develop blog project based on ABP vNext and.NET Core – integrate Hangfire for timed task processing
- Develop blog projects based on ABP vNext and.NET Core – Use AutoMapper to map objects
- Developing blog projects based on ABP vNext and.NET Core – Best Practices for Timed Tasks (Part 1)
- Developing blog projects based on ABP vNext and.NET Core – Best Practices for Timed Tasks (Part 2)
- Developing blog projects based on ABP vNext and.NET Core – Best Practices for Timed Tasks (PART 3)
- Blog Development project based on ABP vNext and.NET Core
- Abp vNext and.NET Core
- Blog Development project based on ABP vNext and.NET Core
- Blog Development project based on ABP vNext and.NET Core
- Blog Development project based on ABP vNext and.NET Core
- Abp vNext and.NET Core Development Blog Project – Blazor
- Abp vNext and.NET Core Development Blog Project – Blazor – Part 2
- Abp vNext and.NET Core Development Blog Project – Blazor
- Abp vNext and.NET Core Development Blog Project – Blazor
- Abp vNext and.NET Core Development Blog Project – Blazor
- Abp vNext and.NET Core Development Blog Project – Blazor – Part 6
- Abp vNext and.NET Core Development Blog Project – Blazor
- Abp vNext and.NET Core Development Blog Project – Blazor Series (8)
- Abp vNext and.NET Core Development Blog Project – Blazor Series (9)
- Abp vNext and.NET Core development blog project – Final release project
The previous article completed two interfaces: the article list page and the article details page. This article continues.
Classification list
Analysis: You can create a new model QueryCategoryDto. Cs to inherit CategoryDto.
//QueryCategoryDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{
public class QueryCategoryDto : CategoryDto
{
/// <summary>
///The total number of
/// </summary>
public int Count { get; set; }}}Copy the code
Add the query category list interface and cache interface.
//IBlogService.Category.cs
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Meowv.Blog.Application.Blog
{
public partial interface IBlogService
{
/// <summary>
///Querying a Category List
/// </summary>
/// <returns></returns>Task<ServiceResult<IEnumerable<QueryCategoryDto>>> QueryCategoriesAsync(); }}Copy the code
//IBlogCacheService.Category.cs
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Meowv.Blog.Application.Caching.Blog
{
public partial interface IBlogCacheService
{
/// <summary>
///Querying a Category List
/// </summary>
/// <param name="factory"></param>
/// <returns></returns>Task<ServiceResult<IEnumerable<QueryCategoryDto>>> QueryCategoriesAsync(Func<Task<ServiceResult<IEnumerable<QueryCategoryDto>>>> factory); }}Copy the code
Implement the two interfaces separately.
//BlogCacheService.Category.cs
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using static Meowv.Blog.Domain.Shared.MeowvBlogConsts;
namespace Meowv.Blog.Application.Caching.Blog.Impl
{
public partial class BlogCacheService
{
private const string KEY_QueryCategories = "Blog:Category:QueryCategories";
/// <summary>
///Querying a Category List
/// </summary>
/// <param name="factory"></param>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryCategoryDto>>> QueryCategoriesAsync(Func<Task<ServiceResult<IEnumerable<QueryCategoryDto>>>> factory)
{
return awaitCache.GetOrAddAsync(KEY_QueryCategories, factory, CacheStrategy.ONE_DAY); }}}Copy the code
//BlogService.Category.cs
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Meowv.Blog.Application.Blog.Impl
{
public partial class BlogService
{
/// <summary>
///Querying a Category List
/// </summary>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryCategoryDto>>> QueryCategoriesAsync()
{
return await _blogCacheService.QueryCategoriesAsync(async() = > {var result = new ServiceResult<IEnumerable<QueryCategoryDto>>();
var list = from category in await _categoryRepository.GetListAsync()
join posts in await _postRepository.GetListAsync()
on category.Id equals posts.CategoryId
group category by new
{
category.CategoryName,
category.DisplayName
} into g
select new QueryCategoryDto
{
CategoryName = g.Key.CategoryName,
DisplayName = g.Key.DisplayName,
Count = g.Count()
};
result.IsSuccess(list);
returnresult; }); }}}Copy the code
Instead of caching, query the category list, syndicate the articles and categories tables with CategoryId fields, group them, calculate the number, and add the API to BlogController.
/// <summary>
///Querying a Category List
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("categories")]
public async Task<ServiceResult<IEnumerable<QueryCategoryDto>>> QueryCategoriesAsync()
{
return await _blogService.QueryCategoriesAsync();
}
Copy the code
The tag list
Analysis: Similar to the classification list, create a new model queryTagTo.cs that inherits TagDto.
//QueryTagDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{
public class QueryTagDto : TagDto
{
/// <summary>
///The total number of
/// </summary>
public int Count { get; set; }}}Copy the code
Add query label list interface and cache interface.
//IBlogCacheService.Tag.cs
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Meowv.Blog.Application.Caching.Blog
{
public partial interface IBlogCacheService
{
/// <summary>
///Querying the tag List
/// </summary>
/// <param name="factory"></param>
/// <returns></returns>Task<ServiceResult<IEnumerable<QueryTagDto>>> QueryTagsAsync(Func<Task<ServiceResult<IEnumerable<QueryTagDto>>>> factory); }}Copy the code
//IBlogService.Tag.cs
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Meowv.Blog.Application.Blog
{
public partial interface IBlogService
{
/// <summary>
///Querying the tag List
/// </summary>
/// <returns></returns>Task<ServiceResult<IEnumerable<QueryTagDto>>> QueryTagsAsync(); }}Copy the code
Implement the two interfaces separately.
//BlogCacheService.Tag.cs
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using static Meowv.Blog.Domain.Shared.MeowvBlogConsts;
namespace Meowv.Blog.Application.Caching.Blog.Impl
{
public partial class BlogCacheService
{
private const string KEY_QueryTags = "Blog:Tag:QueryTags";
/// <summary>
///Querying the tag List
/// </summary>
/// <param name="factory"></param>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryTagDto>>> QueryTagsAsync(Func<Task<ServiceResult<IEnumerable<QueryTagDto>>>> factory)
{
return awaitCache.GetOrAddAsync(KEY_QueryTags, factory, CacheStrategy.ONE_DAY); }}}Copy the code
//BlogService.Tag.cs
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Meowv.Blog.Application.Blog.Impl
{
public partial class BlogService
{
/// <summary>
///Querying the tag List
/// </summary>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryTagDto>>> QueryTagsAsync()
{
return await _blogCacheService.QueryTagsAsync(async() = > {var result = new ServiceResult<IEnumerable<QueryTagDto>>();
var list = from tags in await _tagRepository.GetListAsync()
join post_tags in await _postTagRepository.GetListAsync()
on tags.Id equals post_tags.TagId
group tags by new
{
tags.TagName,
tags.DisplayName
} into g
select new QueryTagDto
{
TagName = g.Key.TagName,
DisplayName = g.Key.DisplayName,
Count = g.Count()
};
result.IsSuccess(list);
returnresult; }); }}}Copy the code
To query the tag list, you need to jointly query tags and post_tags, associate them according to TagId, and then group them to obtain the total number of articles under the tag. Add API in BlogController.
/// <summary>
///Querying the tag List
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("tags")]
public async Task<ServiceResult<IEnumerable<QueryTagDto>>> QueryTagsAsync()
{
return await _blogService.QueryTagsAsync();
}
Copy the code
List of category names & articles
Analysis: This page contains two interfaces, query the name of the category and the list of articles under the current category, unlike the list of articles, it does not have pagination. Category contains two fields, category name and display name, we need to query the real name to display on the page.
Category name
There is no need to add a return model to it, just return a string, and give a query parameter name, add the interface to get the category name and cache interface.
//IBlogService.Category.cs
/// <summary>
///Get category name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
Task<ServiceResult<string>> GetCategoryAsync(string name);
Copy the code
//IBlogCacheService.Category.cs
/// <summary>
///Get category name
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
Task<ServiceResult<string>> GetCategoryAsync(string name, Func<Task<ServiceResult<string>>> factory);
Copy the code
Implement both interfaces.
//BlogCacheService.Category.cs.public partial class BlogCacheService
{
private const string KEY_GetCategory = "Blog:Category:GetCategory-{0}";
/// <summary>
///Get category name
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
public async Task<ServiceResult<string>> GetCategoryAsync(string name, Func<Task<ServiceResult<string>>> factory)
{
return awaitCache.GetOrAddAsync(KEY_GetCategory.FormatWith(name), factory, CacheStrategy.ONE_DAY); }}...Copy the code
//BlogService.Category.cs
/// <summary>
///Get category name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public async Task<ServiceResult<string>> GetCategoryAsync(string name)
{
return await _blogCacheService.GetCategoryAsync(name, async() = > {var result = new ServiceResult<string> ();var category = await _categoryRepository.FindAsync(x => x.DisplayName.Equals(name));
if (null == category)
{
result.IsFailed(ResponseText.WHAT_NOT_EXIST.FormatWith("Classification", name));
return result;
}
result.IsSuccess(category.CategoryName);
return result;
});
}
Copy the code
ResponseText.WHAT_NOT_EXIST is a constant that is used to query if there is a category for the current name, and if there is an error if there is one, return only the category name and add the API to BlogController.
/// <summary>
///Get category name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[HttpGet]
[Route("category")]
public async Task<ServiceResult<string>> GetCategoryAsync(([Required] string name)
{
return await _blogService.GetCategoryAsync(name);
}
Copy the code
[Required]Attribute Parameter name Mandatory.
The article lists
Searching the list of articles by category name and paging search the list of articles return model is the same, but there is no paging, so it is ok to directly return a list, add by category name query article list and cache interface.
//IBlogService.Post.cs
/// <summary>
///Query the list of articles by category name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByCategoryAsync(string name);
Copy the code
//IBlogCacheService.Post.cs
/// <summary>
///Query the list of articles by category name
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByCategoryAsync(string name, Func<Task<ServiceResult<IEnumerable<QueryPostDto>>>> factory);
Copy the code
Implement the two interfaces separately.
//BlogCacheService.Post.cs.public partial class BlogCacheService
{
private const string KEY_QueryPostsByCategory = "Blog:Post:QueryPostsByCategory-{0}";
/// <summary>
///Query the list of articles by category name
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByCategoryAsync(string name, Func<Task<ServiceResult<IEnumerable<QueryPostDto>>>> factory)
{
return awaitCache.GetOrAddAsync(KEY_QueryPostsByCategory.FormatWith(name), factory, CacheStrategy.ONE_DAY); }}...Copy the code
//BlogService.Post.cs
/// <summary>
///Query the list of articles by category name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByCategoryAsync(string name)
{
return await _blogCacheService.QueryPostsByCategoryAsync(name, async() = > {var result = new ServiceResult<IEnumerable<QueryPostDto>>();
var list = (from posts in await _postRepository.GetListAsync()
join categories in await _categoryRepository.GetListAsync()
on posts.CategoryId equals categories.Id
where categories.DisplayName.Equals(name)
orderby posts.CreationTime descending
select new PostBriefDto
{
Title = posts.Title,
Url = posts.Url,
Year = posts.CreationTime.Year,
CreationTime = posts.CreationTime.TryToDateTime()
})
.GroupBy(x => x.Year)
.Select(x => new QueryPostDto
{
Year = x.Key,
Posts = x.ToList()
});
result.IsSuccess(list);
return result;
});
}
Copy the code
Category. DisplayName==name (CreationTime) category. DisplayName==name (CreationTime) Add an API to BlogController.
/// <summary>
///Query the list of articles by category name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[HttpGet]
[Route("posts/category")]
public async Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByCategoryAsync([Required] string name)
{
return await _blogService.QueryPostsByCategoryAsync(name);
}
Copy the code
Tag name & article list
Analysis: This page, like the category page, contains two interfaces to query the name of the tag and the list of articles under the current tag.
Tag name
Add the get label name interface and the cache interface, GetTagAsync().
//IBlogService.Tag.cs
/// <summary>
///Get label name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
Task<ServiceResult<string>> GetTagAsync(string name);
Copy the code
//IBlogCacheService.Tag.cs
/// <summary>
///Get label name
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
Task<ServiceResult<string>> GetTagAsync(string name, Func<Task<ServiceResult<string>>> factory);
Copy the code
Implement both interfaces.
//BlogCacheService.Tag.cs.public partial class BlogCacheService
{
private const string KEY_GetTag = "Blog:Tag:GetTag-{0}";
/// <summary>
///Get label name
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
public async Task<ServiceResult<string>> GetTagAsync(string name, Func<Task<ServiceResult<string>>> factory)
{
return awaitCache.GetOrAddAsync(KEY_GetTag.FormatWith(name), factory, CacheStrategy.ONE_DAY); }}...Copy the code
//BlogService.Tag.cs
/// <summary>
///Get label name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public async Task<ServiceResult<string>> GetTagAsync(string name)
{
return await _blogCacheService.GetTagAsync(name, async() = > {var result = new ServiceResult<string> ();var tag = await _tagRepository.FindAsync(x => x.DisplayName.Equals(name));
if (null == tag)
{
result.IsFailed(ResponseText.WHAT_NOT_EXIST.FormatWith("Label", name));
return result;
}
result.IsSuccess(tag.TagName);
return result;
});
}
Copy the code
ResponseText.WHAT_NOT_EXIST is a constant that is used to query if there is a category for the current name, and if there is an error if there is one, return only the category name and add the API to BlogController.
/// <summary>
///Get label name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[HttpGet]
[Route("tag")]
public async Task<ServiceResult<string>> GetTagAsync(string name)
{
return await _blogService.GetTagAsync(name);
}
Copy the code
[Required]Attribute Parameter name Mandatory.
The article lists
As above, add the interface to query the list of articles by tag name and the interface to cache.
//IBlogService.Post.cs
/// <summary>
///Query the list of articles by tag name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByTagAsync(string name);
Copy the code
//IBlogCacheService.Post.cs
/// <summary>
///Query the list of articles by tag name
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByTagAsync(string name, Func<Task<ServiceResult<IEnumerable<QueryPostDto>>>> factory);
Copy the code
Implement the two interfaces separately.
//BlogCacheService.Post.cs.public partial class BlogCacheService
{
private const string KEY_QueryPostsByTag = "Blog:Post:QueryPostsByTag-{0}";
/// <summary>
///Query the list of articles by tag name
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByTagAsync(string name, Func<Task<ServiceResult<IEnumerable<QueryPostDto>>>> factory)
{
return awaitCache.GetOrAddAsync(KEY_QueryPostsByTag.FormatWith(name), factory, CacheStrategy.ONE_DAY); }}...Copy the code
//BlogService.Post.cs
/// <summary>
///Query the list of articles by tag name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByTagAsync(string name)
{
return await _blogCacheService.QueryPostsByTagAsync(name, async() = > {var result = new ServiceResult<IEnumerable<QueryPostDto>>();
var list = (from post_tags in await _postTagRepository.GetListAsync()
join tags in await _tagRepository.GetListAsync()
on post_tags.TagId equals tags.Id
join posts in await _postRepository.GetListAsync()
on post_tags.PostId equals posts.Id
where tags.DisplayName.Equals(name)
orderby posts.CreationTime descending
select new PostBriefDto
{
Title = posts.Title,
Url = posts.Url,
Year = posts.CreationTime.Year,
CreationTime = posts.CreationTime.TryToDateTime()
})
.GroupBy(x => x.Year)
.Select(x => new QueryPostDto
{
Year = x.Key,
Posts = x.ToList()
});
result.IsSuccess(list);
return result;
});
}
Copy the code
Query post_tags (tags); query post_tags (tags); query post_tags (tags); query post_tags (tags); Filter out the required fields to return and add the API to the BlogController.
/// <summary>
///Query the list of articles by tag name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[HttpGet]
[Route("posts/tag")]
public async Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByTagAsync(string name)
{
return await _blogService.QueryPostsByTagAsync(name);
}
Copy the code
At this point, basically completed the blog front-end required all the query interface, there are still friends chain query, we can complete their own, if you need any new interface to come back to write.
Open source: github.com/Meowv/Blog/…
It is better to study with the following courses
gk.link/a/10iQ7