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
相关产品推荐
相关产品推荐

