.NET 8中如何在服务层收集并返回多个验证错误而非抛出异常?
.NET 8中如何在服务层收集并返回多个验证错误而非抛出异常?
嘿,我完全懂你想要的效果——就像用FluentValidation处理DTO那样,把所有验证问题一次性攒起来返回给前端,而不是遇到一个错误就抛出异常打断整个流程对吧?在.NET 8里我们可以通过自定义验证结果结构,或者复用FluentValidation的思路来实现,下面给你具体的方案:
方案一:自定义验证结果类,手动收集服务层验证错误
首先我们可以定义一个简单的验证结果类,用来承载所有错误信息:
public class ServiceValidationResult { // 存储所有验证错误的集合 public List<string> Errors { get; } = new List<string>(); // 快速判断是否验证通过 public bool IsValid => Errors.Count == 0; // 添加错误的方法 public void AddError(string errorMessage) { Errors.Add(errorMessage); } }
接下来改造你的服务层逻辑,不再抛出异常,而是把错误添加到这个结果类里:
// 假设这是你的服务方法 public ServiceValidationResult ProcessCustomerData(Customer customer) { var validationResult = new ServiceValidationResult(); // 原来的抛异常逻辑改成添加错误 if (!hasAnyPhoneNumber) { validationResult.AddError(MessageHelper.GetMessage(ErrorMessageName.NOT_EMPTY)); } // 你可以继续添加其他业务验证逻辑,所有错误都会被收集 if (string.IsNullOrWhiteSpace(customer.FullName)) { validationResult.AddError("客户姓名不能为空"); } if (!IsValidCustomerType(customer.Type)) { validationResult.AddError("客户类型选择无效"); } return validationResult; }
然后在调用服务的上层(比如API控制器),根据验证结果做处理:
[HttpPost] public IActionResult CreateCustomer(CustomerCreateDto dto) { var customer = _mapper.Map<Customer>(dto); var validationResult = _customerService.ProcessCustomerData(customer); if (!validationResult.IsValid) { // 把错误集合返回给前端,格式可以根据需求调整 return BadRequest(new { Code = "VALIDATION_FAILED", Errors = validationResult.Errors }); } // 验证通过,执行后续业务逻辑 _customerService.SaveCustomer(customer); return Ok(new { Message = "客户创建成功" }); }
方案二:复用FluentValidation处理服务层业务验证
如果你的项目已经在使用FluentValidation处理DTO验证,那可以把这套逻辑延伸到服务层的领域对象验证上,保持风格一致。
首先为你的领域对象创建验证器:
public class CustomerValidator : AbstractValidator<Customer> { public CustomerValidator() { // 基础字段验证 RuleFor(c => c.PhoneNumber) .NotEmpty() .WithMessage(MessageHelper.GetMessage(ErrorMessageName.NOT_EMPTY)); RuleFor(c => c.FullName) .NotEmpty() .WithMessage("客户姓名不能为空"); // 还可以添加依赖数据库的业务验证,比如检查手机号是否已存在 RuleFor(c => c.PhoneNumber) .MustAsync(async (phone, cancellation) => await _customerRepo.IsPhoneUniqueAsync(phone)) .WithMessage("该手机号已被注册"); } }
然后在服务层注入这个验证器,调用验证方法并转换为我们需要的结果:
private readonly CustomerValidator _customerValidator; public CustomerService(CustomerValidator customerValidator) { _customerValidator = customerValidator; } public async Task<ServiceValidationResult> ValidateCustomer(Customer customer) { var fluentResult = await _customerValidator.ValidateAsync(customer); var serviceResult = new ServiceValidationResult(); foreach (var error in fluentResult.Errors) { serviceResult.AddError(error.ErrorMessage); } return serviceResult; }
这样不管是DTO还是服务层的领域对象,都用同一种验证方式,维护起来更方便。
小提示
- 服务层返回验证结果后,上层调用方一定要主动检查
IsValid状态,不要忽略验证结果直接执行业务逻辑。 - 对于复杂的跨字段业务验证,也可以放到验证逻辑里,只要把错误信息添加到结果集合即可,不需要抛出异常。
内容来源于stack exchange
相关产品推荐
相关产品推荐

