在.NET API开发中,你是否也曾为这些问题头疼?接口返回格式不统一、异常处理代码重复、参数验证错误提示杂乱、Swagger配置繁琐...今天给大家推荐一款专为解决这些痛点而生的工具库——Acme.ReturnOh,一站式搞定API返回值标准化、异常处理、参数验证和Swagger配置,让接口开发更规范、更高效。

一、Acme.ReturnOh 是什么?

Acme.ReturnOh 是面向.NET 8.0+ 框架的通用返回参数处理库,核心目标是标准化API响应格式,同时内置全局异常处理、参数验证和Swagger配置能力,让开发者告别重复的返回值处理代码,专注业务逻辑开发。

核心特性:

  • 🎯 统一响应格式:定义标准化的API返回结构,前后端对接更顺畅

  • 🛡️ 全局异常处理:自动捕获并格式化异常响应,减少try-catch冗余代码

  • ✅ 参数验证:自动处理模型验证错误,返回统一格式的提示信息

  • 📚 一键Swagger:简化Swagger配置,支持多版本、多XML注释文件

  • 🚀 轻量易用:NuGet一键安装,几行代码完成集成,无侵入式设计

支持框架:.NET 8.0 / 9.0 / 10.0

二、5分钟快速上手

1. 安装依赖

dotnet add package Acme.ReturnOh

2. 基础配置(Program.cs)

using Acme.ReturnOh;

var builder = WebApplication.CreateBuilder(args);

// 1. 配置Swagger(可选,推荐配置)
builder.Services.ConfigureSwaggerOptions("我的API文档");

// 2. 配置参数验证自动处理
builder.Services.ConfigureApiBehaviorOptions();

// 3. 配置全局异常过滤器
builder.Services.AddExceptionFilterService();

// 4. 添加MVC核心功能
builder.Services.AddControllers();

var app = builder.Build();

// 开发环境启用Swagger
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseAuthorization();
app.MapControllers();
app.Run();

3. 第一个标准化接口

using Acme.ReturnOh;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    [HttpGet(Name = "GetWeatherForecast")]
    public Oh Get()
    {
        var forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        }).ToArray();
        
        // 标准化成功响应
        return forecasts.Success("天气数据获取成功");
    }
}

此时接口会返回标准化格式:

{
  "Code": 200,
  "Msg": "天气数据获取成功",
  "Data": [/* 天气数据数组 */]
}

三、核心功能详解

1. 标准化响应格式

基础结构

Acme.ReturnOh 定义了两种核心返回类型,满足不同场景需求:

// 通用返回类型
public record Oh(int Code, string Msg, object? Data = null);

// 泛型返回类型(强类型)
public record Oh<TEntity>(int Code, string Msg, TEntity? Data) 
    where TEntity : class, new();
常用响应方法

无需手动new对象,通过扩展方法快速生成响应:

// 成功响应(默认200状态码)
return data.Success(); // 默认消息:"成功!"
return data.Success("用户查询成功"); // 自定义消息

// 失败响应(默认500状态码)
return data.Fail(); // 默认消息:"服务器错误!请联系管理员"
return data.Fail("用户名已存在"); // 自定义失败消息

// 自定义状态码和消息
return data.Custom(403, "权限不足,无法访问");

// 布尔值快速转换
bool isSuccess = _userService.Create(user);
return isSuccess.IsSuccess("创建成功", "创建失败");
泛型强类型返回(推荐)
[HttpGet("{id}")]
public Oh<UserDto> GetUserById(int id)
{
    var user = _userService.GetById(id);
    if (user == null)
    {
        return new Oh<UserDto>(404, "用户不存在", null);
    }
    return user.Success<UserDto>("用户查询成功");
}

2. 全局异常处理

无需手动try-catch,框架自动捕获并格式化异常响应:

异常类型 返回状态码 响应示例
ArgumentException 400 {"Code":400,"Msg":"参数错误:用户名不能为空","Data":null}
SystemException 500 {"Code":500,"Msg":"系统错误:数据库连接失败","Data":null}
其他异常 500 {"Code":500,"Msg":"服务器错误!请联系管理员","Data":null}
手动抛出标准化异常
// 业务逻辑中手动抛出异常
if (string.IsNullOrEmpty(userDto.Username))
{
    Oh<User>.ArgumentException("用户名不能为空");
}

if (dbConnection.State != ConnectionState.Open)
{
    Oh<User>.SystemException("数据库连接失败");
}

3. 自动参数验证

结合ASP.NET Core的模型验证特性,自动处理验证错误:

// 定义验证规则
public class UserDto
{
    [Required(ErrorMessage = "用户名不能为空")]
    public string Username { get; set; }
    
    [Required(ErrorMessage = "密码不能为空")]
    [MinLength(6, ErrorMessage = "密码长度不能少于6位")]
    public string Password { get; set; }
}

// 控制器接口
[HttpPost]
public Oh Create([FromBody] UserDto user)
{
    // 无需手动验证,验证失败会自动返回标准化响应
    return _userService.Create(user).Success("创建成功");
}

验证失败时自动返回:

{
  "Code": 400,
  "Msg": "用户名不能为空;密码长度不能少于6位",
  "Data": null
}

4. 一键Swagger配置

简化Swagger的繁琐配置,支持自定义标题、版本、多XML注释文件:

// 基础配置
builder.Services.ConfigureSwaggerOptions("电商API文档");

// 自定义版本
builder.Services.ConfigureSwaggerOptions("电商API文档", "v2");

// 包含多个XML注释文件(显示实体类、服务层注释)
var xmlFiles = new List<string> { "MyProject.Model", "MyProject.Service" };
builder.Services.ConfigureSwaggerOptions("电商API文档", "v1", xmlFiles);

四、高级用法

1. 自定义异常过滤器

如果默认异常处理逻辑不满足需求,可自定义过滤器:

// 自定义异常过滤器
public class CustomExceptionFilter : Attribute, IAsyncExceptionFilter
{
    public async Task OnExceptionAsync(ExceptionContext context)
    {
        if (context.ExceptionHandled)
            return;
        
        // 自定义异常处理逻辑
        Oh result = context.Exception switch
        {
            BusinessException ex => // 业务异常
                new Oh(400, $"业务异常:{ex.Message}"),
            AuthException ex => // 认证异常
                new Oh(401, $"认证失败:{ex.Message}"),
            _ => // 其他异常
                Oh.Fail($"系统错误:{context.Exception.Message}"),
        };
        
        context.ExceptionHandled = true;
        context.Result = new ObjectResult(result);
        await Task.CompletedTask;
    }
}

// 注册自定义过滤器
builder.Services.AddExceptionFilterService<CustomExceptionFilter>();

2. 内置常量复用

库中内置了常用的响应消息和状态码常量,避免硬编码:

// 常用成功/失败消息
return user.Success(CV.GetYes); // "获取成功"
return result.IsSuccess(CV.InsertYes, CV.InsertNo); // "新增成功"/"新增失败"

// 常用状态码
return data.Custom(CV.YesCode, "操作成功"); // 200
return data.Fail(CV.NoCode, "操作失败"); // 500

完整常量列表:

常量名 用途
CV.Yes "成功!" 通用成功消息
CV.GetYes "获取成功" 查询成功消息
CV.InsertYes "新增成功" 新增成功消息
CV.UpdateYes "更新成功" 更新成功消息
CV.DeleteYes "删除成功" 删除成功消息
CV.YesCode 200 成功状态码
CV.NoCode 500 失败状态码

五、完整实战示例

控制器层完整示例

using Acme.ReturnOh;
using Microsoft.AspNetCore.Mvc;

namespace MyProject.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class UserController : ControllerBase
    {
        private readonly IUserService _userService;

        public UserController(IUserService userService)
        {
            _userService = userService;
        }

        // 查询所有用户
        [HttpGet]
        public Oh GetAll()
        {
            var users = _userService.GetAll();
            return users.Success(CV.GetYes);
        }

        // 根据ID查询用户
        [HttpGet("{id}")]
        public Oh<UserDto> GetById(int id)
        {
            var user = _userService.GetById(id);
            if (user == null)
            {
                return new Oh<UserDto>(404, "用户不存在", null);
            }
            return user.Success<UserDto>(CV.GetYes);
        }

        // 新增用户
        [HttpPost]
        public Oh Create([FromBody] UserDto userDto)
        {
            var result = _userService.Create(userDto);
            return result.IsSuccess(CV.InsertYes, CV.InsertNo);
        }

        // 更新用户
        [HttpPut("{id}")]
        public Oh Update(int id, [FromBody] UserDto userDto)
        {
            var result = _userService.Update(id, userDto);
            return result.IsSuccess(CV.UpdateYes, CV.UpdateNo);
        }

        // 删除用户
        [HttpDelete("{id}")]
        public Oh Delete(int id)
        {
            var result = _userService.Delete(id);
            return result.IsSuccess(CV.DeleteYes, CV.DeleteNo);
        }
    }
}

服务层示例

using Acme.ReturnOh;

public class UserService : IUserService
{
    private readonly List<User> _users = new();

    public List<UserDto> GetAll()
    {
        return _users.Select(u => new UserDto
        {
            Id = u.Id,
            Username = u.Username,
            Email = u.Email
        }).ToList();
    }

    public UserDto GetById(int id)
    {
        var user = _users.FirstOrDefault(u => u.Id == id);
        return user == null ? null : new UserDto
        {
            Id = user.Id,
            Username = user.Username,
            Email = user.Email
        };
    }

    public bool Create(UserDto userDto)
    {
        // 业务验证,失败则抛出标准化异常
        if (string.IsNullOrEmpty(userDto.Username))
        {
            Oh<User>.ArgumentException("用户名不能为空");
        }
        
        if (_users.Any(u => u.Username == userDto.Username))
        {
            Oh<User>.ArgumentException("用户名已存在");
        }
        
        _users.Add(new User
        {
            Id = _users.Count + 1,
            Username = userDto.Username,
            Email = userDto.Email
        });
        
        return true;
    }

    // 其他方法省略...
}

六、常见问题解答

1. 如何修改默认的成功/失败消息?

直接在调用Success/Fail方法时传入自定义消息即可:

// 自定义成功消息
return data.Success("数据查询完成");

// 自定义失败消息
return data.Fail("该记录已被删除,无法操作");

2. 如何添加自定义状态码?

使用Custom方法自定义状态码和消息:

// 403权限不足
return data.Custom(403, "您没有该操作权限");

// 401未认证
return data.Custom(401, "请先登录");

3. Swagger不显示XML注释怎么办?

  1. 右键项目 → 属性 → 生成 → 勾选"生成XML文档文件"

  2. 在ConfigureSwaggerOptions中指定XML文件:

var xmlFiles = new List<string> { "MyProject.Controllers", "MyProject.Models" };
builder.Services.ConfigureSwaggerOptions("API文档", "v1", xmlFiles);

4. 如何禁用全局异常处理?

如果需要自定义异常处理逻辑,可不注册默认过滤器:

// 注释掉默认异常过滤器注册
// builder.Services.AddExceptionFilterService();

// 注册自定义过滤器
builder.Services.AddExceptionFilterService<CustomExceptionFilter>();

七、总结

Acme.ReturnOh 作为一款轻量级的.NET API返回值处理库,核心价值在于标准化提效

  1. 🎯 标准化:统一API响应格式,降低前后端对接成本

  2. 🛠️ 提效:内置异常处理、参数验证、Swagger配置,减少重复代码

  3. 🎨 灵活:支持自定义异常处理、自定义状态码,满足个性化需求

  4. 🚀 易用:几行代码集成,学习成本低,开箱即用

无论是小型项目快速开发,还是中大型项目的接口规范化建设,Acme.ReturnOh 都能显著提升开发效率,让开发者从繁琐的返回值处理中解放出来,专注于核心业务逻辑。

版本历史

  • 1.7.3 - 当前稳定版本

  • 1.7.2 - 修复小问题,优化参数验证提示

  • 1.7.1 - 优化异常处理逻辑,增加泛型返回支持

  • 1.7.0 - 新增泛型返回类型

  • 1.5.0 - 初始版本,核心功能上线

如果你的.NET API项目还在为返回值格式不统一、异常处理繁琐而烦恼,不妨试试Acme.ReturnOh,让接口开发更规范、更高效!

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐