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

.NET Core 如何使用FileValidationAttribute结合DocumentType验证文件类型

问题根因

ASP.NET Core的模型绑定与验证顺序和Dto内属性的定义顺序完全一致。你当前的DocumentUploadDto中File属性定义在DocumentType之前,执行File上的验证特性时,DocumentType还未完成赋值,只能拿到枚举类型的默认值(即第一个定义的BANKSTATEMENT),这就是你始终只能拿到第一个枚举值的原因。

可行解决方案

方案1:调整Dto属性顺序(改造成本最低)

只需要把DocumentType属性移到File属性之前,模型绑定会先赋值DocumentType,再验证File时就能拿到正确的枚举值,原有验证逻辑无需修改:

public class DocumentUploadDto
{
    // 调整到File之前,先完成绑定赋值
    public ApplicationDocumentType DocumentType { get; set; }
    [FileValidation]
    public IFormFile File { get; set; }
    public Guid Id { get; set; }
}

方案2:使用类级验证IValidatableObject(推荐,可维护性最高)

直接让Dto实现IValidatableObject接口,所有属性绑定完成后才会执行Validate方法,无需反射就能直接获取所有属性值,逻辑更清晰:

public class DocumentUploadDto : IValidatableObject
{
    public IFormFile File { get; set; }
    public ApplicationDocumentType DocumentType { get; set; }
    public Guid Id { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (File == null)
        {
            yield return new ValidationResult("No file found.", new[] { nameof(File) });
        }

        // 直接获取DocumentType值,无需反射
        if (DocumentType == ApplicationDocumentType.NRIC 
            && File.ContentType == "application/pdf")
        {
            yield return new ValidationResult(
                "Invalid file type. Pdf file type is not allowed for NRIC.", 
                new[] { nameof(File) }
            );
        }

        // 剩余差异化校验逻辑可以都放在这里
    }
}

方案3:从请求上下文直接获取参数(无需修改Dto结构)

如果不想调整Dto结构,可以在验证特性中通过IHttpContextAccessor直接读取请求提交的DocumentType参数:

  1. 先在Startup/Program.cs中注册服务:
services.AddHttpContextAccessor();
  1. 修改验证特性逻辑:
public class FileValidationAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var file = value as IFormFile;
        if (file == null)
            return new ValidationResult("No file found.");
        
        // 从服务容器获取HttpContext访问器
        var httpAccessor = validationContext.GetService(typeof(IHttpContextAccessor)) as IHttpContextAccessor;
        if (httpAccessor?.HttpContext?.Request.Form.TryGetValue("DocumentType", out var dtStr) == true)
        {
            // 转换为枚举类型
            if (Enum.TryParse<ApplicationDocumentType>(dtStr, out var docType))
            {
                if (docType == ApplicationDocumentType.NRIC && file.ContentType == "application/pdf")
                {
                    return new ValidationResult("Invalid file type. Pdf file type is not allowed for NRIC.");
                }
            }
        }

        // 原有通用校验逻辑
        return ValidationResult.Success;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 02:15:08