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

ASP.NET Core自定义验证属性注入IJobRepository遇CS7036错误求助

问题分析与解决方案

错误原因

C# 特性(Attribute)的构造函数参数只能是编译时常量类型(如字符串、数值、枚举等),无法传入需要依赖注入的接口实例。这是因为特性在编译阶段就会被实例化并绑定到目标成员上,此时DI容器还未初始化,根本无法解析IJobRepository这类依赖,因此编译器会抛出CS7036错误。

另外你的原验证逻辑存在逻辑错误:原代码是检查数据库中所有数据是否存在重复电话号码,而非验证当前输入的号码是否重复,这会导致只要数据库里有重复数据,所有提交都会验证失败,不符合实际需求。


方案1:使用IValidatableObject实现Model验证

如果验证逻辑仅针对当前Model,推荐直接实现IValidatableObject接口,通过ValidationContext获取依赖服务:

using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;

public class JobModel : IValidatableObject
{
    [Required(ErrorMessage = "**Required**")]
    [Display(Name = "Customer Contact Number")]
    [DataType(DataType.PhoneNumber)]
    public string CustomerContactNumber { get; set; }

    // 如果是编辑场景,需要添加Id字段排除自身
    // public int Id { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        // 从验证上下文获取依赖服务
        var jobRepository = validationContext.GetService<IJobRepository>();
        if (jobRepository == null)
        {
            yield return new ValidationResult("无法完成电话号码验证:缺少数据存储依赖");
            yield break;
        }

        string inputPhone = CustomerContactNumber?.Trim();
        if (string.IsNullOrEmpty(inputPhone))
        {
            // 必填校验交给RequiredAttribute处理,这里直接跳过
            yield break;
        }

        // 验证逻辑:检查当前号码是否已存在(编辑场景需排除自身Id)
        var isDuplicate = jobRepository.AllJobs.Any(job => 
            job.CustomerContactNumber == inputPhone 
            // && job.Id != Id // 编辑场景添加此行排除当前实体
        );

        if (isDuplicate)
        {
            yield return new ValidationResult(
                "Duplicate Entry", 
                new[] { nameof(CustomerContactNumber) }
            );
        }
    }
}

方案2:修改自定义特性,通过ValidationContext获取依赖

如果需要复用该验证逻辑,可修改特性实现,重写带ValidationContext参数的IsValid重载:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
sealed public class TelephoneAttribute : ValidationAttribute
{
    // 移除带依赖的构造函数,改为无参构造
    public TelephoneAttribute() { }

    // 重写带ValidationContext的重载方法
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        string inputPhone = value?.ToString()?.Trim();
        if (string.IsNullOrEmpty(inputPhone))
        {
            // 必填校验交给RequiredAttribute处理,返回成功
            return ValidationResult.Success;
        }

        // 从上下文获取依赖服务
        var jobRepository = validationContext.GetService<IJobRepository>();
        if (jobRepository == null)
        {
            return new ValidationResult(ErrorMessage ?? "无法验证电话号码:缺少数据存储依赖");
        }

        // 正确的重复检查逻辑
        var isDuplicate = jobRepository.AllJobs.Any(job => 
            job.CustomerContactNumber == inputPhone);

        return isDuplicate 
            ? new ValidationResult(ErrorMessage ?? "Duplicate Entry") 
            : ValidationResult.Success;
    }
}

修改后在Model中即可正常使用:

[Required(ErrorMessage = "**Required**")]
[Display(Name = "Customer Contact Number")]
[DataType(DataType.PhoneNumber)]
[Telephone(ErrorMessage = "Duplicate Entry")] // 可省略Attribute后缀
public string CustomerContactNumber { get; set; }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 11:01:12