基于.NetCore开发博客项目 StarBlog - (28) 开发友情链接相关接口

这篇具有很好参考价值的文章主要介绍了基于.NetCore开发博客项目 StarBlog - (28) 开发友情链接相关接口。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

之前介绍的友情链接功能,只实现了友情链接的展示和管理接口。

还缺失友情链接申请、审核管理、通知,现在把这块功能补全。

Model 什么的之前那篇文章都有,本文直接补全逻辑代码~

详见: 基于.NetCore开发博客项目 StarBlog - (13) 加入友情链接功能

先看效果

友情链接申请页面

基于.NetCore开发博客项目 StarBlog - (28) 开发友情链接相关接口

邮件通知

实现一个简单的通知功能,申请通过之后,给申请友链的邮箱发通知。

使用 MimeKit 这个库可以很方便的实现发邮件功能

为了更方便使用,我封装了一个 EmailUtils 放在 StarBlog.Share.Utils 里面

public class EmailAccountConfig {
  public string Host { get; set; }
  public int Port { get; set; }
  public string FromUsername { get; set; }
  public string FromPassword { get; set; }
  public string FromAddress { get; set; }
}

public static class EmailUtils {
  public static async Task<MessageSentEventArgs> SendEmailAsync(
    EmailAccountConfig config,
    string subject,
    string htmlBody,
    string toName,
    string toAddress,
    string fromName = "StarBlog"
  ) {
    return await SendEmailAsync(
      config,
      new MimeMessage {
        Subject = subject,
        From = {new MailboxAddress(fromName, config.FromAddress)},
        To = {new MailboxAddress(toName, toAddress)},
        Body = new BodyBuilder {
          HtmlBody = htmlBody
        }.ToMessageBody()
      }
    );
  }

  public static async Task<MessageSentEventArgs> SendEmailAsync(EmailAccountConfig config, MimeMessage message,
                                                                HttpProxyClient? proxyClient = null) {
    MessageSentEventArgs result = null;
    using var client = new SmtpClient {
      ServerCertificateValidationCallback = (s, c, h, e) => true,
    };
    if (proxyClient != null) {
      client.ProxyClient = proxyClient;
    }

    client.AuthenticationMechanisms.Remove("XOAUTH2");
    client.MessageSent += (sender, args) => { result = args; };

    await client.ConnectAsync(config.Host, config.Port, SecureSocketOptions.Auto);
    await client.AuthenticateAsync(config.FromUsername, config.FromPassword);
    await client.SendAsync(message);
    await client.DisconnectAsync(true);

    return result;
  }
}

使用比较简单,传入邮箱配置和邮件主题、内容、收件地址就行。

具体的可以接着看下面的代码。

友链申请管理

管理友情链接申请记录的逻辑,同样也是有增删改查,这部分代码跟上面的一样,省略了

构造方法通过依赖注入,从配置系统里读取了邮箱配置,读者可以自行将邮箱配置添加到 appsettings.json 中,这里给出一个outlook邮箱的配置

"EmailAccountConfig": {
  "Host": "smtp-mail.outlook.com",
  "Port": 587,
  "FromUsername": "邮箱地址@outlook.com",
  "FromPassword": "邮箱密码",
  "FromAddress": "邮箱地址@outlook.com"
}

下面开始是 service 的代码

这里只贴设置是否验证发邮件通知 的代码

public class LinkExchangeService {
  private readonly IBaseRepository<LinkExchange> _repo;
  private readonly LinkService _linkService;
  private readonly EmailAccountConfig _emailAccountConfig;

  public LinkExchangeService(IBaseRepository<LinkExchange> repo, LinkService linkService, IOptions<EmailAccountConfig> options) {
    _repo = repo;
    _linkService = linkService;
    _emailAccountConfig = options.Value;
  }

  public async Task<LinkExchange?> SetVerifyStatus(int id, bool status, string? reason = null) {
    var item = await GetById(id);
    if (item == null) return null;

    item.Verified = status;
    item.Reason = reason;
    await _repo.UpdateAsync(item);


    var link = await _linkService.GetByName(item.Name);
    if (status) {
      await SendEmailOnAccept(item);
      if (link == null) {
        await _linkService.AddOrUpdate(new Link {
          Name = item.Name,
          Description = item.Description,
          Url = item.Url,
          Visible = true
        });
      }
      else {
        await _linkService.SetVisibility(link.Id, true);
      }
    }
    else {
      await SendEmailOnReject(item);
      if (link != null) await _linkService.DeleteById(link.Id);
    }

    return await GetById(id);
  }

  // 本文仅贴上申请通过的代码,其他的也是类似的写法
  public async Task SendEmailOnAccept(LinkExchange item) {
    const string starblogLink = "<a href=\"https://deali.cn\">StarBlog</a>";
    var sb = new StringBuilder();
    sb.AppendLine($"<p>您好,友链申请已通过!感谢支持,欢迎互访哦~</p>");
    sb.AppendLine($"<br>");
    sb.AppendLine($"<p>以下是您申请的友链信息:</p>");
    sb.AppendLine($"<p>网站名称:{item.Name}</p>");
    sb.AppendLine($"<p>介绍:{item.Description}</p>");
    sb.AppendLine($"<p>网址:{item.Url}</p>");
    sb.AppendLine($"<p>站长:{item.WebMaster}</p>");
    sb.AppendLine($"<p>补充信息:{item.Reason}</p>");
    sb.AppendLine($"<br>");
    sb.AppendLine($"<br>");
    sb.AppendLine($"<br>");
    sb.AppendLine($"<p>本消息由 {starblogLink} 自动发送,无需回复。</p>");
    await EmailUtils.SendEmailAsync(
      _emailAccountConfig,
      "[StarBlog]友链申请结果反馈",
      sb.ToString(),
      item.WebMaster,
      item.Email
    );
  }
}

在设置是否验证的方法中,实现了:

  • 设置一个申请为已验证,自动将该申请的链接添加到友情链接中
  • 设置一个申请为未验证,则自动将对应的友情链接删除(如果存在的话)

其他地方就跟上面的友情链接一样了。

写完之后别忘了注册服务

builder.Services.AddScoped<LinkExchangeService>();
builder.Services.AddScoped<LinkService>();

友链申请

展示功能做完了,还得接着做友链申请的功能,以方便路过的站长申请互换友链~

添加 StarBlog.Web/ViewModels/LinkExchange/LinkExchangeAddViewModel.cs 文件

我们使用 AspNetCore MVC 框架提供的表单验证功能

public class LinkExchangeAddViewModel {
  /// <summary>
  /// 网站名称
  /// </summary>
  [Display(Name = "网站名称")]
  [Required(ErrorMessage = "必须填写网站名称")]
  public string Name { get; set; }

  /// <summary>
  /// 介绍
  /// </summary>
  [Display(Name = "介绍")]
  public string? Description { get; set; }

  /// <summary>
  /// 网址
  /// </summary>
  [Display(Name = "网址")]
  [Required(ErrorMessage = "必须填写网址")]
  [DataType(DataType.Url)]
  public string Url { get; set; }

  /// <summary>
  /// 站长
  /// </summary>
  [Display(Name = "站长名称")]
  [Required(ErrorMessage = "必须填写站长名称")]
  public string WebMaster { get; set; }

  /// <summary>
  /// 联系邮箱
  /// </summary>
  [Display(Name = "联系邮箱")]
  [Required(ErrorMessage = "必须填写联系邮箱")]
  [DataType(DataType.EmailAddress)]
  public string Email { get; set; }
}

接着写一下页面 StarBlog.Web/Views/LinkExchange/Add.cshtml

@model StarBlog.Web.ViewModels.LinkExchange.LinkExchangeAddViewModel
@{
ViewData["Title"] = "申请友链";
}


<div class="container px-4 py-3">
  <h2 class="d-flex w-100 justify-content-between pb-2 mb-3 border-bottom">
    <div>申请友链</div>
    <div>Link Exchange</div>
  </h2>

  <div class="card px-1 py-3">
    <form enctype="multipart/form-data" class="card-body row" asp-controller="LinkExchange" asp-action="Add" method="post">
      <div class="col-xl-6">
        <div class="mb-4">
          <h4 class="card-title">友链信息</h4>
          <h6 class="card-subtitle mb-3 text-muted">请输入您的网站信息,方便后续联系</h6>
        </div>

        <div class="mb-3">
          <label asp-for="Name" class="form-label"></label>
          <input asp-for="Name" class="form-control">
          <span asp-validation-for="Name" class="form-text text-danger"></span>
        </div>
        <div class="mb-3">
          <label asp-for="Description" class="form-label"></label>
          <input asp-for="Description" class="form-control">
          <span asp-validation-for="Description" class="form-text text-danger"></span>
        </div>
        <div class="mb-3">
          <label asp-for="Url" class="form-label"></label>
          <input asp-for="Url" class="form-control">
          <span asp-validation-for="Url" class="form-text text-danger"></span>
        </div>
        <div class="mb-3">
          <label asp-for="WebMaster" class="form-label"></label>
          <input asp-for="WebMaster" class="form-control">
          <span asp-validation-for="WebMaster" class="form-text text-danger"></span>
        </div>
        <div class="mb-3">
          <label asp-for="Email" class="form-label"></label>
          <input asp-for="Email" class="form-control">
          <span asp-validation-for="Email" class="form-text text-danger"></span>
        </div>
      </div>

      <div class="col-xl-6">
        <div class="ms-3 mb-4">
          <h4 class="card-title">注意事项</h4>
          <h6 class="card-subtitle mb-3 text-muted">申请友情链接需符合以下几点要求</h6>
        </div>

        <ul class="list-group list-group-flush list-group-numbered">
          <li class="list-group-item d-flex justify-content-between align-items-start">
            <div class="ms-2 me-auto">
              <div class="fw-bold">相互性</div>
              请先在您的网站添加本站链接,再进行友链申请
            </div>
          </li>
          <li class="list-group-item d-flex justify-content-between align-items-start">
            <div class="ms-2 me-auto">
              <div class="fw-bold">内容类别</div>
              本站优先招同类原创、内容相近的博客或网站
            </div>
          </li>
          <li class="list-group-item d-flex justify-content-between align-items-start">
            <div class="ms-2 me-auto">
              <div class="fw-bold">SEO</div>
              Baidu和Google有正常收录,有近期快照的网站优先
            </div>
          </li>
          <li class="list-group-item d-flex justify-content-between align-items-start">
            <div class="ms-2 me-auto">
              <div class="fw-bold">合法性</div>
              不含有违反相关国家法律内容的合法网站,不接受TB客等垃圾站的链接
            </div>
          </li>
          <li class="list-group-item d-flex justify-content-between align-items-start">
            <div class="ms-2 me-auto">
              <div class="fw-bold">更新及时性</div>
              不接受原创内容很少,且长期不更新的网站
            </div>
          </li>
          <li class="list-group-item d-flex justify-content-between align-items-start">
            <div class="ms-2 me-auto">
              <div class="fw-bold">可访问性</div>
              如您的网站无法访问,将会暂时撤销友情链接,如需恢复请联系站长处理
            </div>
          </li>
        </ul>
      </div>

      <div class="form-group">
        <button type="submit" class="btn btn-outline-primary">提交</button>
        <button type="reset" class="btn btn-outline-warning">重置</button>
      </div>
    </form>
  </div>
</div>

最后是Controller,添加 StarBlog.Web/Controllers/LinkExchangeController.cs 文件

代码如下

public class LinkExchangeController : Controller {
  private readonly ILogger<LinkExchangeController> _logger;
  private readonly LinkExchangeService _service;
  private readonly IMapper _mapper;
  private readonly Messages _messages;

  public LinkExchangeController(
    ILogger<LinkExchangeController> logger, LinkExchangeService service, IMapper mapper,
    Messages messages) {
    _logger = logger;
    _service = service;
    _mapper = mapper;
    _messages = messages;
  }

  [HttpGet]
  public IActionResult Add() {
    return View();
  }

  [HttpPost]
  public async Task<IActionResult> Add(LinkExchangeAddViewModel vm) {
    if (!ModelState.IsValid) return View();

    if (await _service.HasUrl(vm.Url)) {
      _messages.Error("相同网址的友链申请已提交!");
      return View();
    }

    var item = _mapper.Map<LinkExchange>(vm);
    item = await _service.AddOrUpdate(item);

    // 发送邮件通知
    await _service.SendEmailOnAdd(item);

    _messages.Info("友链申请已提交,正在处理中,请及时关注邮件通知~");
    return RedirectToAction("Index", "Home");
  }
}

搞定~

一切就绪

欢迎各位站长大佬来交换友链~!文章来源地址https://www.toymoban.com/news/detail-464358.html

到了这里,关于基于.NetCore开发博客项目 StarBlog - (28) 开发友情链接相关接口的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python Flask框架-开发简单博客-项目布局、应用设置

    作者:Eason_LYC 悲观者预言失败,十言九中。 乐观者创造奇迹,一次即可。 一个人的价值,只在于他所拥有的。所以可以不学无术,但不能一无所有! 技术领域:WEB安全、网络攻防 关注WEB安全、网络攻防。我的专栏文章知识点全面细致,逻辑清晰、结合实战,让你在学习路

    2024年02月02日
    浏览(47)
  • 基于 Spring Boot 博客系统开发(三)

    本系统是简易的个人博客系统开发,为了更加熟练地掌握 SprIng Boot 框架及相关技术的使用。🌿🌿🌿 基于 Spring Boot 博客系统开发(二)👈👈 在Thymeleaf中,如果你想要抽取公共页面(例如,头部、底部、导航栏等),可以通过定义和使用片段(fragments)和包含(includes)来

    2024年04月28日
    浏览(37)
  • 基于NodeJs+Express+MySQL 实现的个人博客完整项目

    目录 一、创建项目并初始化 项目结构 二、安装项目所需要的包 三、创建所需要的数据库表 表 user 用于存放账户密码 表 notepad 用于存放文章数据 表 leaving 用于存放留言板的数据 三、编写app.js文件 1、导入所有需要的包 2、创建web服务器 3、创建db文件夹,在文件夹里面创建

    2024年02月08日
    浏览(52)
  • 【Node.js】一文带你开发博客项目之接口(处理请求、搭建开发环境、开发路由)

    个人简介 👀 个人主页: 前端杂货铺 🙋‍♂️ 学习方向: 主攻前端方向,也会涉及到服务端 📃 个人状态: 在校大学生一枚,已拿 offer(秋招) 🥇 推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2Vue3项目实战 🥝Node.js 内容 参考链接 Node.js(一) 初识 Node.js DNS 解析,建

    2023年04月21日
    浏览(55)
  • 基于SqlSugar的开发框架循序渐进介绍(28)-- 快速构建系统参数管理界面

    在参照一些行业系统软件的时候,发现一个做的挺不错的系统功能-系统参数管理,相当于把任何一个基础的系统参数碎片化进行管理,每次可以读取一个值进行管理,这样有利于我们快速的处理业务需求,是一个挺好的功能。本篇随笔模拟这个功能,基于SqlSugar开发框架的基

    2023年04月23日
    浏览(46)
  • 【Node.js实战】一文带你开发博客项目之Express重构(博客的增删查改、morgan写日志)

    个人简介 👀 个人主页: 前端杂货铺 🙋‍♂️ 学习方向: 主攻前端方向,也会涉及到服务端 📃 个人状态: 在校大学生一枚,已拿多个前端 offer(秋招) 🚀 未来打算: 为中国的工业软件事业效力n年 🥇 推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2Vue3项目实战 🥝

    2024年02月06日
    浏览(66)
  • 【Node.js实战】一文带你开发博客项目之登录(前置知识)

    个人简介 👀 个人主页: 前端杂货铺 🙋‍♂️ 学习方向: 主攻前端方向,也会涉及到服务端 📃 个人状态: 在校大学生一枚,已拿多个前端 offer(秋招) 🚀 未来打算: 为中国的工业软件事业效力n年 🥇 推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2Vue3项目实战 🥝

    2024年02月21日
    浏览(51)
  • 4.php开发-个人博客项目&登录验证&cookie&session&验证码安全​

    目录 知识点 本节大纲思路 ——这里以我自己的为例—— cookie验证—————— login1.php-登录后台界面 login_check.php-检查,作为包含文件 add_news.php-后台界面 php编码 如何创建 Cookie?--setcookie() 语法 实例 1 php header跳转 演示案例-cookie验证脆弱问题 session验证—————— sess

    2024年01月25日
    浏览(47)
  • 4.php开发-个人博客项目&登录验证&cookie&session&验证码安全

    目录 4.php开发-个人博客项目登录验证cookiesession验证码安全 知识点 本节大纲思路 ——这里以我自己的为例—— cookie验证—————— login1.php-登录后台界面 login_check.php-检查,作为包含文件 add_news.php-后台界面 php编码 如何创建 Cookie?--setcookie() 语法 实例 1 php header跳转 演示

    2024年01月23日
    浏览(47)
  • 6.php开发-个人博客项目&Tp框架&路由访问&安全写法&历史漏洞

    目录 知识点 php框架——TP URL访问 Index.php-放在控制器目录下 ​编辑 Test.php--要继承一下 带参数的—————— 加入数据库代码 --不过滤 --自己写过滤 --手册(官方)的过滤 用TP框架找漏洞: 如何判断网站是thinkphp? 黑盒: 白盒: php总结 ​ 1-基于TP框架入门安装搭建使用

    2024年01月25日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包