v2 版本(归档) - 更新日志
Furion 框架升级/发版规则
升级前重点关注可能造成【破坏性】的标签类型:、、、
版本号规则:主版本号.次版本号.修订版本号.迭代版本号
- 只要【确认】为框架
bug,则当天修复,当天发版,修订版本号加 1。 - 只要
.NET SDK版本更新,则当天升级,当天发版,修订版本号加 1。 - 如果
.csproj文件有变更,则当天发版,修订版本号加 1。 - 如果新增
扩展包,为了版本号统一,则当天发版,修订版本号加 1。 - 如果涉及到代码重构,则当天发版,次版本号
加 1,修订版本号清 0。 - 如果
.NET SDK主版本号升级,则当天发版,主版本号加 1。
如有意外不能当天发版,则会在 Issue 中说明具体发版时间,正常不会超过 3 天。
v2.20(已发布,全新事件总线)
v2.20+ 版本说明
在 Furion v2.20+ 版本后采用 Jaina 事件总线替换原有的 EventBus
- 新特性
- 远程请求支持
GET请求自动转换类类型类型对象 #I4HR5Q
- 远程请求支持
- 突破性变化
-
EventBus模块,采用 Jaina 方式
-
- 问题修复
- 开启规范化结果并自定义全局异常导致异常经过
OnSucceeded过滤器 bug #I4DTVL -
.NET5.0.5+微软底层修改了[ApiController]验证失败返回IActionResult类型 #I4ISOK - 远程请求上传文件异常 0c0752
- 框架启动不支持环境变量
ASPNETCORE_HOSTINGSTARTUPASSEMBLIES配置 !438 - 定时任务内存和 CPU 占用及特殊情况下空异常问题 12c65de
- 默认控制器启用规范化结果无效 bugc7a4a5e
- 依赖注入
InjectionAttribute特性的ExceptInterfaces单词拼写错误问题 !436 -
Sql命令参数传入Clay类型异常问题 #I4D21Q
- 开启规范化结果并自定义全局异常导致异常经过
- 其他更改
- 文档
- 事件总线新文档
v2.19(已发布)
- 新特性
- 问题修复
-
Scoped.Create在EFCore进行Add-Migration时候报空异常问题,原因是在PM环境中不存在根服务0853e74 - 定时任务执行异常后异常一直驻留内存问题,修正为执行成功自动清空过去异常 197a62b
-
Jwt扩展包不正确的代码导致 IOptions 失效#I46LUP -
Swagger枚举Schema过滤器不输出值问题 #I46LON !404 -
Swagger处理非int类型枚举转换 bug #I46QJ9 - 视图引擎编译模板生成
dll后再次加载出现IL格式化错误问题 ff52d38 - 管道
Channel读取器无法释放Handler对象问题 10f4a90 -
Worker Services下日志不输出问题 c482548 - 远程请求
multipart/form-data类型对接微信小程序上传文件 问题 d9bad03 - 工作单元上下文在某些情况下共享事务失效问题 006d439
-
Swagger枚举值在GET请求中Schema显示不正确问题 fb72fd7 - 远程请求
404不走异常过滤器问题 !426 - 自定义事件总线并发情况下调用完成后无法正确处理队列数据 !429
-
v2.19+版本之后模块化开发加载外部程序集失效问题 !433 - 定时任务 SpareTime 频繁检查导致 CPU 增高问题 aa0a2ee
-
- 特别鸣谢
v2.18(已发布)
- 新特性
- 突破性变化
在过去,很多开发者总是喜欢在
Startup.cs配置服务的ConfigureService方法中解析服务,这样导致内存存在溢出风险,GC 无法回收。 正确的方式是尽可能的避免ConfigureService中解析服务。如果需要在【启动时】获取配置选项,请使用App.GetConfig<TOptions>(路径, true)代替App.GetOptions<TOption>。
- 问题修复
- 文档
- 包管理工具文档
- 模板引擎、
Sql操作,数据库上下文等等文档
v2.17(已发布)
- 新特性
- 突破性变化
- 问题修复
- 其他更改
- Swagger 生成泛型 SchemaIds 默认连接符,由
Of改为_81946b6
- Swagger 生成泛型 SchemaIds 默认连接符,由
v2.16(已发布)
- 新特性
- 突破性变化
查看变化
新版本自定义规范化结果
using Furion.DataValidation;
using Furion.DependencyInjection;
using Furion.UnifyResult.Internal;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Threading.Tasks;
namespace Furion.UnifyResult
{
/// <summary>
/// RESTful 风格返回值
/// </summary>
[SuppressSniffer, UnifyModel(typeof(RESTfulResult<>))]
public class RESTfulResultProvider : IUnifyResultProvider
{
/// <summary>
/// 异常返回值
/// </summary>
/// <param name="context"></param>
/// <param name="metadata"></param>
/// <returns></returns>
public IActionResult OnException(ExceptionContext context, ExceptionMetadata metadata)
{
return new JsonResult(RESTfulResult(metadata.StatusCode, errors: metadata.Errors));
}
/// <summary>
/// 成功返回值
/// </summary>
/// <param name="context"></param>
/// <param name="data"></param>
/// <returns></returns>
public IActionResult OnSucceeded(ActionExecutedContext context, object data)
{
return new JsonResult(RESTfulResult(StatusCodes.Status200OK, true, data));
}
/// <summary>
/// 验证失败返回值
/// </summary>
/// <param name="context"></param>
/// <param name="metadata"></param>
/// <returns></returns>
public IActionResult OnValidateFailed(ActionExecutingContext context, ValidationMetadata metadata)
{
return new JsonResult(RESTfulResult(StatusCodes.Status400BadRequest, errors: metadata.ValidationResult));
}
/// <summary>
/// 特定状态码返回值
/// </summary>
/// <param name="context"></param>
/// <param name="statusCode"></param>
/// <param name="unifyResultSettings"></param>
/// <returns></returns>
public async Task OnResponseStatusCodes(HttpContext context, int statusCode, UnifyResultSettingsOptions unifyResultSettings)
{
// 设置响应状态码
UnifyContext.SetResponseStatusCodes(context, statusCode, unifyResultSettings);
switch (statusCode)
{
// 处理 401 状态码
case StatusCodes.Status401Unauthorized:
await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, errors: "401 Unauthorized")
, App.GetOptions<JsonOptions>()?.JsonSerializerOptions);
break;
// 处理 403 状态码
case StatusCodes.Status403Forbidden:
await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, errors: "403 Forbidden")
, App.GetOptions<JsonOptions>()?.JsonSerializerOptions);
break;
default: break;
}
}
/// <summary>
/// 返回 RESTful 风格结果集
/// </summary>
/// <param name="statusCode"></param>
/// <param name="succeeded"></param>
/// <param name="data"></param>
/// <param name="errors"></param>
/// <returns></returns>
private static RESTfulResult<object> RESTfulResult(int statusCode, bool succeeded = default, object data = default, object errors = default)
{
return new RESTfulResult<object>
{
StatusCode = statusCode,
Succeeded = succeeded,
Data = data,
Errors = errors,
Extras = UnifyContext.Take(),
Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
};
}
}
}
- 问题修复
-
MVC控制器启用规范化处理后返回new Json({})对象为null问题 #I4354S
-
- 其他更改
- 多语言底层设计,取消需要创建
Lang.cs空类的要求 #I434YJ -
MiniProfiler性能,减少不必要的监听
- 多语言底层设计,取消需要创建
v2.15(已发布)
- 新特性
- 问题修复
- 其他更改
- 系统启动性能,从 106M 减少到 84M
- 大量底层代码,包大小从 391Kb 减少到 350Kb(不带注释版本仅 64Kb)
v2.13/v2.14(已发布)
- 新特性
- 突破性变化
- 问题修复
- 其他更改
v2.10/2.11/2.12 (已发布)
该版本有多个破坏性更改,更新时请认真查看。
- 新特性
-
App.Configuration.Reload()扩展 #I3XYI8 -
ISubscribeHandler支持异步方法定义 #I3XYHJ -
app.UseUnifyResultStatusCodes()可配置修改返回状态码 #I3VZQH - 远程请求添加默认
User-Agent头 #I3W17C - 支持
Sql高级代理切换数据库上下文定位器 #I3XFP6 #I3XDCR - 定时任务
CronFormat自动识别 #I3Y7GT -
Sql 高级代理拦截功能 #I3YHG4 - 拦截远程请求所有异常处理 #I3YPDE
- 远程请求配置
Timeout超时时间 #I3YPPK -
RSA加密算法 #I3YZNU !345 -
DataTable和DataSet支持不指定强类型返回 #I3Z6RI -
Sql字符串扩展方法设置Timeout超时时间 #I3ZKWF -
Sql高级代理[Timeout]特性,设置超时时间 #I3ZKWF
-
- 突破性变化
-
FakeDelete假删除/软删除所有功能 #I3XKII -
PBKDF2加密算法 #I3Z0IO - 远程请求设置超时时间单位由
分钟改为秒#I3YPPK -
IJsonSerializerProvider接口参数,新增inherit参数 #I3ZQU5 -
[NonAutomatic]特性名称为[Manual]#I3XKKX -
[NotChangedListener]特性名称为[SuppressChangedListener]#I3XKLZ -
[ManualSaveChanges]名称为[ManualCommit]#I3XKNP -
DbContext.TenantIdQueryFilterExpression名称为DbContext.BuildTenantQueryFilter#I3XKTB -
[SkipScan]名称为[SuppressSniffer]#I3XN5N -
[SkipProxy]名称为[SuppressProxy]#I3XN7O -
Sql执行,性能提升 20% #I3W33U
-
- 问题修复
- 动态 WebAPI 扫描控制器没有屏蔽没有注册的第三方控制器 #I3Y7TJ
-
AppDbContext设置TablePrefix无效: #I3Y57Q - 定时任务使用异步委托导致程序终止 bug #I3XVZ0
- 事件总线一个
消息id对应多个Handler只触发第一个#I3XYP0 -
.ToPagedList()分页方法传入小于或等于 0 的页码 #I3XNAN -
JSON序列化默认DateTimeOffset异常 #I3XMOL - 继承
Serilog日志在Worker Service生成重复日志 bug #I3WA0L !331 -
粘土对象动态添加Clay类型 bug #I3W9LW -
ValidationTypes.Numeric校验数值类型正则表达式错误 #I3WADS - 数据库命令参数
DbParameter的Value是object类型的时候且不指定 #I3YKM6 -
Oracle数据库存储过程游标参数报错问题 #I3ZBYE -
Worker Services采用独立发布后无法执行问题 #I3ZH3X - 远程请求如果无返回值序列化异常问题 !348
- 其他更改
- 文档变化
- 问答答疑
-
dapper多个数据源如何继承 #I3WUOI - 关于
SpareTime多次执行问题#I3XEQU - 选项更改通知(热更新):数据库里的数据更改了如何通知选项进行改变? #I3XYI8
-
SaaS多租户添加时无法获取租户Id#I3Y5CF - 获取
_httpContextAccessor.HttpContext为空#I3Y6BI -
Ubuntu中使用App.Configuration方法读取不到值 #I3Y74H - 数据库上下文作用域问题 #I3YHXP
- 使用
UnitofWork提交事务,可以提交成功,但是系统会有错误 #I3YIWU - 数据库读写分离--非默认主库的从库随机该如何配置? #I3YVR7
-
v2.9.0 (已发布)
- 新特性
- 突破性变化
- 问题修复
- 其他更改
- 运行时内存,实现请求结束自动释放未托管资源 #I3VXAU
- 文档变化
-
App静态类文档、远程请求文档、分表分库文档
-
- 问答答疑
- 动态 WebAPI,自定义根据方法名生成 [HttpMethod] 规则报错 #I3VKQG
-
InsertAsync的时候提示ID为空 #I3VS7E -
FirstOrDefault自动过滤了TanantId字段 #I3W0VH - 对方接口返回
HttpConnectionResponseContent远程请求拿不到返回值 #I3W17C - 查询方法
FindOrDefault报错 #I3W830 -
SqlNonQuery在UnitOfWork循环执行#I3W8WW - 因
Swagger配置问题,导致Swagger中不能自动携带 token 授权的问题 #I3W934 - 远程请求
SetBody参数识别不了#I3WBM1 -
Scoped.Create里执行sql.SqlNonQuery()或者obj.insert()问题#I3WB5O - 调用函数或存储过程,怎么出参数据自定义对象?如
Oracle数据库的数组或记录 #I3W71W
v2.7.0/2.8.0 (已发布)
- 新特性
-
throw Oops.On("异常消息")应用多语言支持 #I3UYC2 -
Db.GetMSRepository()获取主从库仓储静态方法 #I3UBSJ - 工作单元特性,支持静态类强制性开启共享事务 #I3S9N8
-
EFCore执行sql模式打印日志 #I3SE8X - 远程请求支持默认
HttpClient配置 #I3SI17 -
短 ID生成功能 #I3T7JP -
[SensitiveDetection]支持配置替换敏感词汇 #I3THIA -
SpecificationDocumentBuilder.DocumentGroups和SpecificationDocumentBuilder.CheckApiDescriptionInCurrentGroup(currentGroup, apiDescription)公开方法#I3UDSY
-
- 突破性变化
- 问题修复
-
[DataValidation]和[SensitiveDetection]多语言应用失效 #I3UH6U -
Scoped系列方法异步出现Task is cancel情况 #I3SJF6 -
Mysql数据库的ToPagedList方法返回的结果进行遍历出现MySqlConnection is aleady use问题 #I3SJQ3 -
tool/cli.psl没有包含项目名称 #I3S1T6 - 远程请求做上传文件时,没有传入
Body,程序直接跳过 #I3TKFH - 远程请求
multipart/form-data内容分割符缺失 #I3TNO9 - 远程请求代理拦截方式返回
HttpResponseMessage问题 #I3V161 -
repository.Database.SetCommandTimeout(600)无法生效#I3VAQS
-
- 其他更改
- 文档变化
- 问答答疑
- 默认
MasterDbContextLocator不随自定义的参数生成 #I3SDBB - 事件总线中订阅处理程序类获取不到用户信息,这个正常吗 #I3SS0U
- 在有多租户过滤器的情况下,是否有一种方式查询全量的数据 #I3T0VI
- mysql 使用
&"tools/cli.ps1"页面化加载表结构失败 #I3T4F8 - 其他 Web 层的 Startup 优先执行 #I3T8IP
- 辅助角色服务实现建议 #I3T906
- 开启
easy connection后同一内网地址浏览器可以正常访问,远程请求则无法访问#I3TA2U -
scope.ServiceProvider.GetService<IOtherService>不存在 #I3TQMV - 能否在 WPF 项目中使用呢? #I3TMCC
-
Dapper多个数据源 #I3TM9B -
L.GetSelectCulture()方法异常 #I3TQS4 - 循环中使用
IDGen.NextID()得到的结果并不是连续的 #I3UAF6 - 模块化动态加载插件支持通配符匹配.dll #I3UDT8
-
MVC模式,在Controller里快捷方式创建View页面出错 #I3UFGB - 数据库迁移没有种子数据 #I3UI7G
-
SpareTimeAttribute中 根据 Cron 表达式 自动匹配 Cron 表达式格式化方式 #I3UTKQ - 使用
workService集成SqlSugar报错 #I3V8HJ -
sqlserver 2008分页报错如何解决呢 #I3VF96
- 默认
v2.5.0/2.6.0 (已发布)
- 新特性
- 突破性变化
- 问题修复
- 远程调用方法错误,请求报文头
Headers不能添加到IHttpDispatchProxy的子接口上 #I3RAF7
- 远程调用方法错误,请求报文头
- 其他更改
- 应用启动性能,减少内存分配
- 文档变化
- 问答答疑
- 关于
Furion集群部署 #I3R3J4 - 升级最新框架以后, 数据库生成模型报错 #I3R7TP
- 数据库上下文事务执行中,
SaveNow执行后有警告 #I3RAJI -
Hangfire使用事务出现错误 #I3ROQ5 - 如何实现 cli 不执行某些表的迁移,web 请求可以正常操作呢? #I3ROU5
- 在使用定时任务时候出现的问题:继承
ISpareTimeWorker#I3RRZS -
MySql时间差 8 小时处理 #I3RSCO -
Db.GetRepository<>方法结合[UnitOfWork]后不可用 #I3RUK5 - 事务开启失败问题 #I3RYJY
- 支持
DbProvider可动态配置 #I3RYPE -
WorkService依赖注入ISingleton问题 #I3RZ1L -
ISpareTimeWorker运行期动态修改 #I3S33Q
- 关于
v2.4.0 (已发布)
- 新特性
- 突破性变化
- .NET 5 SDK 为 5.0.6 版本
-
IJsonSerializerProvider.GetSerializerOptions()接口方法 #I3QIJN
- 问题修复
- 其他更改
-
Furion框架底层性能,减少内存占用,提高应用初始化速度 92f8cc1
-
- 文档变化
- JSON 序列化文档、规范化结果文档、数据库上下文文档
- 问答答疑
-
InsertOrUpdateNowAsync报错 #I3QKO5
-
v2.3.0 (已发布)
v2.2.0 (已发布)
- 新特性
- 突破性变化
- 问题修复
- 其他更改
- 文档变化
- 粘土对象文档 #I3OG18
- 问答答疑
v2.1.0 (已发布)
- 新特性
- 突破性变化
- 问题修复
- 其他更改
- 支持应用启动的时候迁移种子数据 #I3NH3M
- 文档变化
- 问答答疑
v2.0.0 (已发布)
- 新特性
- 控制台应用程序及 Worker Services 支持 #I3K4DG
- 完整任务调度功能 #I3IRUX
-
Cron表达式解析 #I3IQ9Y - 支持
Swagger自定义配置swagger.json地址模板 #I3IHMX - 支持配置动态 WebApi 区域 #I3IJAZ
- 远程请求新增支持传入服务提供器
IServiceProvider#I3IVBL - 全局配置选型
SupportPackageNamePrefixs配置,支持配置包前缀 #I3K0SN - 应用启动时支持
referenceassembly类型程序集扫描 #I3K0SN - 依赖注入
AOP拦截获取方法真实特性 #I3LZBX - EFCore 手动
SaveChanges()特性 #I3N01Y - 支持
Cors跨域更多配置 #I3N2J0
- 突破性变化
- 问题修复
- 关闭
InjectMiniProfiler参数后内存缓存无效 #I3IHLR - 在多租户中调用
Tenant属性出现偶然性数据库上下文被释放的情况 #I3IC70 - Sql 代理中如果返回基元类型抛出不能将 object 转换成对应类型的异常 #I3IC84
- 存储过程多返回值的时候,outputvalues 的 name 不是定义的 MSG 的 name,是 Msg 类型。 #I3IC7Y
- PhoneNumber 手机号验证正则表达式错误 #I3ID10
- 依赖注入 AOP 拦截无法捕获内部异常 #I3IGCC
- 全局拦截标记异常已被处理后异常过滤器依然执行 #I3J463
- 自定义全局异常拦截器不起作用 #I3K1SJ
- 在 WorkerService 模式下,还是使用 WebHostEnvironment 来判断 Host 环境,会导致错误 #I3LCQY
- 定时任务
DoOnce抛空异常 bug #I3M0ZT
- 关闭
- 其他更改
- 文档变化
- 问答答疑
- 数据校验,自定义 ErrorMessage 无效问题 #I3ICL3
- 最新 issue 中新增的“新增常用的 JSON 序列化方法” 会导致 AOP 拦截异常 #I3I7VE
- Furion.DatabaseAccessor.PrivateEntityBase 中的 TenantId 数据类型设置为 object #I3IQV6
- 有关异常拦截和处理的疑问 #I3IUFZ
-
DataValidation在空值的情况下被忽略掉了#I3IWSM - 日志文档没有更新 #I3J1DX
- 对于 webapi 简单类型参数,是否可以以 json 方式提交 #I3J18I
-
IUnifyResultProvider实现中如果UnifyModel的 type 不是范型会报错 #I3JBXF - 如何模块化开发新功能? #I3J7ZZ
- 建议增加微服务中间件的集成 #I3JTZQ
- 二级虚拟目录部署的 swagger 的 MiniProfiler js 报错 #I3IWLR