基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(二)
基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(二)
转载于:https://github.com/Meowv/Blog
上篇文章完成了两个接口:文章列表页、文章详情页,本篇继续。
分类列表
图片
分析:这里多了一个统计文章数量的字段,可以直接新建一个模型QueryCategoryDto.cs继承CategoryDto。
//QueryCategoryDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{
public class QueryCategoryDto : CategoryDto
{
///
/// 总数
///
public int Count { get; set; }
}
}
添加查询分类列表接口和缓存接口。
//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
{
///
/// 查询分类列表
///
///
Task<ServiceResult<IEnumerable>> QueryCategoriesAsync();
}
}
//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
{
///
/// 查询分类列表
///
///
///
Task<ServiceResult<IEnumerable>> QueryCategoriesAsync(Func<Task<ServiceResult<IEnumerable>>> factory);
}
}
分别实现这两个接口。
//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>/// 查询分类列表/// </summary>/// <param name="factory"></param>/// <returns></returns>public async Task<ServiceResult<IEnumerable<QueryCategoryDto>>> QueryCategoriesAsync(Func<Task<ServiceResult<IEnumerable<QueryCategoryDto>>>> factory){return await Cache.GetOrAddAsync(KEY_QueryCategories, factory, CacheStrategy.ONE_DAY);}
}
}
//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
{
///
/// 查询分类列表
///
///
public async Task<ServiceResult<IEnumerable>> QueryCategoriesAsync()
{
return await _blogCacheService.QueryCategoriesAsync(async () =>
{
var result = new ServiceResult<IEnumerable>();
var list = from category in await _categoryRepository.GetListAsync()join posts in await _postRepository.GetListAsync()on category.Id equals posts.CategoryIdgroup category by new{category.CategoryName,category.DisplayName} into gselect new QueryCategoryDto{CategoryName = g.Key.CategoryName,DisplayName = g.Key.DisplayName,Count = g.Count()};result.IsSuccess(list);return result;});}
}
}
缓存就不说了,查询分类列表,联合查询文章和分类两张表,关联字段为CategoryId,然后分组,计算出对应的数量,在BlogController中添加API。
///
/// 查询分类列表
///
///
[HttpGet]
[Route(“categories”)]
public async Task<ServiceResult<IEnumerable>> QueryCategoriesAsync()
{
return await _blogService.QueryCategoriesAsync();
}
图片
标签列表
图片
分析:和分类列表差不多,新建模型QueryTagDto.cs继承TagDto。
//QueryTagDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{
public class QueryTagDto : TagDto
{
///
/// 总数
///
public int Count { get; set; }
}
}
添加查询标签列表接口和缓存接口。
//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
{
///
/// 查询标签列表
///
///
///
Task<ServiceResult<IEnumerable>> QueryTagsAsync(Func<Task<ServiceResult<IEnumerable>>> factory);
}
}
//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
{
///
/// 查询标签列表
///
///
Task<ServiceResult<IEnumerable>> QueryTagsAsync();
}
}
分别实现这两个接口。
//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>/// 查询标签列表/// </summary>/// <param name="factory"></param>/// <returns></returns>public async Task<ServiceResult<IEnumerable<QueryTagDto>>> QueryTagsAsync(Func<Task<ServiceResult<IEnumerable<QueryTagDto>>>> factory){return await Cache.GetOrAddAsync(KEY_QueryTags, factory, CacheStrategy.ONE_DAY);}
}
}
//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
{
///
/// 查询标签列表
///
///
public async Task<ServiceResult<IEnumerable>> QueryTagsAsync()
{
return await _blogCacheService.QueryTagsAsync(async () =>
{
var result = new ServiceResult<IEnumerable>();
var list = from tags in await _tagRepository.GetListAsync()join post_tags in await _postTagRepository.GetListAsync()on tags.Id equals post_tags.TagIdgroup tags by new{tags.TagName,tags.DisplayName} into gselect new QueryTagDto{TagName = g.Key.TagName,DisplayName = g.Key.DisplayName,Count = g.Count()};result.IsSuccess(list);return result;});}
}
}
查询标签列表需要联合查询tags和post_tags,根据TagId进行关联,然后分组从而获取标签下文章的总数,在BlogController中添加API。
///
/// 查询标签列表
///
///
[HttpGet]
[Route(“tags”)]
public async Task<ServiceResult<IEnumerable>> QueryTagsAsync()
{
return await _blogService.QueryTagsAsync();
}
图片
分类名称&文章列表
图片
分析:此页面下包含两个接口,查询分类的名称和当前分类下的文章列表,和文章列表不同的是,它不带分页。分类包含两个字段,分类名称和展示名称,我们要把真正的名称查询出来展示在页面上。
分类名称
不需要给他添加返回模型,直接返回一个string类型即可,同时给一个查询参数name,添加获取分类名称接口和缓存接口。
//IBlogService.Category.cs
///
/// 获取分类名称
///
///
///
Task<ServiceResult> GetCategoryAsync(string name);
//IBlogCacheService.Category.cs
///
/// 获取分类名称
///
///
///
///
Task<ServiceResult> GetCategoryAsync(string name, Func<Task<ServiceResult>> factory);
实现这两个接口。
//BlogCacheService.Category.cs
…
public partial class BlogCacheService
{
private const string KEY_GetCategory = “Blog:Category:GetCategory-{0}”;
/// <summary>/// 获取分类名称/// </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 await Cache.GetOrAddAsync(KEY_GetCategory.FormatWith(name), factory, CacheStrategy.ONE_DAY);}
}
…
//BlogService.Category.cs
///
/// 获取分类名称
///
///
///
public async Task<ServiceResult> GetCategoryAsync(string name)
{
return await _blogCacheService.GetCategoryAsync(name, async () =>
{
var result = new ServiceResult();
var category = await _categoryRepository.FindAsync(x => x.DisplayName.Equals(name));if (null == category){result.IsFailed(ResponseText.WHAT_NOT_EXIST.FormatWith("分类", name));return result;}result.IsSuccess(category.CategoryName);return result;
});
}
FormatWith()是扩展方法,ResponseText.WHAT_NOT_EXIST是之前说过的常量,直接查询是否存在当前name的分类,如果不存在给出错误提示,存在的话,则只返回分类名称,在BlogController中添加API。
///
/// 获取分类名称
///
///
///
[HttpGet]
[Route(“category”)]
public async Task<ServiceResult> GetCategoryAsync(([Required] string name)
{
return await _blogService.GetCategoryAsync(name);
}
[Required]Attribute 指定参数name必填。
图片
图片
文章列表
通过分类名称查询文章列表和分页查询文章列表返回模型是一样的,只是不用分页,所以直接返回一个列表就可以了,添加通过分类名称查询文章列表和缓存的接口。
//IBlogService.Post.cs
///
/// 通过分类名称查询文章列表
///
///
///
Task<ServiceResult<IEnumerable>> QueryPostsByCategoryAsync(string name);
//IBlogCacheService.Post.cs
///
/// 通过分类名称查询文章列表
///
///
///
///
Task<ServiceResult<IEnumerable>> QueryPostsByCategoryAsync(string name, Func<Task<ServiceResult<IEnumerable>>> factory);
分别实现这两个接口。
//BlogCacheService.Post.cs
…
public partial class BlogCacheService
{
private const string KEY_QueryPostsByCategory = “Blog:Post:QueryPostsByCategory-{0}”;
/// <summary>/// 通过分类名称查询文章列表/// </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 await Cache.GetOrAddAsync(KEY_QueryPostsByCategory.FormatWith(name), factory, CacheStrategy.ONE_DAY);}
}
…
//BlogService.Post.cs
///
/// 通过分类名称查询文章列表
///
///
///
public async Task<ServiceResult<IEnumerable>> QueryPostsByCategoryAsync(string name)
{
return await _blogCacheService.QueryPostsByCategoryAsync(name, async () =>
{
var result = new ServiceResult<IEnumerable>();
var list = (from posts in await _postRepository.GetListAsync()join categories in await _categoryRepository.GetListAsync()on posts.CategoryId equals categories.Idwhere categories.DisplayName.Equals(name)orderby posts.CreationTime descendingselect 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;
});
}
这个逻辑和分页查询文章列表是差不多的,联合查询文章表和分类表,关联字段为CategoryId,指定查询条件categories.DisplayName==name,以CreationTime倒序排序,年份分组,筛选出所需字段返回,在BlogController中添加API。
///
/// 通过分类名称查询文章列表
///
///
///
[HttpGet]
[Route(“posts/category”)]
public async Task<ServiceResult<IEnumerable>> QueryPostsByCategoryAsync([Required] string name)
{
return await _blogService.QueryPostsByCategoryAsync(name);
}
图片
标签名称&文章列表
图片
分析:此页面和分类页一样,包含两个接口,查询标签的名称和当前标签下的文章列表。
标签名称
添加获取标签名称接口和缓存接口,GetTagAsync()。
//IBlogService.Tag.cs
///
/// 获取标签名称
///
///
///
Task<ServiceResult> GetTagAsync(string name);
//IBlogCacheService.Tag.cs
///
/// 获取标签名称
///
///
///
///
Task<ServiceResult> GetTagAsync(string name, Func<Task<ServiceResult>> factory);
实现这两个接口。
//BlogCacheService.Tag.cs
…
public partial class BlogCacheService
{
private const string KEY_GetTag = “Blog:Tag:GetTag-{0}”;
/// <summary>/// 获取标签名称/// </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 await Cache.GetOrAddAsync(KEY_GetTag.FormatWith(name), factory, CacheStrategy.ONE_DAY);}
}
…
//BlogService.Tag.cs
///
/// 获取标签名称
///
///
///
public async Task<ServiceResult> GetTagAsync(string name)
{
return await _blogCacheService.GetTagAsync(name, async () =>
{
var result = new ServiceResult();
var tag = await _tagRepository.FindAsync(x => x.DisplayName.Equals(name));if (null == tag){result.IsFailed(ResponseText.WHAT_NOT_EXIST.FormatWith("标签", name));return result;}result.IsSuccess(tag.TagName);return result;
});
}
FormatWith()是扩展方法,ResponseText.WHAT_NOT_EXIST是之前说过的常量,直接查询是否存在当前name的分类,如果不存在给出错误提示,存在的话,则只返回分类名称,在BlogController中添加API。
///
/// 获取标签名称
///
///
///
[HttpGet]
[Route(“tag”)]
public async Task<ServiceResult> GetTagAsync(string name)
{
return await _blogService.GetTagAsync(name);
}
[Required]Attribute 指定参数name必填。
图片
图片
文章列表
和上面一模一样的,添加通过标签名称查询文章列表接口和缓存接口。
//IBlogService.Post.cs
///
/// 通过标签名称查询文章列表
///
///
///
Task<ServiceResult<IEnumerable>> QueryPostsByTagAsync(string name);
//IBlogCacheService.Post.cs
///
/// 通过标签名称查询文章列表
///
///
///
///
Task<ServiceResult<IEnumerable>> QueryPostsByTagAsync(string name, Func<Task<ServiceResult<IEnumerable>>> factory);
分别实现这两个接口。
//BlogCacheService.Post.cs
…
public partial class BlogCacheService
{
private const string KEY_QueryPostsByTag = “Blog:Post:QueryPostsByTag-{0}”;
/// <summary>/// 通过标签名称查询文章列表/// </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 await Cache.GetOrAddAsync(KEY_QueryPostsByTag.FormatWith(name), factory, CacheStrategy.ONE_DAY);}
}
…
//BlogService.Post.cs
///
/// 通过标签名称查询文章列表
///
///
///
public async Task<ServiceResult<IEnumerable>> QueryPostsByTagAsync(string name)
{
return await _blogCacheService.QueryPostsByTagAsync(name, async () =>
{
var result = new ServiceResult<IEnumerable>();
var list = (from post_tags in await _postTagRepository.GetListAsync()join tags in await _tagRepository.GetListAsync()on post_tags.TagId equals tags.Idjoin posts in await _postRepository.GetListAsync()on post_tags.PostId equals posts.Idwhere tags.DisplayName.Equals(name)orderby posts.CreationTime descendingselect 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;
});
}
这个查询有点特殊,联合查询了3张表,先查post_tags和tags,关联字段TagId,再根据PostId查询posts,指定查询条件tags.DisplayName==name,以CreationTime倒序排序,年份分组,筛选出所需字段返回,在BlogController中添加API。
///
/// 通过标签名称查询文章列表
///
///
///
[HttpGet]
[Route(“posts/tag”)]
public async Task<ServiceResult<IEnumerable>> QueryPostsByTagAsync(string name)
{
return await _blogService.QueryPostsByTagAsync(name);
}
图片
至此,基本上完成了博客前端所需的所有查询接口,就还剩下友链的查询,大家可以自己完成,后面如果需要什么新的接口再回头来写就好了。
开源地址:https://github.com/Meowv/Blog/tree/blog_tutorial
基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(二)相关推荐
- 基于 abp vNext 和 .NET Core 开发博客项目 - 终结篇之发布项目
基于 abp vNext 和 .NET Core 开发博客项目 - 终结篇之发布项目 转载于:https://github.com/Meowv/Blog 既然开发完成了,还是拿出来溜溜比较好,本篇是本 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(九)
基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(九) 转载于:https://github.com/Meowv/Blog 终于要接近尾声了,上一篇基本上将文 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(八)
基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(八) 转载于:https://github.com/Meowv/Blog 上一篇完成了标签模块和友情链接模块 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(七)
基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(七) 转载于:https://github.com/Meowv/Blog 上一篇完成了后台分类模块的所有功能 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(六)
基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(六) 转载于:https://github.com/Meowv/Blog 上一篇完成了博客文章详情页面的数据 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(五)
基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(五) 转载于:https://github.com/Meowv/Blog 上一篇完成了分类标签友链的列表查询 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(四)
基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(四) 转载于:https://github.com/Meowv/Blog 上一篇完成了博客的分页查询文章列表 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(三)
基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(三) 转载于:https://github.com/Meowv/Blog 上一篇完成了博客的主题切换,菜单和 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(二)
基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(二) 转载于:https://github.com/Meowv/Blog 上一篇搭建了 Blazor 项目并 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(五)
基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(五) 转载于:https://github.com/Meowv/Blog 上篇文章完成了文章详情页数据查询和清除缓存 ...
最新文章
- LeetCode简单题之查找共用字符
- java csv格式文件写入_java csv文件写入
- struts2 s标签
- JavaFX FXML场景编辑器使用示例
- reactnative 获取定位_【React Native】定位获取经纬度,当前城市等地址信息
- server.MapPath的相对路径问题
- 人人商城小程序服务器根目录,微擎通用-人人商城v3小程序安装步骤小程序配置说明...
- XP 远程连接window 2008 网络级别身份验证问题解决方法
- VS2015+OpenCV3.4.0+dmtx最新版联合集成开发 解析dm码
- 2018WPS暑期实习生web前端笔试题
- 嵌入式系统开发笔记19:CJ/T-188 冷热量表协议解析8
- 机器学习作业-FOGS: 基于学习图的一阶梯度监督交通流预测
- C# MethodInvoker委托的使用
- 中国LED芯片行业市场竞争状况分析及十si五发展趋势研究报告2021~2027年
- 用C语言写基于单片机的定时闹钟,基于单片机定时闹钟设计.doc
- 卓有成效的管理者读后感
- android多线程下载3
- 全国仅三家!小红书平台授权卓尔数科核心代理商牌照
- C语言 一维数组叠加为二维数组样例
- glc四驱软件测试,北京奔驰GLC减配严重,四驱性能极差,官方是这么解释的
热门文章
- 艾媒咨询:泛娱乐「体验共享」报告发布,网易云信多个案例领衔
- 网易技术干货 | 云信移动端音视频UI自动化测试实践
- 数据结构_串_mindmap+LeetCode_344.反转字符串(Java、C)
- 2018年10月Top 10 Python开源项目
- 前端每日实战:116# 视频演示如何用 CSS 和原生 JS 开发一个监控网络连接状态的页面...
- 理解UIView的绘制
- react-native填坑--react-navigation
- 为终端服务连接配置网络级身份验证
- 你不得不知道的Visual Studio 2012(3)- 创建Windows应用程序
- [转载]迅速成长的两个重要途径