Skip to content

Fast.UnifyResult

逐成员 API、参数与返回参考

版本 3.5.33;目标 net8.0net9.0net10.0;依赖 Fast.Runtime。为 MVC 提供统一响应、验证失败处理和友好异常,不自动覆盖任意 Minimal API 返回值。

bash
dotnet add package Fast.UnifyResult

注册与行为

以下为消费端 Program.cs,使用 Microsoft.NET.Sdk.Web,目标选择本页列出的 .NET 8、9 或 10,并安装上方指定包。app.Run() 表示正常宿主启动;本次文档维护不会执行它。

csharp
using Fast.UnifyResult;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddUnifyResult();

var app = builder.Build();
app.MapControllers();
app.Run();
入口作用
AddDataValidation()注册数据验证过滤器;抑制原生 ModelStateInvalidFilter 和非可空引用类型的隐式 Required
AddFriendlyException()注册异常过滤器,发现的 IGlobalExceptionHandler 使用 Singleton
AddUnifyResult()包含前两项,设置 EnabledUnifyHandler,增加成功响应过滤器与状态码处理中间件;返回服务集合

不要因使用 C# 非可空字符串就假定此管道一定自动做 Required 验证;需要的输入约束应明确标注并验证。

响应模型与扩展接口

RestfulResult<T> 的字段为 Success: boolCode: int?Message: objectData: TTimestamp: long。JSON 字段大小写由序列化器设置决定;Code 是包装字段,不能直接等同于当前 HTTP 状态码。

接口 / API合同
IUnifyResultProvider.OnSucceeded(ActionExecutedContext, object)返回成功结果 IActionResult
OnException(ExceptionContext, ExceptionMetadata, int? statusCode = null, string message = null)返回异常结果 IActionResult
OnValidateFailed(ActionExecutingContext, ValidationMetadata)返回验证失败结果 IActionResult
OnResponseStatusCodes(HttpContext, int statusCode)异步处理响应状态码,返回 Task
IUnifyResponseProvider.ResponseDataAsync接收时间戳、数据、上下文,返回 Task<object>
ResponseExceptionAsync返回 (int statusCode, string message) 的任务
ResponseValidationExceptionAsync验证失败扩展处理,返回 Task
IGlobalExceptionHandler全局异常扩展点,按发现的实现注册
NonUnifyAttribute / NonValidationAttribute选择性跳过对应包装/验证流程
ExceptionMetadata / ValidationMetadata异常和验证处理元数据
UnifyContext.HandleRestfulStatusCode/GetRestfulResult创建框架包装结果;EnabledUnifyHandler 是共享状态
BadPageResult状态码结果类型

自定义 Provider 通过框架类型扫描发现;未找到 IUnifyResultProvider 时使用默认 RestfulResultProvider。Provider 注册为 Singleton,不应持有某一次请求的状态。文件/流及已处理响应需要遵循过滤器排除逻辑,不能在业务返回值外再次无条件包一层。

MVC 成功结果与模型验证

在上方 Program.cs 注册与映射控制器后,把下面的类加入同一个 Web 项目。请求示例是 POST /api/notes,JSON 为 { "title": "示例" }

csharp
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/notes")]
public sealed class NotesController : ControllerBase
{
    [HttpPost]
    public NoteOutput Preview([FromBody] NoteInput input) => new(input.Title.Trim());
}

public sealed class NoteInput
{
    [Required, StringLength(80, MinimumLength = 1)]
    public string Title { get; set; } = "";
}

public sealed record NoteOutput(string Title);

控制器返回业务对象,成功过滤器再交给响应 Provider 处理;不要在业务方法中再次手工包装同一响应。缺失或超长 Title 触发模型验证,实际错误结构由注册的验证与统一结果流程决定。示例没有数据库写入。自定义 IUnifyResultProvider / IUnifyResponseProvider 会改变最终协议,因此这里不硬编码所有应用相同的响应 JSON。Minimal API 的 MapGet 返回值不自动等价于 MVC 过滤器结果。

来源与验证

依据 注册结果 Provider 合同。本轮未编译示例或执行成功、验证失败、异常、文件响应的 HTTP 用例。