❤️ 感谢不看好我们的人 | .NET 框架 Furion v4.9.2.25

来源: 投稿
作者: 百小僧
2024-04-22 01:06:00

感谢看好我们的人,更感谢不看好我们的人

自2023年11月26日以来,Furion 在商业化探索的道路上已走过了五个多月的历程。这段时间里,我们积极组建了一支充满活力和创新精神的新团队,不仅全力投入到下一代 Furion 版本的研发中,还同步研发了多款具有市场竞争力的商业应用产品。

起初,我们担心商业化的进程可能会引发市场的抵触和疑虑。然而,事实却证明我们的担忧是多余的。通过不断的努力和优化,我们逐渐吸引了越来越多的精准用户,他们不仅认可我们的价值,还愿意与我们携手共进,共同成长。更令人欣喜的是,这类用户的数量还在持续增长,为我们未来的发展奠定了坚实的基础。

在这个过程中,我们与用户之间建立了深厚的信任和合作关系。用户们可以更加放心地使用 Furion 框架,遇到问题时也能得到我们及时、专业的支持。而我们则通过用户的反馈和需求,不断优化产品功能,提升用户体验,实现了与用户的互利共赢。

此外,我们还通过商业化的收入,进一步壮大了团队规模,吸引了更多优秀的人才加入我们的行列。这使得我们能够更加专注于产品的研发和创新,为用户提供更多、更好的功能和应用产品。

展望未来,我们将继续秉承用户至上的理念,不断优化 Furion 框架和商业应用产品,为用户提供更加便捷、高效、安全的解决方案。同时,我们也期待与更多的合作伙伴携手共进,共同开创更加美好的未来。

最后,

对于那些看好我们的人,我们心怀感激,你们的信任与支持是我们前进的动力。同样我们也珍视那些不看好我们的人,因为你们的质疑与挑战,让我们时刻保持清醒与警觉,不断寻找改进的空间。

在这个阶段,我们其实更期待听到质疑的声音,因为它们能让我们更加深入地审视自己,从而做出更好的决策。逆风翻盘,往往比顺风顺水更具挑战性,也更能体现出我们的价值。

无论外界如何看待我们,我们都坚信,我们正在做的事情是正确的、有意义的,它让我们自己感到快乐,也为更多用户带来了价值。这就是我们前进的动力,也是我们坚持下去的信念。


企业招聘/市场情况

自 Furion 于2023年11月26日启动商业化以来,已成功为 4175 家企业开通文档会员或VIP会员服务,并出具了相应发票。同时,我们在招聘平台上统计到已有 653 个企业发布了招聘岗位,仅2024年4月就有 49 家企业在平台上发布招聘信息。

此外,在 Gitee 平台上,Furion 仓库收获了超过 11K 的 Stars,近 6K 的 Watches,以及 4K 的 Forked。值得一提的是,我们的仓库贡献者已超过 250人,大家的热情参与和贡献是我们不断前行的动力。而在 NuGet 平台,我们的总下载量已接近 1600万,这一数字充分证明了 Furion 的受欢迎程度和广泛应用。

在此,我们衷心感谢大家的支持与信任。未来,我们将继续努力,为大家提供更好的产品和服务。

BOSS  直聘

https://www.zhipin.com/web/geek/job?query=furion&city=100010000

前程无忧

https://we.51job.com/pc/search?jobArea=000000&keyword=furion&searchType=2&keywordType=

项目信息


本期亮点

1. 新增定时任务作业计划工厂 ISchedulerFactory 启停作业 StartJob 和 PauseJob 方法

问题分析

在过去,要启动或暂停某个作业,需遵循一系列步骤:

// 首先要检查作业计划是否存在
-if (_schedulerFactory.TryGetJob(jobId, out var scheduler))
{
     // 接着启动作业
-    scheduler?.Start();
     
     // 或暂停作业
-    scheduler?.Pause();
}

这种操作方式虽然功能完备,但处理大量作业时显得繁琐冗长。

解决方案

现在,我们进行了优化,只需通过以下简洁的调用即可完成操作:

 // 轻松启动作业
+_schedulerFactory.TryStartJob(jobId, out var scheduler);

 // 便捷暂停作业
+_schedulerFactory.TryPauseJob(jobId, out var scheduler);

此优化显著提升了作业管理的便捷性和效率,操作上更加流畅自如。

2. 新增运行时动态修改  Swagger UI 信息

问题分析

在某些应用场景中,我们可能需要对 Swagger UI 的描述内容进行动态调整,以适应不同需求。为此,可以利用 ISwaggerProvider 接口实现灵活操作。

以下是相关代码示例:

+ public void ChangeSwaggerUI_Information([FromServices] ISwaggerProvider swaggerProvider)
  {
      // 通过依赖注入的方式,引入 ISwaggerProvider 接口
+     var openApiDocument = swaggerProvider.GetSwagger("Default"); // 获取名为 "Default" 的分组文档

      // 直接对文档信息进行修改
+     openApiDocument.Info.Title = "我是新标题";
+     openApiDocument.Info.Description = "我是新描述";
}

以下是相关的屏幕截图:

在这段代码中,我们首先通过依赖注入的方式获取了 ISwaggerProvider 接口的实例,然后调用其 GetSwagger 方法获取了名为 "Default" 的分组文档。接着,我们直接修改了文档中的标题和描述信息,实现了对 Swagger UI 描述内容的动态调整。

3. 新增 AES 加解密支持向量 IV、模式 Mode 和填充 Padding 配置

问题分析

在使用前端库 crypto-js 与后端 Java 进行 AES 加解密操作时,由于先前的 Furion 框架未提供必要的向量 IV(初始化向量)、模式 Mode(加密模式)以及填充 Padding(数据填充方式)的配置选项,这导致了在与其他编程语言进行互操作时,加解密过程出现异常情况。

示例代码

// 要加密的明文
var plainText = "一个应用程序框架,您可以将它集成到任何 .NET/C# 应用程序中。";

// 密钥(必须为 16、24 或 32 字节,这里使用 32 字节)
+ var key = "bda66540c463dfdbe70666019f89e554";    // furion 小写 32 位 MD5 加密字符串

// 自定义偏移量(16 字节),如果不指定,则使用默认值
+ byte[] customIV = { 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, 0x6f, 0x70, 0x81, 0x92, 0xa3, 0xb4, 0xc5, 0xd6, 0xe7, 0xf8, 0x09 };

// 使用 CBC 模式和 PKCS7 填充进行加密
+ var encryptedText = AESEncryption.Encrypt(plainText, key
+     , customIV    // 向量
+     , CipherMode.CBC    // 模式
+     , PaddingMode.PKCS7);    // 填充

Console.WriteLine("加密后文本: " + encryptedText);

// 使用相同的密钥、偏移量、模式和填充进行解密
+ var decryptedText = AESEncryption.Decrypt(encryptedText, key
+     , customIV    // 向量
+     , CipherMode.CBC    // 模式
+     , PaddingMode.PKCS7);    // 填充

Console.WriteLine("解密后文本: " + decryptedText);

输出结果

+ 加密后文本: Gis8TV5vcIGSo7TF1uf4Ceu2xkJjjXomVxcd7SGBQOi5doe8iu+m1mI+FYK6pTrmhp4vKQEfjNAtbQnZiqjHwWrk0Tt2gPXEcX750PjCvsbA/OQBBc0r/JsJPuW2V5Hf+7fk5b8Q7mqHOwDM8432Ag==

+ 解密后文本: 一个应用程序框架,您可以将它集成到任何 .NET/C# 应用程序中。

4. 修复动态 WebAPI 错误将 CancellationToken 类型当作路由参数

问题分析

在实际应用中,经常需要监控客户端发送的请求是否在中途意外中断,例如服务器尚未完成响应时,用户关闭了浏览器窗口或标签页,或其他不可预见的因素导致请求未能完整执行。

解决方案

针对这种情况,我们可以在 Action 方法的参数列表中增加 CancellationToken 参数。此参数的作用在于能够监听客户端是否提前终止了请求,从而进行相应的处理。

[HttpGet]
+public async Task SomeApi(CancellationToken cancellationToken)
{
    // 监听客户端是否终止请求
+    cancellationToken.Register(() => 
+    {
+        Console.WriteLine("用户中断了请求。");
+    });

    // 确保在异步方法中使用 cancellationToken
    await Task.Run(() => {
        // 模拟异步操作
+    }, cancellationToken);
}

注意,在异步方法中,应该确保 CancellationToken 被正确传递并用于可能中断的异步操作。在上面的代码中,我们使用了 Task.Run 来模拟一个异步操作,并将 cancellationToken 作为参数传递,以便在需要时能够中断该操作。

相关文档

对于如何进一步了解和使用 CancellationToken,您可以查阅微软官方文档,了解有关 ASP.NET Core 中最小 API 响应的更多细节:
https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/minimal-apis/responses?view=aspnetcore-8.0

5. 新增粘土对象 Clay 支持无限极组合嵌套

问题分析

在之前的版本中,Clay 粘土对象主要支持通过对象或 JSON 字符串的方式生成,但缺乏对对象属性直接设置粘土对象的支持。

在新版本中,我们实现了对任意组合和嵌套的支持,使得粘土对象更为灵活和强大。

public dynamic TestClay()
{
    // 创建粘土对象 package
+    var package = Clay.Object(new
+    {
+        Name = "我是第一层"
+    });

    var a3 = Clay.Object(new object[] { });

    // 为 a3 数组添加多个对象元素
    a3[0] = new
    {
        Name = "明细1"
    };
    a3[1] = new
    {
        Name = "明细2"
    };
    a3[2] = package; // 将 package 嵌套到 a3中

+    // 创建另一个粘土对象,其中嵌套了 package
+    a3[3] = new
+    {
+        package // 这里直接使用变量名作为键,将 package 作为一个属性嵌套
+    };

+    // 创建粘土对象 policy,其中包含多个嵌套对象
+    var policy = Clay.Object(new
    {
        search = new
        {
            hotel_id = 10,
            check_in_date = DateTime.Now
        },
+        // 在 policy 中嵌套 package 对象
+        package,
+        // 使用匿名类(或类型类)嵌套粘土对象
+        package1 = new
+        {
+            package, // 嵌套 package 对象
+            a3 // 嵌套 a3 数组对象
+        }
    });

    return policy;
}

最终输出

经过上述代码的构造,我们得到了一个嵌套的粘土对象 policy,其结构如下:

{
  "search": {
    "hotel_id": 10,
    "check_in_date": "2024-04-16T14:37:46.201809+08:00"
  },
  "package": {
    "Name": "我是第一层"
  },
  "package1": {
    "package": {
      "Name": "我是第一层"
    },
    "a3": [
      {
        "Name": "明细1"
      },
      {
        "Name": "明细2"
      },
      {
        "Name": "我是第一层"
      },
      {
        "package": {
          "Name": "我是第一层"
        }
      }
    ]
  }
}

这个输出的 JSON 结构清晰地展示了 policy 对象内部是如何嵌套 package  a3 对象的,以及 a3 数组又是如何包含多个对象元素的。这样的结构使得粘土对象能够灵活处理各种复杂的嵌套场景。

6. 新增动态 WebAPI 支持贴 [Route] 特性动态生成控制器情况

示例代码

 Furion 框架的演进中,控制器生成的方式发生了显著变化。以往,生成控制器需要满足一系列条件,如派生自 ControllerBase 基类,或添加 [DynamicApiController] 特性,或实现 IDynamicApiController 接口。

现在,我们大大简化了这一过程,只需在类上添加 [Route("路由模板")] 特性,即可轻松生成控制器。

- // [ApiController]    // 此特性可选,主要实现模型绑定验证
+[Route("[controller]")]    // 仅需添加此路由特性,即可实现控制器的生成
 public class RouteController
 {
     public void Get()
     {
     }
 }

这一改进不仅简化了代码结构,还提高了开发效率,让开发者能够更加专注于业务逻辑的实现。

7. 修复审计日志 Monitor 不支持粘土对象 Clay/dynamic 类似格式化输出

问题分析

粘土对象 赋予了强类型 C# 语言操作对象的能力,使其类似于弱类型语言 JavaScript 的灵活性

在某些情况下,我们需要在接口中直接返回粘土对象 Clay/dynamic 类型。当引入审计日志 [LoggingMonitor] 支持时,我们发现无法正确输出 JSON 格式。例如:

+[LoggingMonitor]
+public dynamic TestClayMonitor()
{
    var clay = Clay.Parse("""
        {
        	"name": "Furion",
        	"age": 4,
        	"products": [{
        		"name": "Furion",
        		"author": "百小僧"
        	},
        	{
        		"name": "Layx",
        		"author": "百小僧"
        	}],
        }
        """);

+    return clay;
}

输出结果却是:

观察打印结果,我们发现粘土对象被错误地转换成了 key:value 格式,这显然不是期望的结果。

解决方案

在最近的更新中,我们已经修复了这个问题,现在输出格式正确无误:

8. 新增远程情况代理模式支持 [BaseAddress] 特性快速设置客户端 BaseAddress

问题分析

在实际开发中,我们经常会遇到需要对接第三方 API 接口的情况。过去,通常的做法是在全局配置文件如 Program.cs  Startup.cs 中统一设置每个接口的 BaseAddress。例如:

services.AddRemoteRequest(options =>
{
+    options.AddHttpClient("weixin", client => 
+    {
+        client.BaseAddress = new Uri("https://weixin.qq.com/");
+    });
});

这种方式虽然可以实现功能,但每次添加新的第三方接口时都需要在全局配置中增加相应的设置,显得不够灵活且不够直观。

解决方案

为了解决上述问题,我们在新版本中引入了 [BaseAddress] 特性。这一特性允许我们在接口级别甚至接口方法级别直接设置 BaseAddress,从而无需在全局配置中进行繁琐的设置。以下是使用新特性的示例:

+[BaseAddress("https://weixin.qq.com/")] // 为整个接口方法设置基础地址
public interface IHttp : IBase
{
     [Get("api/theapi")]
     Task<HttpResponseMessage> TheApi();

+    [Get("api/otherapi"), BaseAddress("https://v2.weixin.qq.com/")] // 为特定方法设置不同的基础地址
     Task<HttpResponseMessage> OtherApi();
}

使用 [BaseAddress] 特性的好处在于,它提供了更加灵活和精细化的配置方式,让我们能够根据不同的接口或方法需求设置不同的 BaseAddress。同时,这也减少了在全局配置中维护大量设置的工作量和出错的可能性。

因此,我们无需再编写如下全局配置代码:

// 不再需要全局配置设置 BaseAddress
// options.AddHttpClient("weixin", client => 
// {
//     client.BaseAddress = new Uri("https://weixin.qq.com/");
// });

通过这种方式,我们可以更加高效、简洁地进行接口的配置,提高开发效率和代码的可维护性。


本期更新

更新日志:https://furion.net/docs/category/upgrade/

  • 新特性

    • [新增] 远程请求代理模式支持 [BaseAddress] 特性快速设置 HttpClient 客户端 BaseAddress 4.9.2.25 ⏱️2024.04.19 ea88c95
    • [新增] 粘土对象进行固化类型时支持 JsonSerializerOptions 序列化配置 4.9.2.24 ⏱️2024.04.17 cc6dd13
    • [新增] 动态 WebAPI 支持贴 [Route] 特性动态生成控制器 4.9.2.19 ⏱️2024.04.16 #I9H1QH
    • [新增] 粘土对象支持无限极组合嵌套功能 4.9.2.19 ⏱️2024.04.16 b02916e
    • [新增] AES 加解密支持向量 IV、模式 Mode 和填充 Padding 配置 4.9.2.18 ⏱️2024.04.15 d549bba
    • [新增] 定时任务作业计划工厂 ISchedulerFactory 启停作业 StartJobPauseJob 方法 4.9.2.16 ⏱️2024.04.11 89061ef
  • 突破性变化

    • [更新] Swagger 文档注释逻辑,将 /// 注释方式优先级调整至最高,可覆盖 [DisplayName] 特性方式 4.9.2.17 ⏱️2024.04.14 ba5249c
    • [更新] 定时任务作业计划工厂 TryRunJob 方法签名,追加 out IScheduler scheduler 参数 4.9.2.16 ⏱️2024.04.11 89061ef
  • 问题修复

    • [修复] 定时任务创建作业处理程序存在内存溢出风险 4.9.2.25 ⏱️2024.04.19 #I9D0RH
    • [修复] 动态 WebAPI 不支持 [BindNever] 特性忽略路由和 Action 参数设置 4.9.2.25 ⏱️2024.04.19 21599e6
    • [修复] 审计日志 Monitor 不支持粘土对象 Clay/dynamic 类型格式化输出 4.9.2.24 ⏱️2024.04.17 d578cfb
    • [修复] 粘土对象无限嵌套粘土对象且 XElement 属性包含 type="null" 节点出现异常问题 4.9.2.21 ⏱️2024.04.16 9d5870f
    • [修复] 粘土对象嵌套粘土对象只输出第一个属性问题 4.9.2.20 ⏱️2024.04.16 1a75778
    • [修复] 动态 WebAPI 错误将 CancellationToken 类型当作路由参数 4.9.2.19 ⏱️2024.04.16 #I9H14X
    • [修复] 定时任务因新增 GroupSet 功能影响到了原有的 SetGroupName 逻辑 4.9.2.15 ⏱️2024.04.11 #I9FOU0 9e08278
  • 文档

    • [更新] 事件总线文档、定时任务文档、规范化接口文档、远程请求文档、粘土对象文档、FS 静态类文档、序列化文档、模块化文档、规范化文档、数据加解密文档、动态 WebAPI 文档
展开阅读全文
点击加入讨论🔥(2) 发布并加入讨论🔥
2 评论
2 收藏
分享
返回顶部
顶部