让 .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 仅集成了以下两个依赖:

麻雀虽小五脏俱全。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 亮点分析(一)的更多相关文章

  1. .NET Core Community 第四个千星项目诞生:微服务框架 Surging

    本文所有打赏将全数捐赠于 NCC(NCC 的资金目前由 倾竹大人 负责管理),请注明捐赠于 NCC.捐赠情况将由倾竹大人在此处公示. 提及 .NET 微服务,我们脑海中浮现的一系列印象中,总有 Sur ...

  2. .NETCore 千星项目模块化开发框架 SimplCommerce 详解

    SimplCommerce 是 github 上过千星的.netcore 商城示例项目,本文详解他的模块化框架现实思路,其业务(如产品.订单)不作介绍.因作者文笔水平很差,它又很值得学习和推荐,就算不 ...

  3. 使用Python爬取淘宝两千款套套

    各位同学们,好久没写原创技术文章了,最近有些忙,所以进度很慢,给大家道个歉. 警告:本教程仅用作学习交流,请勿用作商业盈利,违者后果自负!如本文有侵犯任何组织集团公司的隐私或利益,请告知联系猪哥删除! ...

  4. 介绍开源的.net通信框架NetworkComms框架 源码分析

    原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架  作者是英国人  以前是收费的 售价249英镑 我曾经花了 ...

  5. Android Small插件化框架源码分析

    Android Small插件化框架源码分析 目录 概述 Small如何使用 插件加载流程 待改进的地方 一.概述 Small是一个写得非常简洁的插件化框架,工程源码位置:https://github ...

  6. YII框架源码分析(百度PHP大牛创作-原版-无广告无水印)

           YII 框架源码分析    百度联盟事业部——黄银锋 目 录 1. 引言 3 1.1.Yii 简介 3 1.2.本文内容与结构 3 2.组件化与模块化 4 2.1.框架加载和运行流程 4 ...

  7. java fork-join框架应用和分析

    http://shmilyaw-hotmail-com.iteye.com/blog/1897636 java fork-join框架应用和分析 博客分类: concurrency multithre ...

  8. 对比Tornado和Twisted两种异步Python框架

    做Python的人,一定知道两个性能优秀的异步网络框架:tornado,和twisted. 那么,这两个著名的框架,又有什么异同呢?tornado和twisted,我都用在几个游戏项目中,做过后端,觉 ...

  9. Spark RPC框架源码分析(一)简述

    Spark RPC系列: Spark RPC框架源码分析(一)运行时序 Spark RPC框架源码分析(二)运行时序 Spark RPC框架源码分析(三)运行时序 一. Spark rpc框架概述 S ...

随机推荐

  1. Mac 安装Homebrew慢的问题解决

    一开始安装,在官网上的命令: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/ma ...

  2. 【鸿蒙开发板试用报告】用OLED板实现FlappyBird小游戏(中)

    小伙伴们久等了,在上一篇<[开发板试用报告]用OLED板实现FlappyBird小游戏(上)>中,我们本着拿来主义的原则,成功的让小鸟在OLED屏幕上自由飞翔起来,下面我们将加入按钮交互功 ...

  3. LeetCode 033 Search in Rotated Sorted Array

    题目要求:Search in Rotated Sorted Array Suppose a sorted array is rotated at some pivot unknown to you b ...

  4. 「考试」CSP-S 2020

    乱扯 爆炸的过程是这样的 写了\(2.5h\)的\(T1\)过不去大样例,自闭了 决定调\(T2\)然后过了样例但事实上写的完全是假的 这个时候突然\(T1\)灵光一闪就没再看\(T2\)了 然后就一 ...

  5. 【2020.12.02提高组模拟】球员(player)

    题目 题目描述 老师们已经知道学生喜欢睡觉,Soaring是这项记录保持者.他只会在吃饭或玩FIFA20时才会醒来.因此,他经常做关于足球的梦,在他最近的一次梦中,他发现自己成了皇家马德里足球俱乐部的 ...

  6. 一文搞懂RESTful API

    RESTful接口实战 原创公众号:bigsai 转载请联系bigsai 文章收藏在回车课堂 前言 在学习RESTful 风格接口之前,即使你不知道它是什么,但你肯定会好奇它能解决什么问题?有什么应用 ...

  7. secret_key伪造session来进行越权

    从swpuctf里面的一道ctf题目来讲解secret_key伪造session来进行越权. 以前没有遇到过这种题目,这次遇到了之后查了一些资料把它做了出来,记录一下知识点. 参考资料 http:// ...

  8. pyinstaller---将py文件打包成exe

    pyinstaller可将Python脚本打包成可执行程序,使在没有Python环境的机器上运行. 1.pyinstaller在windows下的安装 直接在命令行用pip安装 pyinstaller ...

  9. Newbe.ObjectVisitor 0.4.4 发布,模型验证器上线

    Newbe.Claptrap 0.4.4 发布,模型验证器上线. 更新内容 完全基于表达式树的模型验证器 本版本,我们带来了基于表达式树实现的模型验证器.并实现了很多内置的验证方法. 我们罗列了与 F ...

  10. Scrum冲刺_Day01

    一.团队展示: 1.项目:light_note备忘录 2.队名:删库跑路队 3.团队成员 队员(不分先后) 项目角色 黄敦鸿 后端工程师.测试 黄华 后端工程师.测试 黄骏鹏 后端工程师.测试 黄源钦 ...