具有外键的自定义验证属性重复项

时间:2019-08-31 23:31:26

标签: asp.net-core validationattribute

我有一个自定义验证属性,该属性用于防止使用EF Core服务器端在db表中重复输入。下面的代码在为包含字符串值的列(在本例中为MappingName列)分配自定义属性时效果很好-请参见数据库表图像。

如果用户尝试创建另一个系统映射,例如名称为“ Mapping 1”,那么自定义验证属性将向他们发出警告并停止将它们保存到数据库,这很好,但是我需要使用两个外键(整数值而不是字符串)和重复项的相同工作流进行此操作还有它们是外键的事实。

我需要解决的两列是:

ConnectorInboundID = 1 ConnectorOutboundID = 1 (其他表中的外键)

参考以下代码: 使用当前的自定义属性配置,模型类中的“ MappingName”列可以正常运行。

使用相同的自定义属性方法,外键列无法正常工作。

下面的图像仅显示了系统映射数据库表的设计布局:

database table

database table

模型类:

 public class SystemMapping
 {
     public int ID { get; set; } // Primary Key

     [Required]
     [CheckDuplicate(nameof(ID), ColumnName = "systemMappingName")] // This works well
     [Display(Name = "Mapping Name")]
     public string MappingName { get; set; }

     [Required]
     [CheckDuplicate(nameof(ID), ColumnName = "systemMappingInboundConnectorName")] // This does NOT work :(
     [Display(Name = "Connector In")]
     public int ConnectorInboundID { get; set; }
     [Display(Name = "Connector In")]
     public ConnectorInbound ConnectorInbound { get; set; }
  }

自定义验证属性类:

 public class CheckDuplicate : ValidationAttribute
 {
     private readonly string _IdPropertyName;

     public CheckDuplicate(string IdPropertyName)
     {
         _IdPropertyName = IdPropertyName;
     }

     public string ColumnName { get; set; }

     protected override ValidationResult IsValid(
    object value, ValidationContext validationContext)
    {
       // SystemMapping Model
        if (ColumnName == "systemMappingName") // System Mapping Name.
        {
            // ? is used in case the object 'value' is null.
            // This only happens when deleting a row from the database.
            string name = value?.ToString();

            var property = validationContext.ObjectType.GetProperty(_IdPropertyName);
            if (property != null)
            {
                var idValue = property.GetValue(validationContext.ObjectInstance, null);
                var _context = (ApplicationDbContext)validationContext.GetService(typeof(ApplicationDbContext));
            var exists = _context.SystemMapping.Any(d => d.MappingName == name && d.ID != int.Parse(idValue.ToString()));
            if (exists)
                return new ValidationResult("Name already in use...");

            return ValidationResult.Success;
            }

            // SystemMapping Model
            if (ColumnName == "systemMappingInboundConnectorName") // Inbound Connector Name.
            {
                // ? is used in case the object 'value' is null.
                // This only happens when deleting a row from the database.
                string name = value?.ToString();
                //int id = Convert.ToInt32(value); // This didnt work either...

                var property = validationContext.ObjectType.GetProperty(_IdPropertyName);
                if (property != null)
                {
                    var idValue = property.GetValue(validationContext.ObjectInstance, null);
                    var _context = (ApplicationDbContext)validationContext.GetService(typeof(ApplicationDbContext));
                    //var exists = _context.SystemMapping.Any(d => d.ConnectorInboundID == name && d.ID != int.Parse(idValue.ToString()));
                    var exists = _context.SystemMapping.Any(d => d.ConnectorInboundID == name && d.ID != int.Parse(idValue.ToString()));
                    if (exists)
                        return new ValidationResult("Connector already in use...");

                return ValidationResult.Success;
            }
        }
    }

我得到的错误警告与以下事实有关:自定义属性代码期望从模型类导入的对象“值”的字符串值,但我确实尝试修改自定义属性代码以更改对象值从字符串到整数,错误消失并允许我运行应用程序,没有任何调试错误,但是我发现在asp.net创建页面上创建新的系统映射时,该页面通常应将我定向到索引页面,其中列出了新添加的项目,但未添加任何内容。

下图显示了如果我尝试对这些外键列使用相同的方法,则会得到错误:

database table

我想找到一个解决方案,使我能够继续使用与普通字符串一样有效的方法,但是将其与整数值和/或可能正在尝试使用外键的事实一起使用正在引起问题。

0 个答案:

没有答案