基於 abp vNext 和 .NET Core 開發博客項目 - 博客介面實戰篇(二)

来源:https://www.cnblogs.com/meowv/archive/2020/06/03/12994914.html
-Advertisement-
Play Games

系列文章 基於 abp vNext 和 .NET Core 開發博客項目 - 使用 abp cli 搭建項目 基於 abp vNext 和 .NET Core 開發博客項目 - 給項目瘦身,讓它跑起來 基於 abp vNext 和 .NET Core 開發博客項目 - 完善與美化,Swagger登場 ...


系列文章

  1. 基於 abp vNext 和 .NET Core 開發博客項目 - 使用 abp cli 搭建項目
  2. 基於 abp vNext 和 .NET Core 開發博客項目 - 給項目瘦身,讓它跑起來
  3. 基於 abp vNext 和 .NET Core 開發博客項目 - 完善與美化,Swagger登場
  4. 基於 abp vNext 和 .NET Core 開發博客項目 - 數據訪問和代碼優先
  5. 基於 abp vNext 和 .NET Core 開發博客項目 - 自定義倉儲之增刪改查
  6. 基於 abp vNext 和 .NET Core 開發博客項目 - 統一規範API,包裝返回模型
  7. 基於 abp vNext 和 .NET Core 開發博客項目 - 再說Swagger,分組、描述、小綠鎖
  8. 基於 abp vNext 和 .NET Core 開發博客項目 - 接入GitHub,用JWT保護你的API
  9. 基於 abp vNext 和 .NET Core 開發博客項目 - 異常處理和日誌記錄
  10. 基於 abp vNext 和 .NET Core 開發博客項目 - 使用Redis緩存數據
  11. 基於 abp vNext 和 .NET Core 開發博客項目 - 集成Hangfire實現定時任務處理
  12. 基於 abp vNext 和 .NET Core 開發博客項目 - 用AutoMapper搞定對象映射
  13. 基於 abp vNext 和 .NET Core 開發博客項目 - 定時任務最佳實戰(一)
  14. 基於 abp vNext 和 .NET Core 開發博客項目 - 定時任務最佳實戰(二)
  15. 基於 abp vNext 和 .NET Core 開發博客項目 - 定時任務最佳實戰(三)
  16. 基於 abp vNext 和 .NET Core 開發博客項目 - 博客介面實戰篇(一)

上篇文章完成了兩個介面:文章列表頁、文章詳情頁,本篇繼續。

分類列表

1

分析:這裡多了一個統計文章數量的欄位,可以直接新建一個模型QueryCategoryDto.cs繼承CategoryDto

//QueryCategoryDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{
    public class QueryCategoryDto : CategoryDto
    {
        /// <summary>
        /// 總數
        /// </summary>
        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
    {
        /// <summary>
        /// 查詢分類列表
        /// </summary>
        /// <returns></returns>
        Task<ServiceResult<IEnumerable<QueryCategoryDto>>> 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
    {
        /// <summary>
        /// 查詢分類列表
        /// </summary>
        /// <param name="factory"></param>
        /// <returns></returns>
        Task<ServiceResult<IEnumerable<QueryCategoryDto>>> QueryCategoriesAsync(Func<Task<ServiceResult<IEnumerable<QueryCategoryDto>>>> 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
    {
        /// <summary>
        /// 查詢分類列表
        /// </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);
                return result;
            });
        }
    }
}

緩存就不說了,查詢分類列表,聯合查詢文章和分類兩張表,關聯欄位為CategoryId,然後分組,計算出對應的數量,在BlogController中添加API。

/// <summary>
/// 查詢分類列表
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("categories")]
public async Task<ServiceResult<IEnumerable<QueryCategoryDto>>> QueryCategoriesAsync()
{
    return await _blogService.QueryCategoriesAsync();
}

2

標簽列表

3

分析:和分類列表差不多,新建模型QueryTagDto.cs繼承TagDto

//QueryTagDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{
    public class QueryTagDto : TagDto
    {
        /// <summary>
        /// 總數
        /// </summary>
        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
    {
        /// <summary>
        /// 查詢標簽列表
        /// </summary>
        /// <param name="factory"></param>
        /// <returns></returns>
        Task<ServiceResult<IEnumerable<QueryTagDto>>> QueryTagsAsync(Func<Task<ServiceResult<IEnumerable<QueryTagDto>>>> 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
    {
        /// <summary>
        /// 查詢標簽列表
        /// </summary>
        /// <returns></returns>
        Task<ServiceResult<IEnumerable<QueryTagDto>>> 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
    {
        /// <summary>
        /// 查詢標簽列表
        /// </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);
                return result;
            });
        }
    }
}

查詢標簽列表需要聯合查詢tags和post_tags,根據TagId進行關聯,然後分組從而獲取標簽下文章的總數,在BlogController中添加API。

/// <summary>
/// 查詢標簽列表
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("tags")]
public async Task<ServiceResult<IEnumerable<QueryTagDto>>> QueryTagsAsync()
{
    return await _blogService.QueryTagsAsync();
}

4

分類名稱&文章列表

5

分析:此頁面下包含兩個介面,查詢分類的名稱和當前分類下的文章列表,和文章列表不同的是,它不帶分頁。分類包含兩個欄位,分類名稱和展示名稱,我們要把真正的名稱查詢出來展示在頁面上。

分類名稱

不需要給他添加返回模型,直接返回一個string類型即可,同時給一個查詢參數name,添加獲取分類名稱介面和緩存介面。

//IBlogService.Category.cs
/// <summary>
/// 獲取分類名稱
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
Task<ServiceResult<string>> GetCategoryAsync(string name);
//IBlogCacheService.Category.cs
/// <summary>
/// 獲取分類名稱
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
Task<ServiceResult<string>> GetCategoryAsync(string name, Func<Task<ServiceResult<string>>> 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
/// <summary>
/// 獲取分類名稱
/// </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("分類", name));
            return result;
        }

        result.IsSuccess(category.CategoryName);
        return result;
    });
}

FormatWith()是擴展方法,ResponseText.WHAT_NOT_EXIST是之前說過的常量,直接查詢是否存在當前name的分類,如果不存在給出錯誤提示,存在的話,則只返回分類名稱,在BlogController中添加API。

/// <summary>
/// 獲取分類名稱
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[HttpGet]
[Route("category")]
public async Task<ServiceResult<string>> GetCategoryAsync(([Required] string name)
{
    return await _blogService.GetCategoryAsync(name);
}

[Required]Attribute 指定參數name必填。

6

7

文章列表

通過分類名稱查詢文章列表和分頁查詢文章列表返回模型是一樣的,只是不用分頁,所以直接返回一個列表就可以了,添加通過分類名稱查詢文章列表和緩存的介面。

//IBlogService.Post.cs
/// <summary>
/// 通過分類名稱查詢文章列表
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByCategoryAsync(string name);
//IBlogCacheService.Post.cs
/// <summary>
/// 通過分類名稱查詢文章列表
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByCategoryAsync(string name, Func<Task<ServiceResult<IEnumerable<QueryPostDto>>>> 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
/// <summary>
/// 通過分類名稱查詢文章列表
/// </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;
    });
}

這個邏輯和分頁查詢文章列表是差不多的,聯合查詢文章表和分類表,關聯欄位為CategoryId,指定查詢條件categories.DisplayName==name,以CreationTime倒序排序,年份分組,篩選出所需欄位返回,在BlogController中添加API。

/// <summary>
/// 通過分類名稱查詢文章列表
/// </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);
}

8

標簽名稱&文章列表

9

分析:此頁面和分類頁一樣,包含兩個介面,查詢標簽的名稱和當前標簽下的文章列表。

標簽名稱

添加獲取標簽名稱介面和緩存介面,GetTagAsync()

//IBlogService.Tag.cs
/// <summary>
/// 獲取標簽名稱
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
Task<ServiceResult<string>> GetTagAsync(string name);
//IBlogCacheService.Tag.cs
/// <summary>
/// 獲取標簽名稱
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
Task<ServiceResult<string>> GetTagAsync(string name, Func<Task<ServiceResult<string>>> 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
/// <summary>
/// 獲取標簽名稱
/// </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("標簽", name));
            return result;
        }

        result.IsSuccess(tag.TagName);
        return result;
    });
}

FormatWith()是擴展方法,ResponseText.WHAT_NOT_EXIST是之前說過的常量,直接查詢是否存在當前name的分類,如果不存在給出錯誤提示,存在的話,則只返回分類名稱,在BlogController中添加API。

/// <summary>
/// 獲取標簽名稱
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[HttpGet]
[Route("tag")]
public async Task<ServiceResult<string>> GetTagAsync(string name)
{
    return await _blogService.GetTagAsync(name);
}

[Required]Attribute 指定參數name必填。

10

11

文章列表

和上面一模一樣的,添加通過標簽名稱查詢文章列表介面和緩存介面。

//IBlogService.Post.cs
/// <summary>
/// 通過標簽名稱查詢文章列表
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByTagAsync(string name);
//IBlogCacheService.Post.cs
/// <summary>
/// 通過標簽名稱查詢文章列表
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByTagAsync(string name, Func<Task<ServiceResult<IEnumerable<QueryPostDto>>>> 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
/// <summary>
/// 通過標簽名稱查詢文章列表
/// </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;
    });
}

這個查詢有點特殊,聯合查詢了3張表,先查post_tags和tags,關聯欄位TagId,再根據PostId查詢posts,指定查詢條件tags.DisplayName==name,以CreationTime倒序排序,年份分組,篩選出所需欄位返回,在BlogController中添加API。

/// <summary>
/// 通過標簽名稱查詢文章列表
/// </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);
}

12

至此,基本上完成了博客前端所需的所有查詢介面,就還剩下友鏈的查詢,大家可以自己完成,後面如果需要什麼新的介面再回頭來寫就好了。

開源地址:https://github.com/Meowv/Blog/tree/blog_tutorial


搭配下方課程學習更佳 ↓ ↓ ↓

http://gk.link/a/10iQ7

7


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 有時,使符號常量的作用域為類很有用: class Bakery { private: const int Months = 12; // declare a constant? FALSE double costs[Months]; ... 但這是行不通的,因為——聲明類只是描述了對象的形式,並沒有 ...
  • 在寫代碼的時候,免不了要使用變數。但程式中的一個變數並不一定是在哪裡都可以被使用,根據情況不同,會有不同的“有效範圍”。 看這樣一段代碼: def func(x): print ('X in the beginning of func(x): ', x) x = 2 print ('X in the ...
  • 一.瀏覽器內核太撈了一般人都會避開他 from selenium.webdriver import Chrome from selenium.webdriver import ChromeOptions option = ChromeOptions() option.add_experimental ...
  • spring註入map,spring註入一個介面的多個實現類在map里 ...
  • 轉載https://www.jianshu.com/p/5d27888e7c93#!/xh #!/usr/bin/env python # -*- coding=utf-8 -*- """ AES加密解密工具類 @author jzx @date 2018/10/24 此工具類加密解密結果與 htt ...
  • 什麼是sam 轉換 Single Abstract Method 實際上這是java8中提出的概念,你就把他理解為是一個方法的介面的就可以了 看一下我們每天都在使用的線程池 ExecutorService executorService= Executors.newScheduledThreadPo ...
  • 結合 AOP 輕鬆處理事件發佈處理日誌 Intro 前段時間,實現了 EventBus 以及 EventQueue 基於 Event 的事件處理,但是沒有做日誌(EventLog)相關的部分,原本想增加兩個介面, 處理事件發佈日誌和事件處理日誌,最近用了 AOP 的思想處理了 EntityFrame ...
  • Microsoft.AspNetCore.Mvc.Versioning //引入程式集 .net core 下麵api的版本控製作用不需要多說,可以查閱https://www.cnblogs.com/dc20181010/p/11313738.html 普通的版本控制一般是通過鏈接、header此類 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...