You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ASP.NET Core Web API中实现Announcement类的多属性非空验证

解决方案:自定义数据验证属性

在ASP.NET Core中,你可以通过自定义验证属性实现"ReceiverUserId、SectionId、RoleId至少一个非空"的规则,让模型绑定阶段自动完成验证,无需在控制器里手动判断。

1. 创建自定义验证属性

新建一个继承自ValidationAttribute的类,重写IsValid方法来检查指定字段是否全为空:

using System.ComponentModel.DataAnnotations;
using System.Reflection;

public class AtLeastOneNonNullAttribute : ValidationAttribute
{
    private readonly string[] _targetProperties;

    public AtLeastOneNonNullAttribute(params string[] propertyNames)
    {
        _targetProperties = propertyNames;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var instance = validationContext.ObjectInstance;
        var type = instance.GetType();

        foreach (var propName in _targetProperties)
        {
            PropertyInfo? prop = type.GetProperty(propName);
            if (prop == null)
            {
                return new ValidationResult($"找不到属性 {propName}");
            }

            var propValue = prop.GetValue(instance);
            if (propValue != null)
            {
                return ValidationResult.Success;
            }
        }

        return new ValidationResult(ErrorMessage ?? "ReceiverUserId、SectionId、RoleId 至少需要填写一个");
    }
}

2. 将验证属性应用到实体类

把[AtLeastOneNonNull]标记添加到Announcement类上,指定要检查的三个字段名:

[AtLeastOneNonNull(nameof(ReceiverUserId), nameof(SectionId), nameof(RoleId))]
public class Announcement
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Detail { get; set; }
    public DateTime Date { get; set; }
    public string? Attachment { get; set; }
    public AppUser Poster { get; set; }
    public string PosterUserId { get; set; }
    public AppUser? Receiver { get; set; }
    public string? ReceiverUserId { get; set; }
    public Section? Section { get; set; }
    public int? SectionId { get; set; }
    public IdentityRole? Role { get; set; }
    public string? RoleId { get; set; }
}

3. 控制器自动处理验证结果

确保你的控制器标记了[ApiController]特性,ASP.NET Core会自动验证模型状态,一旦验证失败,会直接返回400 Bad Request响应并携带错误信息:

[ApiController]
[Route("api/announcements")]
public class AnnouncementsController : ControllerBase
{
    [HttpPost]
    public IActionResult Create([FromBody] Announcement announcement)
    {
        // [ApiController]已自动完成验证,无需手动检查ModelState.IsValid
        // 直接执行业务逻辑,比如保存到数据库
        return Ok("公告创建成功");
    }
}

额外建议:使用DTO分离关注点

不建议直接在数据库实体类上绑定验证规则,更合理的做法是创建数据传输对象(DTO),将验证规则应用到DTO上,再映射到实体类:

[AtLeastOneNonNull(nameof(ReceiverUserId), nameof(SectionId), nameof(RoleId))]
public class CreateAnnouncementDto
{
    public string Title { get; set; }
    public string Detail { get; set; }
    public DateTime Date { get; set; }
    public string? Attachment { get; set; }
    public string? ReceiverUserId { get; set; }
    public int? SectionId { get; set; }
    public string? RoleId { get; set; }
}

控制器接收DTO后再转换为实体:

[HttpPost]
public IActionResult Create([FromBody] CreateAnnouncementDto dto)
{
    var announcement = new Announcement
    {
        Title = dto.Title,
        Detail = dto.Detail,
        Date = dto.Date,
        Attachment = dto.Attachment,
        ReceiverUserId = dto.ReceiverUserId,
        SectionId = dto.SectionId,
        RoleId = dto.RoleId,
        PosterUserId = User.FindFirstValue(ClaimTypes.NameIdentifier)
    };

    // 执行数据库保存操作
    return Ok("公告创建成功");
}

这种方式可以分离API请求的验证规则和数据库实体结构,更符合代码设计原则。

内容的提问来源于stack exchange,提问作者Semir Hamid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 03:42:04