两千星 .NET5 框架 Furion 亮点分析(一)

让 .NET 开发更简单,更通用,更流行。
Furion 介绍
Furion 是基于 .NET5 平台下打造的现代化 Web 框架。旨在 让 .NET 开发更简单,更通用,更流行。。
Furion 非常精悍短小,底层只依赖两个第三方库,去除注释文件仅有 73kb 大小。
麻雀虽小五脏俱全,企业级项目开发所需功能它一个也不少。

开源地址
文档地址
目前文档正在逐步完善中。
项目案例
- 考试君:基于 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 类型的脚手架,可以极速搭建企业项目多层架构。
| 模板类型 | 名称 | 版本 | 描述 |
|---|---|---|---|
| Furion.Template.Mvc | Mvc 模板 | ||
| Furion.Template.Api | WebApi 模板 | ||
| Furion.Template.App | Mvc/WebApi 模板 | ||
| Furion.Template.Razor | RazorPages 模板 | ||
| Furion.Template.RazorWithWebApi | RazorPages/WebApi 模板 | ||
| Furion.Template.Blazor | Blazor 模板 | ||
| Furion.Template.BlazorWithWebApi | Blazor/WebApi 模板 |
文档传送门: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 才能越走越远。
两千星 .NET5 框架 Furion 亮点分析(一)的更多相关文章
- .NET Core Community 第四个千星项目诞生:微服务框架 Surging
本文所有打赏将全数捐赠于 NCC(NCC 的资金目前由 倾竹大人 负责管理),请注明捐赠于 NCC.捐赠情况将由倾竹大人在此处公示. 提及 .NET 微服务,我们脑海中浮现的一系列印象中,总有 Sur ...
- .NETCore 千星项目模块化开发框架 SimplCommerce 详解
SimplCommerce 是 github 上过千星的.netcore 商城示例项目,本文详解他的模块化框架现实思路,其业务(如产品.订单)不作介绍.因作者文笔水平很差,它又很值得学习和推荐,就算不 ...
- 使用Python爬取淘宝两千款套套
各位同学们,好久没写原创技术文章了,最近有些忙,所以进度很慢,给大家道个歉. 警告:本教程仅用作学习交流,请勿用作商业盈利,违者后果自负!如本文有侵犯任何组织集团公司的隐私或利益,请告知联系猪哥删除! ...
- 介绍开源的.net通信框架NetworkComms框架 源码分析
原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架 作者是英国人 以前是收费的 售价249英镑 我曾经花了 ...
- Android Small插件化框架源码分析
Android Small插件化框架源码分析 目录 概述 Small如何使用 插件加载流程 待改进的地方 一.概述 Small是一个写得非常简洁的插件化框架,工程源码位置:https://github ...
- YII框架源码分析(百度PHP大牛创作-原版-无广告无水印)
YII 框架源码分析 百度联盟事业部——黄银锋 目 录 1. 引言 3 1.1.Yii 简介 3 1.2.本文内容与结构 3 2.组件化与模块化 4 2.1.框架加载和运行流程 4 ...
- java fork-join框架应用和分析
http://shmilyaw-hotmail-com.iteye.com/blog/1897636 java fork-join框架应用和分析 博客分类: concurrency multithre ...
- 对比Tornado和Twisted两种异步Python框架
做Python的人,一定知道两个性能优秀的异步网络框架:tornado,和twisted. 那么,这两个著名的框架,又有什么异同呢?tornado和twisted,我都用在几个游戏项目中,做过后端,觉 ...
- Spark RPC框架源码分析(一)简述
Spark RPC系列: Spark RPC框架源码分析(一)运行时序 Spark RPC框架源码分析(二)运行时序 Spark RPC框架源码分析(三)运行时序 一. Spark rpc框架概述 S ...
随机推荐
- mq消息
同步,异步,单向 Message的扩展属性主要包含下面几个: tag:消息tag,用于消息过滤 keys:Message索引键,用多个空格隔开,可以根据这些key快速检索到消息 waitStoreMs ...
- 自学linux——18.FTP服务器的搭建
Centos7下FTP服务器的搭建 一.FTP的作用 文件传输协议(File Transfer Protocol,FTP),是一种在互联网中进行文件传输的协议,基于客户端/服务器模式,默认使用 20. ...
- oracle sql%notfound
SQL%NOTFOUND 是一个布尔值.与最近的sql语句(update,insert,delete,select)发生交互,当最近的一条sql语句没有涉及任何行的时候,则返回true.否则返回fal ...
- MacOS JMeter安装(多图)
本文基于 MacOS 环境下进行 Jmeter 的安装. 一.下载JMeter 本文选用 JMeter 5.3 版本安装,5.3 版本需要 JDK 1.8 + 版本环境. Jmeter 5.3 下载: ...
- Spring Boot系列 八、集成Kafka
一.引入依赖 <dependency> <groupId>org.springframework.kafka</groupId> <artifactId> ...
- python批量definition query
import arcpy mxd = arcpy.mapping.MapDocument("current") for lyr in arcpy.mapping.ListLayer ...
- day1(Django)
1,web项目工作流程 1.1 了解web程序工作流程 1.2 django生命周期 2,django介绍 目的:了解Django框架的作用和特点作用: 简便.快速的开发数据库驱动的网站 Djan ...
- PyQt(Python+Qt)学习随笔:Qt Designer中主窗口对象unifiedTitleAndToolBarOnMac属性
unifiedTitleAndToolBarOnMac 用于确认在mac操作系统上是否使用统一的标题和工具栏外观 有如下几个限制: 1.不支持使用带OpenGl内容的窗口,包括QGLWidget 和 ...
- PyQt(Python+Qt)学习随笔:布局控件layout的LeftMargin等contentsMargins属性
在Qt Designer中布局控件有4个,分别是Vertical Layout(垂直布局).Horizontal Layout(水平布局).Grid Layout(网格布局).Form Layout( ...
- 稀疏矩阵三元组表快速转置(C语言实现)
本来准备昨天下午写的,但是因为去参加360众测靶场的考核耽搁了,靶场的题目还是挺基础的. 继续学习吧. 使用黑色墨水在白纸上签名就像由像素点构成的稀疏矩阵.如图4所示. 图4 手写体签名 [问题]请将 ...