

两千星 .NET5 框架 Furion 亮点分析(一)
source link: http://www.cnblogs.com/dotnetchina/p/14201430.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

让 .NET 开发更简单,更通用,更流行。
Furion 介绍
Furion 是基于 .NET5 平台下打造的现代化 Web 框架。旨在 让 .NET 开发更简单,更通用,更流行。
。
Furion 非常精悍短小,底层 只依赖两个第三方库 ,去除注释文件仅有 73KB
大小。
麻雀虽小五脏俱全,企业级项目开发所需功能它一个也不少。
开源地址
文档地址
- 国内文档: https://monksoul.gitee.io/furion/
- 国外文档: https://furion.pro
目前文档正在逐步完善中。
项目案例
- 考试君:基于 Furion 的在线考试系统
- 园丁:基于 Furion + Blazor 的超简单后台管理系统
- Queer:基于 Furion + Layui 的通用型管理系统
- Pear Admin:PearAdmin 官方和 Furion 官方合作管理系统
- JoyAdmin:基于 Furion + iviewadmin 开发的管理系统
Furion 亮点介绍
1. 极易集成
Furion
设计遵循“无侵入性或侵入性极小”原则,只需要在 Progame.cs
文件夹中添加 Inject()
方法即可完成初始化配置。
using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; namespace FurStart { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder .Inject() // 只需这一行即可完成配置 .UseStartup<Startup>(); }); } }
文档传送门: https://monksoul.gitee.io/furion/docs/get-start
2. 丰富脚手架
Furion
提供了 .NET5
所有 Web 类型的脚手架,可以极速搭建企业项目多层架构。
文档传送门: https://monksoul.gitee.io/furion/docs/template
3. 极少依赖
Furion
为了追求极速入门,极致性能,尽可能的不使用或减少第三方依赖。目前 Furion
仅集成了以下两个依赖:
- MiniProfiler :性能分析和监听必备
- Swashbuckle :
Swagger
接口文档
麻雀虽小五脏俱全。 Furion
即使只集成了这两个依赖,但是主流的 依赖注入/控制反转
, AOP
面向切面编程, 事件总线
, 数据验证
, 数据库操作
等等一个都不少。
文档传送门: https://monksoul.gitee.io/furion/docs/
4. appsettings.json
分割合并
默认情况下,.NET5 的配置文件需写在 appsettings.json
文件中,如需添加其他配置,需手动添加并在主机启动时加载进来, Furion
提供了非常灵活方便的方式,支持配置文件放在项目其他位置,并自动加载,自动配置并合并。如: system.json
{ "AppInfo": { "Name": "Furion", "Version": "1.7.0" } }
此时 system.json
会自动加载并自动合并。
文档传送门: https://monksoul.gitee.io/furion/docs/configuration
5. 热重载配置选项
Furion
提供了非常灵活的选项配置功能,支持后期配置,配置更改通知。
using Furion.ConfigurableOptions; namespace Furion.Application { public class AppInfoOptions : IConfigurableOptionsListener<AppInfoOptions> { public string Name { get; set; } public string Version { get; set; } public string Company { get; set; } // 选项更改监听 public void OnListener(AppInfoOptions options, IConfiguration configuration) { var name = options.Name; // 实时的最新值 var version = options.Version; // 实时的最新值 } // 选项后期配置 public void PostConfigure(AppInfoOptions options, IConfiguration configuration) { } }
文档传送门: https://monksoul.gitee.io/furion/docs/options
6. 动态API及变体服务
Furion
提供了动态构建 WebApi
的方式,可以大大提高 WebApi
的开发效率,还能实现 WebApi
服务接口化。
using Furion.DynamicApiController; namespace Furion.Application { public class FurAppService : IDynamicApiController { public string Get() { return $"GET 请求"; } public string Post() { return $"POST 请求"; } public string Delete() { return $"DELETE 请求"; } public string Put() { return $"PUT 请求"; } public string Patch() { return $"PATCH 请求"; } } }
文档传送门: https://monksoul.gitee.io/furion/docs/dynamic-api-controller
7. 统一结果规范化处理
Furion
提供了非常灵活的方式去规范化 WebApi
的返回结果,使其采用统一规范的结果返回。
using Furion.DependencyInjection; using Furion.Utilities; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.ModelBinding; using System; using System.Collections.Generic; using System.Threading.Tasks; namespace Furion.UnifyResult { /// <summary> /// RESTful 风格返回值 /// </summary> [SkipScan, UnifyModel(typeof(RESTfulResult<>))] public class RESTfulResultProvider : IUnifyResultProvider { /// <summary> /// 异常返回值 /// </summary> /// <param name="context"></param> /// <returns></returns> public IActionResult OnException(ExceptionContext context) { // 解析异常信息 var (ErrorCode, ErrorContent) = UnifyContext.GetExceptionMetadata(context); return new JsonResult(new RESTfulResult<object> { StatusCode = ErrorCode, Succeeded = false, Data = null, Errors = ErrorContent, Extras = UnifyContext.Take(), Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }); } /// <summary> /// 成功返回值 /// </summary> /// <param name="context"></param> /// <returns></returns> public IActionResult OnSucceeded(ActionExecutedContext context) { object data; // 处理内容结果 if (context.Result is ContentResult contentResult) data = contentResult.Content; // 处理对象结果 else if (context.Result is ObjectResult objectResult) data = objectResult.Value; else if (context.Result is EmptyResult) data = null; else return null; return new JsonResult(new RESTfulResult<object> { StatusCode = context.Result is EmptyResult ? StatusCodes.Status204NoContent : StatusCodes.Status200OK, // 处理没有返回值情况 204 Succeeded = true, Data = data, Errors = null, Extras = UnifyContext.Take(), Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }); } /// <summary> /// 验证失败返回值 /// </summary> /// <param name="context"></param> /// <param name="modelStates"></param> /// <param name="validationResults"></param> /// <param name="validateFailedMessage"></param> /// <returns></returns> public IActionResult OnValidateFailed(ActionExecutingContext context, ModelStateDictionary modelStates, Dictionary<string, IEnumerable<string>> validationResults, string validateFailedMessage) { return new JsonResult(new RESTfulResult<object> { StatusCode = StatusCodes.Status400BadRequest, Succeeded = false, Data = null, Errors = validationResults, Extras = UnifyContext.Take(), Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }); } /// <summary> /// 处理输出状态码 /// </summary> /// <param name="context"></param> /// <param name="statusCode"></param> /// <returns></returns> public async Task OnResponseStatusCodes(HttpContext context, int statusCode) { switch (statusCode) { // 处理 401 状态码 case StatusCodes.Status401Unauthorized: await context.Response.WriteAsJsonAsync(new RESTfulResult<object> { StatusCode = StatusCodes.Status401Unauthorized, Succeeded = false, Data = null, Errors = "401 Unauthorized", Extras = UnifyContext.Take(), Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }, JsonSerializerUtility.GetDefaultJsonSerializerOptions()); break; // 处理 403 状态码 case StatusCodes.Status403Forbidden: await context.Response.WriteAsJsonAsync(new RESTfulResult<object> { StatusCode = StatusCodes.Status403Forbidden, Succeeded = false, Data = null, Errors = "403 Forbidden", Extras = UnifyContext.Take(), Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }, JsonSerializerUtility.GetDefaultJsonSerializerOptions()); break; default: break; } } } }
文档传送门: https://monksoul.gitee.io/furion/docs/specification-document#67-统一返回值模型
8. 强大的 Swagger
在线文档
Furion
内置了强大的 Swagger
规范化文档,并赋予了更多强大的能力。
文档传送门: https://monksoul.gitee.io/furion/docs/specification-document
9. 非常强大的数据库操作功能
文档传送门: https://monksoul.gitee.io/furion/docs/dbcontext
10. 异常处理最佳实践
Furion
采用独特的异常处理方案,可以大大的将异常和业务逻辑分离。
using Furion.DynamicApiController; using Furion.FriendlyException; namespace Furion.Application { public class FurAppService : IDynamicApiController { [IfException(typeof(ExceptionType), ErrorMessage = "特定异常类型全局拦截")] [IfException(ErrorMessage = "全局异常拦截")] [IfException(ErrorCodes.z1000, ErrorMessage = "我覆盖了默认的:{0} 不能小于 {1}")] [IfException(ErrorCodes.x1001, "格式化参数1", "格式化参数2", ErrorMessage = "我覆盖了默认的:{0} 不能小于 {1}")] [IfException(ErrorCodes.x1000, "格式化参数1", "格式化参数2")] [IfException(ErrorCodes.SERVER_ERROR, "格式化参数1", "格式化参数2")] public int Get(int id) { if (id < 3) { throw Oops.Oh(ErrorCodes.z1000, id, 3); } return id; } } }
文档传送门: https://monksoul.gitee.io/furion/docs/friendly-exception
11. 强大且灵活的 SaaS 多租户实现方式
文档传送门: https://monksoul.gitee.io/furion/docs/saas
12. 极易使用的对象依赖配置
Furion
提供了三种极易配置的接口依赖配置。
using Furion.Core; using Furion.DatabaseAccessor; using Furion.DependencyInjection; namespace Furion.Application { public interface IBusinessService<T> { Person Get(int id); } public class BusinessService<T> : IBusinessService<T>, ITransient { private readonly IRepository<Person> _personRepository; public BusinessService(IRepository<Person> personRepository) { _personRepository = personRepository; } public Person Get(int id) { return _personRepository.Find(id); } } }
文档传送门: https://monksoul.gitee.io/furion/docs/dependency-injection
13. 强大的视图引擎
Furion
内置了强大的视图引擎功能,完美支持 Razor
语法。
var result = _viewEngine.RunCompile(@" Hello @Model.Name @foreach(var item in Model.Items) { <p>@item</p> } ", new TestModel { Name = "Furion", Items = new[] { 3, 1, 2 } });
文档传送门: https://monksoul.gitee.io/furion/docs/view-engine
结语
由于篇幅有效,这里只是抛砖引玉,但 Furion
的亮点远不止这些,可以查看文档了解并学习。
文档地址: https://monksoul.gitee.io/furion/
最后,喜欢 Furion 可以给个 Star,您的支持 Furion 才能越走越远。
Recommend
-
13
靴子落地,期盼已久的.Net5终于来了! 在3月16号正式发布了第一个预览版本。号称一统江湖的.Net5究竟为我们带来了什么,是...
-
23
“ 11月了,期待已久的.NET5即将发布,你做好准备了吗?如果还只是在Windows上用Visual Studio +...
-
25
#Net5 – Migrating a fully functional Windows Form app to Net 5 in 10 minutes ! elbruno EnglishP...
-
5
Net/NetCore/.NET5 ORM 六大查询体系 - SqlSugar 高级篇 SqlSugar ORM是一款老牌国产ORM框架,生命力也比较顽强,从早期ORM不成熟阶段,一...
-
19
WTM5.0发布,全面支持.net5 WTM5.0是WTM框架开源2年以来最大的一次升级,全面支持.net5,大幅重构了底层代码,针对广大用户提出的封装过度,不够灵...
-
12
New issue Net5.0 & fable3 #415 Conversation ...
-
8
.Net5 WPF快速入门系列教程 一、概要 在工作中大家会遇到需...
-
2
Install .NET5 on Ubuntu 20.04 Although I have and continue to spend the majority of my time developing .NET5 ASP.NET Core web applications and web API's on macOS, I've noticed...
-
12
Orchard Core .NET5 and C# 9 When .NET5 and C# 9 was released I eagerly began developing ASP.NET Core web applications and web API's using the new features.
-
17
Furion:.NET 5快速开发框架,让开发更简单,更通用,更流行!布莱恩特独立开发者
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK