U.NET 项目中的 nified API 响应简化了应用程序之间的通信,强调了软件开发的一致性和清晰度。本文描述了实现统一 API 响应所涉及的优势和过程步骤。
统一 API 响应本质上是 API 端点生成的响应的标准化格式。无论请求的结果如何,响应都遵循统一的结构,通常包含在 Result 对象中。这种统一性提高了清晰度,并简化了开发人员和客户的处理。
首先,我们定义 Error 类,它封装了消息。您可以使用 Implicit Conversion 轻松地从 String 更改为 Error,反之亦然。
public class Error
{
public Error(string message)
{
Message = message;
}
public string Message { get; }
public static Error None => new(string.Empty);
public static implicit operator Error(string message) => new(message);
public static implicit operator string(Error error) => error.Message;
}
这个由 Result 类使用的类将用作响应对象。让我们创建具有两个属性的 Result 类:
public class Result
{
public Result(bool isSuccess, Error error)
{
IsSuccess = isSuccess;
Error = error;
}
public bool IsSuccess { get; }
public Error Error { get; }
public static Result Success() => new(true, Error.None);
public static Result Failure(Error error) => new(false, error);
public static Result<T> Success<T>(T data) => new(true, Error.None, data);
public static Result<T> Failure<T>(Error error) => new(false, error, default);
}
看看这两个非泛型方法,Success 和 Failure:
暂时跳过泛型方法
我现在知道你心中的问题了:
如果响应包含数据,我该怎么办?我看到您指示操作成功或失败。
请保持冷静,不要混淆;现在一切都会清楚的。
如您所见,您可以使用 Result 类返回统一响应,但不返回数据
让我们创建泛型 Result 类包含名为 data 的属性,该属性返回带有 data 的 Result
public class Result<T> : Result
{
public T? Data { get; }
public Result(bool isSuccess, Error error, T? data) : base(isSuccess, error)
{
Data = data;
}
}
在这个类中,你会看到 'Result<T>' 继承自 Result,并包含返回带有 Data 的 Response 的 Data 属性
现在你可以问我:
您有两个 C-Sharp 文件。使用相同的名称,您是怎么做到的?
听着,我不是魔术师,但在构建统一 API 响应时,您可以执行以下操作:
您在此处看到 Generic Result 类,我将其命名为 'ResultT.cs'
这解释了为什么这些泛型方法存在于非泛型 Result 类中。
public static Result<T> Success<T>(T data) => new(true, Error.None, data);
public static Result<T> Failure<T>(Error error) => new(false, error, default);
通过这种方法,我们终止了 Result Object Response,并且 Result 类已准备好使用它。
我不知道您在构建 API 时使用的特定架构模式;但是,它可以在您选择的架构模式中实现。
在上面的项目中,我对 3 层架构进行了模拟
项目施工为:
1- 域层
2- 业务逻辑层
3- 表示层
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
public class UserSamplesList
{
private static List<User> _users = new()
{
new User { Id = 1, Name = "John Doe", Email = "joh@gmail.com"},
new User { Id = 2, Name = "Jane Smith", Email = "jane@gmail.com"},
new User { Id = 3, Name = "Alice Johnson", Email = "alice@gmail.com"},
new User { Id = 4, Name = "Bob Brown", Email = "bob@gmail.com"},
new User { Id = 5, Name = "Emily Davis", Email = "emily@gmail.com"},
new User { Id = 6, Name = "Michael Wilson", Email = "michael@gmail.com"},
new User { Id = 7, Name = "Sophia Taylor", Email = "sophia@gmail.com"},
new User { Id = 8, Name = "James Martinez", Email = "james@gmail.com"},
new User { Id = 9, Name = "Olivia Garcia", Email = "olivia@gmail.com"},
new User { Id = 10, Name = "William Rodriguez", Email = "william@gmail.com"}
};
public static IEnumerable<User> GetUsers()
{
return _users;
}
public static User GetUser(int id)
{
return _users.FirstOrDefault(u => u.Id == id);
}
public static void AddUser(User user)
{
_users.Add(user);
}
public static void UpdateUser(User user)
{
var existingUser = _users.FirstOrDefault(u => u.Id == user.Id);
if (existingUser != null)
{
existingUser.Name = user.Name;
existingUser.Email = user.Email;
}
}
}
Domain Layer 已成功完成。
public interface IUserService
{
Task<Result<IEnumerable<User>>> GetUsersAsync();
Task<Result<User>> GetUserAsync(int id);
Task<Result> CreateUserAsync(User user);
Task<Result> UpdateUserAsync(User user);
}
public class UserService : IUserService
{
public Task<Result> CreateUserAsync(User user)
{
if (user is null)
return Task.FromResult(Result.Failure("User is null"));
UserSamplesList.AddUser(user);
return Task.FromResult(Result.Success());
}
public Task<Result<User>> GetUserAsync(int id)
{
var user = UserSamplesList.GetUser(id);
if (user == null)
{
return Task.FromResult(Result.Failure<User>($"User with id {id} not found"));
}
return Task.FromResult(Result.Success(user));
}
public Task<Result<IEnumerable<User>>> GetUsersAsync()
{
var users = UserSamplesList.GetUsers();
return Task.FromResult(Result.Success(users));
}
public Task<Result> UpdateUserAsync(User user)
{
if (user == null)
{
return Task.FromResult(Result.Failure("User is null"));
}
UserSamplesList.UpdateUser(user);
return Task.FromResult(Result.Success());
}
}
using Microsoft.AspNetCore.Mvc;
using UnifiedApiResponse.Models;
using UnifiedApiResponse.Services;
namespace UnifiedApiResponse.Controllers;
[Route("api/[controller]")]
[ApiController]
public class UserController : ControllerBase
{
private readonly IUserService _userService;
public UserController(IUserService userService)
{
_userService = userService;
}
[HttpGet()]
public async Task<IActionResult> GetUsers()
{
var result = await _userService.GetUsersAsync();
return result.IsSuccess
? Ok(result)
: NotFound(result.Error);
}
[HttpPost]
public async Task<IActionResult> CreateUser(User user)
{
var result = await _userService.CreateUserAsync(user);
return result.IsSuccess
? Ok(result)
: BadRequest(result.Error);
}
}
{
"data": [
{
"id": 1,
"name": "John Doe",
"email": "joh@gmail.com"
},
{
"id": 2,
"name": "Jane Smith",
"email": "jane@gmail.com"
}
],
"isSuccess": true,
"error": {
"message": ""
}
}
{
"isSuccess": false,
"data": null,
"error": "Failed to create user: Email is already in use."
}