欢迎访问 生活随笔!

凯发ag旗舰厅登录网址下载

当前位置: 凯发ag旗舰厅登录网址下载 > 编程语言 > >内容正文

asp.net

基于 abp vnext 和 .net core 开发博客项目 -凯发ag旗舰厅登录网址下载

发布时间:2025/1/21 16 豆豆
凯发ag旗舰厅登录网址下载 收集整理的这篇文章主要介绍了 基于 abp vnext 和 .net core 开发博客项目 - 博客接口实战篇(三) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

基于 abp vnext 和 .net core 开发博客项目 - 博客接口实战篇(三)

转载于:https://github.com/meowv/blog

上篇文章完成了分类和标签页面相关的共6个接口,本篇继续来写博客增删改查api的业务。

供前端查询用的接口还剩下一个,这里先补上。

友链列表

图片

分析:返回标题和对应的链接即可,传输对象friendlinkdto.cs。

//friendlinkdto.cs
namespace meowv.blog.application.contracts.blog
{
public class friendlinkdto
{
///
/// 标题
///
public string title { get; set; }

/// /// 链接/// public string linkurl { get; set; } }

}
添加查询友链列表接口和缓存接口。

//iblogservice.friendlink.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> queryfriendlinksasync();
}
}
//iblogcacheservice.friendlink.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> queryfriendlinksasync(func>> factory);
}
}
接下来,实现他们。

//blogcacheservice.friendlink.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_queryfriendlinks = “blog:friendlink:queryfriendlinks”;

/// /// 查询友链列表/// /// /// public async task>> queryfriendlinksasync(func>>> factory){return await cache.getoraddasync(key_queryfriendlinks, factory, cachestrategy.one_day);} }

}
//blogservice.friendlink.cs
using meowv.blog.application.contracts.blog;
using meowv.blog.domain.blog;
using meowv.blog.toolkits.base;
using system.collections.generic;
using system.threading.tasks;

namespace meowv.blog.application.blog.impl
{
public partial class blogservice
{
///
/// 查询友链列表
///
///
public async task> queryfriendlinksasync()
{
return await _blogcacheservice.queryfriendlinksasync(async () =>
{
var result = new serviceresult();

var friendlinks = await _friendlinksrepository.getlistasync();var list = objectmapper.map, ienumerable>(friendlinks);result.issuccess(list);return result;});} }

}
直接查询所有的友链数据,这里使用前面讲到的automapper处理对象映射,将ienumerable转换为ienumerable。

在meowvblogautomapperprofile.cs中添加一条配置:createmap();,在blogcontroller中添加api。

///
/// 查询友链列表
///
///
[httpget]
[route(“friendlinks”)]
public async task> queryfriendlinksasync()
{
return await _blogservice.queryfriendlinksasync();
}
编译运行,打开查询友链的api,此时没数据,手动添加几条数据进去再试试吧。

图片

文章管理

图片

后台文章管理包含:文章列表、新增、更新、删除文章,接下来依次完成这些接口。

文章列表

这里的文章列表和前台的文章列表差不多,就是多了一个id,以供编辑和删除使用,所以可以新建一个模型类querypostforadmindto继承querypostdto,添加postbriefforadmindto继承postbriefdto同时新增一个字段主键id。

在querypostforadmindto中隐藏基类成员posts,使用新的接收类型:ienumerable。

//postbriefforadmindto.cs
namespace meowv.blog.application.contracts.blog
{
public class postbriefforadmindto : postbriefdto
{
///
/// 主键
///
public int id { get; set; }
}
}

//querypostforadmindto.cs
using system.collections.generic;

namespace meowv.blog.application.contracts.blog
{
public class querypostforadmindto : querypostdto
{
///
/// posts
///
public new ienumerable posts { get; set; }
}
}
添加分页查询文章列表的接口:querypostsforadminasync(),关于后台的一些接口就不添加缓存了。

//iblogservice.admin.cs
using meowv.blog.application.contracts;
using meowv.blog.application.contracts.blog;
using meowv.blog.toolkits.base;
using system.threading.tasks;

namespace meowv.blog.application.blog
{
public partial interface iblogservice
{
///
/// 分页查询文章列表
///
///
///
task> querypostsforadminasync(paginginput input);
}
}
然后实现这个接口。

//blogservice.admin.cs
using meowv.blog.application.contracts;
using meowv.blog.application.contracts.blog;
using meowv.blog.toolkits.base;
using meowv.blog.toolkits.extensions;
using system.linq;
using system.threading.tasks;

namespace meowv.blog.application.blog.impl
{
public partial class blogservice
{
///
/// 分页查询文章列表
///
///
///
public async task> querypostsforadminasync(paginginput input)
{
var result = new serviceresult();

var count = await _postrepository.getcountasync();var list = _postrepository.orderbydescending(x => x.creationtime).pagebyindex(input.page, input.limit).select(x => new postbriefforadmindto{id = x.id,title = x.title,url = x.url,year = x.creationtime.year,creationtime = x.creationtime.trytodatetime()}).groupby(x => x.year).select(x => new querypostforadmindto{year = x.key,posts = x.tolist()}).tolist();result.issuccess(new pagedlist(count.trytoint(), list));return result;} }

}
实现逻辑也非常简单和之前一样,就是在select的时候多了一个id,添加一个新的controller:blogcontroller.admin.cs,添加这个接口。

//blogcontroller.admin.cs
using meowv.blog.application.contracts;
using meowv.blog.application.contracts.blog;
using meowv.blog.toolkits.base;
using microsoft.aspnetcore.authorization;
using microsoft.aspnetcore.mvc;
using system.threading.tasks;
using static meowv.blog.domain.shared.meowvblogconsts;

namespace meowv.blog.httpapi.controllers
{
public partial class blogcontroller
{
///
/// 分页查询文章列表
///
///
///
[httpget]
[authorize]
[route(“admin/posts”)]
[apiexplorersettings(groupname = grouping.groupname_v2)]
public async task> querypostsforadminasync([fromquery] paginginput input)
{
return await _blogservice.querypostsforadminasync(input);
}
}
}
因为是后台的接口,所以加上authorizeattribute,指定接口组为groupname_v2,参数方式为[fromquery]。

当没有进行授权的时候,是无法访问接口的。

图片

新增文章

图片

在做新增文章的时候要注意几点,不是单纯的添加文章数据就结束了,要指定文章分类,添加文章的标签。添加标签我这里是从标签库中去取得数据,只存标签id,所以添加标签的时候就可能存在添加了标签库中已有的标签。

新建一个新增和更新文章的通用输出参数模型类,起名:editpostinput,继承postdto,然后添加标签tags字段,返回类型ienumerable。

//editpostinput.cs
using system.collections.generic;

namespace meowv.blog.application.contracts.blog.params
{
public class editpostinput : postdto
{
///
/// 标签列表
///
public ienumerable tags { get; set; }
}
}
添加新增文章的接口:insertpostasync。

///
/// 新增文章
///
///
///
task insertpostasync(editpostinput input);
然后去实现这个接口,实现之前,配置automapper实体映射。

createmap().formember(x => x.id, opt => opt.ignore());
将editpostinput转换为post,并且忽略id字段。

///
/// 新增文章
///
///
///
public async task insertpostasync(editpostinput input)
{
var result = new serviceresult();

var post = objectmapper.map(input); post.url = $"{post.creationtime.tostring(" yyyy mm dd ").replace(" ", "/")}{post.url}/"; await _postrepository.insertasync(post);var tags = await _tagrepository.getlistasync();var newtags = input.tags.where(item => !tags.any(x => x.tagname.equals(item))).select(item => new tag{tagname = item,displayname = item}); await _tagrepository.bulkinsertasync(newtags);var posttags = input.tags.select(item => new posttag {postid = post.id,tagid = _tagrepository.firstordefault(x => x.tagname == item).id }); await _posttagrepository.bulkinsertasync(posttags);result.issuccess(responsetext.insert_success); return result;

}
url字段,根据创建时间按照yyyy/mm/dd/name/格式拼接。

然后找出是否有新标签,有的话批量添加至标签表。

再根据input.tags构建posttag列表,也进行批量保存,这样才算是新增好一篇文章,最后输出responsetext.insert_success常量,提示成功。

在blogcontroller.admin.cs添加api。

///
/// 新增文章
///
///
///
[httppost]
[authorize]
[route(“post”)]
[apiexplorersettings(groupname = grouping.groupname_v2)]
public async task insertpostasync([frombody] editpostinput input)
{
return await _blogservice.insertpostasync(input);
}

图片

更新文章

更新操作和新增操作输入参数一样,只新增一个id用来标识更新那篇文章,添加updatepostasync更新文章接口。

///
/// 更新文章
///
///
///
///
task updatepostasync(int id, editpostinput input);
同样的实现这个接口。

///
/// 更新文章
///
///
///
///
public async task updatepostasync(int id, editpostinput input)
{
var result = new serviceresult();

var post = await _postrepository.getasync(id); post.title = input.title; post.author = input.author; post.url = $"{input.creationtime.tostring(" yyyy mm dd ").replace(" ", "/")}{input.url}/"; post.html = input.html; post.markdown = input.markdown; post.creationtime = input.creationtime; post.categoryid = input.categoryid;await _postrepository.updateasync(post);var tags = await _tagrepository.getlistasync();var oldposttags = from post_tags in await _posttagrepository.getlistasync()join tag in await _tagrepository.getlistasync()on post_tags.tagid equals tag.idwhere post_tags.postid.equals(post.id)select new{post_tags.id,tag.tagname};var removedids = oldposttags.where(item => !input.tags.any(x => x == item.tagname) &&tags.any(t => t.tagname == item.tagname)).select(item => item.id); await _posttagrepository.deleteasync(x => removedids.contains(x.id));var newtags = input.tags.where(item => !tags.any(x => x.tagname == item)).select(item => new tag{tagname = item,displayname = item}); await _tagrepository.bulkinsertasync(newtags);var posttags = input.tags.where(item => !oldposttags.any(x => x.tagname == item)).select(item => new posttag{postid = id,tagid = _tagrepository.firstordefault(x => x.tagname == item).id}); await _posttagrepository.bulkinsertasync(posttags);result.issuccess(responsetext.update_success); return result;

}
responsetext.update_success是常量更新成功。

先根据id查询到数据库中的这篇文章数据,然后根据input参数,修改需要修改的数据,最后保存。

注意的是,如果修改的时候修改了标签,有可能新增也有可能删除,也许会又有新增又有删除。

这时候就需要注意,这里做了一个比较通用的方法,找到数据库中当前文章id的所有tags,然后根据参数input.tags可以找出被删掉的标签的posttags的id,调用删除方法删掉即可,同时也可以获取到新增的标签,批量进行保存。

完成上面操作后,才保存新加标签与文章对应的数据,最后提示更新成功,在blogcontroller.admin添加api。

///
/// 更新文章
///
///
///
///
[httpput]
[authorize]
[route(“post”)]
[apiexplorersettings(groupname = grouping.groupname_v2)]
public async task updatepostasync([required] int id, [frombody] editpostinput input)
{
return await _blogservice.updatepostasync(id, input);
}
[httpput]指定请求方式为put请求,一般需要修改用put,添加用post。

[required]指定参数id必填且是fromquery的方式,input为[frombody]。

更新一下上面新增的数据试试。

图片

图片

删除文章

删除相对来说就非常简单了,一般删除都会做逻辑删除,就是避免某些手残删除了,有找回的余地,我们这里就直接delete了,也没什么重要数据。

添加接口:deletepostasync。

///
/// 删除文章
///
///
///
task deletepostasync(int id);
实现接口。

///
/// 删除文章
///
///
///
public async task deletepostasync(int id)
{
var result = new serviceresult();

var post = await _postrepository.getasync(id); if (null == post) {result.isfailed(responsetext.what_not_exist.formatwith("id", id));return result; }await _postrepository.deleteasync(id); await _posttagrepository.deleteasync(x => x.postid == id);result.issuccess(responsetext.delete_success); return result;

}
删除的时候同样去查询一下数据,来判断是否存在。

responsetext.delete_success是添加的常量删除成功,删除成功同时也要将post_tags表的标签对应关系也干掉才算完整,在blogcontroller.admin添加api。

///
/// 删除文章
///
///
///
[httpdelete]
[authorize]
[route(“post”)]
[apiexplorersettings(groupname = grouping.groupname_v2)]
public async task deletepostasync([required] int id)
{
return await _blogservice.deletepostasync(id);
}
[httpdelete]指定请求方式是删除资源,[required]指定参数id必填。

删掉上面添加的文章看看效果。

图片

至此,完成了博客文章的增删改接口,未完待续…

开源地址:https://github.com/meowv/blog/tree/blog_tutorial

总结

以上是凯发ag旗舰厅登录网址下载为你收集整理的基于 abp vnext 和 .net core 开发博客项目 - 博客接口实战篇(三)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得凯发ag旗舰厅登录网址下载网站内容还不错,欢迎将凯发ag旗舰厅登录网址下载推荐给好友。

网站地图