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

ASP.NET Core Web API:如何使用Fluent Validation验证start_date与end_date的格式为yyyy-MM-dd

ASP.NET Core Web API:如何使用Fluent Validation验证start_date与end_date的格式为yyyy-MM-dd

我理解你现在的需求——已经用Fluent Validation完成了基本的非空校验和日期大小比较,现在要额外确保start_date和end_date必须严格遵循yyyy-MM-dd的格式。这里给你两种实用的解决方案,你可以根据项目情况选择:

方案一:保持现有DateTime模型,校验原始输入格式

如果不想修改现有模型结构,我们可以通过验证上下文获取原始请求中的日期字符串,来做严格的格式校验:

步骤1:更新验证器

修改EmployeeHistoryRequestValidator,为日期字段添加自定义格式校验规则:

using System.Globalization;
using FluentValidation;

public class EmployeeHistoryRequestValidator : AbstractValidator<EmployeeHistoryRequest>
{
    public EmployeeHistoryRequestValidator()
    {
        // 原有员工编码校验规则
        RuleFor(p => p.employee_code)
            .NotNull().WithMessage("Employee Code cannot be null")
            .NotEmpty().WithMessage("Employee Code field is required. ERROR!");

        // 开始日期校验:非空 + 格式验证
        RuleFor(p => p.start_date)
            .NotNull().WithMessage("Start Date cannot be null")
            .Must((model, startDate, context) =>
            {
                // 从上下文获取原始请求中的start_date字符串
                if (context.RootContextData.TryGetValue("start_date", out var rawValue) && rawValue is string rawDate)
                {
                    // 严格匹配yyyy-MM-dd格式
                    return DateTime.TryParseExact(rawDate, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out _);
                }
                // 无法获取原始值则视为格式不合法
                return false;
            })
            .WithMessage("Start Date must be in the format yyyy-MM-dd (e.g., 2019-08-24)");

        // 结束日期校验:和开始日期逻辑一致
        RuleFor(p => p.end_date)
            .NotNull().WithMessage("End Date cannot be null")
            .Must((model, endDate, context) =>
            {
                if (context.RootContextData.TryGetValue("end_date", out var rawValue) && rawValue is string rawDate)
                {
                    return DateTime.TryParseExact(rawDate, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out _);
                }
                return false;
            })
            .WithMessage("End Date must be in the format yyyy-MM-dd (e.g., 2019-08-24)");

        // 原有日期大小比较规则
        RuleFor(x => x)
            .Must(x => x.end_date > x.start_date)
            .WithMessage("End Date must be greater than Start Date");
    }
}

步骤2:在Controller中传递原始请求数据

在处理请求的Action里,需要把原始请求中的日期字符串传递给验证上下文:

using Microsoft.AspNetCore.Mvc;
using System.Text.Json;

[ApiController]
[Route("api/[controller]")]
public class EmployeeController : ControllerBase
{
    [HttpPost("history")]
    public async Task<IActionResult> SubmitEmployeeHistory([FromBody] EmployeeHistoryRequest request)
    {
        // 读取原始请求的JSON数据
        var rawRequest = await JsonSerializer.DeserializeAsync<dynamic>(HttpContext.Request.Body);
        
        // 创建验证上下文并传入原始日期值
        var validationContext = new ValidationContext<EmployeeHistoryRequest>(request);
        validationContext.RootContextData["start_date"] = rawRequest.start_date;
        validationContext.RootContextData["end_date"] = rawRequest.end_date;

        // 执行验证
        var validator = new EmployeeHistoryRequestValidator();
        var validationResult = validator.Validate(validationContext);

        if (!validationResult.IsValid)
        {
            return BadRequest(validationResult.Errors);
        }

        // 后续调用第三方API的业务逻辑
        return Ok("Request validated successfully");
    }
}

方案二:将模型日期属性改为string,直接校验格式(更简洁)

如果允许调整模型结构,这种方案会更直观——把日期属性改为string类型,先验证格式,再转换为DateTime供后续使用:

步骤1:修改模型

using System.Globalization;

public class EmployeeHistoryRequest
{
    public string employee_code { get; set; }
    public string start_date { get; set; }
    public string end_date { get; set; }

    // 提供转换后的DateTime属性,方便业务逻辑使用
    public DateTime StartDate => DateTime.ParseExact(start_date, "yyyy-MM-dd", CultureInfo.InvariantCulture);
    public DateTime EndDate => DateTime.ParseExact(end_date, "yyyy-MM-dd", CultureInfo.InvariantCulture);
}

步骤2:更新验证器

using System.Globalization;
using FluentValidation;

public class EmployeeHistoryRequestValidator : AbstractValidator<EmployeeHistoryRequest>
{
    public EmployeeHistoryRequestValidator()
    {
        RuleFor(p => p.employee_code)
            .NotNull().WithMessage("Employee Code cannot be null")
            .NotEmpty().WithMessage("Employee Code field is required. ERROR!");

        // 开始日期校验:非空 + 正则格式匹配 + 有效日期验证
        RuleFor(p => p.start_date)
            .NotNull().WithMessage("Start Date cannot be null")
            .NotEmpty().WithMessage("Start Date should not be empty. ERROR!")
            .Matches(@"^\d{4}-\d{2}-\d{2}$").WithMessage("Start Date must be in the format yyyy-MM-dd")
            .Must(dateStr => DateTime.TryParseExact(dateStr, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out _))
            .WithMessage("Start Date is not a valid date (e.g., 2019-08-24 is valid, 2019-13-01 is invalid)");

        // 结束日期校验:和开始日期逻辑一致
        RuleFor(p => p.end_date)
            .NotNull().WithMessage("End Date cannot be null")
            .NotEmpty().WithMessage("End Date should not be empty. ERROR!")
            .Matches(@"^\d{4}-\d{2}-\d{2}$").WithMessage("End Date must be in the format yyyy-MM-dd")
            .Must(dateStr => DateTime.TryParseExact(dateStr, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out _))
            .WithMessage("End Date is not a valid date (e.g., 2019-08-24 is valid, 2019-13-01 is invalid)");

        // 日期大小比较:转换为DateTime后判断
        RuleFor(x => x)
            .Must(x => 
            {
                DateTime.TryParseExact(x.start_date, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var start);
                DateTime.TryParseExact(x.end_date, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var end);
                return end > start;
            })
            .WithMessage("End Date must be greater than Start Date");
    }
}

这种方案不需要额外处理原始请求,验证逻辑更清晰,推荐在可以修改模型的场景下使用。

备注:内容来源于stack exchange,提问作者Ayobamilaye

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 10:38:01