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

ASP.NET Core Web API中如何在自定义验证器中获取路由参数?

解决自定义模型验证器在PUT端点中使用数据库原始日期的问题

要解决PUT端点中需从数据库获取原始StartDate进行验证的问题,我们可以在自定义ValidationAttribute中通过HttpContext获取路由参数,并注入数据库服务查询原始数据,同时区分POST和PUT场景处理比较逻辑,完全符合模型层验证的要求。

实现步骤及代码修改

  1. 修改自定义验证属性
    更新DateGreaterThanAttribute,添加获取路由参数、查询数据库原始数据的逻辑:
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.Reflection;

public class Contract
{
    [JsonPropertyName("StartDate")]
    public DateTime StartDate { get; set; }

    [DateGreaterThan("StartDate", ErrorMessage = "EndDate must be greater than start date.")]
    [JsonPropertyName("EndDate")]
    public DateTime EndDate { get; set; }
}

internal class DateGreaterThanAttribute : ValidationAttribute
{
    private readonly string _comparisonProperty;

    public DateGreaterThanAttribute(string comparisonProperty)
    {
        _comparisonProperty = comparisonProperty;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var endDate = (DateTime)value;
        DateTime startDateToCompare;

        // 获取HttpContext以读取路由参数
        var httpContextAccessor = validationContext.GetService<IHttpContextAccessor>();
        var httpContext = httpContextAccessor?.HttpContext;

        // 判断是否为更新场景(存在路由id)
        if (httpContext != null && httpContext.Request.RouteValues.TryGetValue("id", out var idObj) && idObj != null)
        {
            // 注入DbContext查询数据库中的原始合约数据
            var dbContext = validationContext.GetService<YourDbContext>();
            if (dbContext == null)
            {
                return new ValidationResult("Database context not available.");
            }

            // 解析id(根据实际类型调整,比如Guid、long等)
            if (!int.TryParse(idObj.ToString(), out var contractId))
            {
                return new ValidationResult("Invalid contract ID format.");
            }

            // 查询原始合约的StartDate
            var originalContract = dbContext.Contracts.AsNoTracking().FirstOrDefault(c => c.Id == contractId);
            if (originalContract == null)
            {
                return new ValidationResult("Contract not found in database.");
            }

            startDateToCompare = originalContract.StartDate;
        }
        else
        {
            // 创建场景(POST),使用传入模型中的StartDate
            var property = validationContext.ObjectType.GetProperty(_comparisonProperty);
            if (property == null)
            {
                throw new ArgumentException($"Comparison property '{_comparisonProperty}' not found on model.");
            }

            var comparisonValue = property.GetValue(validationContext.ObjectInstance);
            if (comparisonValue == null)
            {
                return new ValidationResult("StartDate cannot be null.");
            }

            startDateToCompare = (DateTime)comparisonValue;
        }

        // 执行日期比较逻辑
        if (endDate <= startDateToCompare)
        {
            return new ValidationResult(ErrorMessage ?? "EndDate must be greater than the start date.");
        }

        return ValidationResult.Success;
    }
}
  1. 注册必要服务
    在Program.cs中注册IHttpContextAccessor和你的DbContext,确保验证属性能获取到这些服务:
var builder = WebApplication.CreateBuilder(args);

// 注册HttpContext访问器
builder.Services.AddHttpContextAccessor();

// 注册DbContext(根据实际数据库类型调整)
builder.Services.AddDbContext<YourDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("YourConnectionString")));

// 其他服务注册...

var app = builder.Build();

// 中间件配置...

app.Run();

关键说明

  • 场景区分:通过检查路由中是否存在id参数,自动区分创建(POST)和更新(PUT)场景。
  • 原始数据获取:更新场景下直接从数据库查询原始合约的StartDate,避免使用PUT请求中可能被篡改的传入值。
  • 服务注入:利用ValidationContext.GetService()方法获取IHttpContextAccessor和DbContext,符合依赖注入原则。
  • 错误处理:添加了id解析失败、合约不存在等异常情况的验证错误返回,保证逻辑完整性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 22:31:03