Custom ValidationAttribute:如何检查重复值,忽略正在编辑的对象

时间:2017-04-08 17:34:50

标签: asp.net asp.net-mvc validation validationattribute

我试图编写一个自定义ValidationAttribute,用于验证是否已存在具有相同值的记录。

问题是如果用户正在编辑现有记录,那么我的代码找到匹配相同值的记录。如果用户没有更改该值,它将找到正在编辑的那个。

所以我认为我可以将值与ValidationContext.ObjectInstance中的值进行比较,以检测它何时没有发生变化,如下所示:

public class UrlTagValidationAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext context)
    {
        string tag = value as string;
        if (string.IsNullOrWhiteSpace(tag))
            return new ValidationResult("URL Tag is required.");

        // We allow a valid that is equal to the original value
        if (context.ObjectInstance is TrainerModel model && model.Tag == tag)
            return ValidationResult.Success;

        // Cannot be an existing tag
        using (var dbContext = new OnBoard101Entities())
        {
            if (!dbContext.TrainerDetails.Any(td => td.Tag == tag))
                return ValidationResult.Success;
        }

        return new ValidationResult("This URL Tag is not available. Please enter a different one.");
    }
}

但这不起作用。我发现ValidationContext.ObjectInstance中的值经常与输入的值匹配,即使我创建了新记录。

我很难找到有关ValidationContext当前用法的最佳和最新文档。有人可以建议一种方法来检查是否存在与输入的值匹配的记录但是在编辑记录时允许它并且该字段的值没有改变?

1 个答案:

答案 0 :(得分:0)

当前正在编辑的项目最有可能具有某种属性来识别它(在数据库中查找)。因此,您需要获取该属性,以便在搜索数据库时查找重复的标记。以下是在自定义验证类中如何执行此操作。我假设标识符名为TrainerId

public class UrlTagValidationAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext context)
    {
        string tag = value as string;
        if(string.IsNullOrWhiteSpace(tag))
            return new ValidationResult("URL Tag is required.");

        var currentTrainer = validationContext.ObjectInstance 
                                 as TrainerModel;
        if (currentTrainer == null)
        {
            // What do you want to do? You cannot always return an error
            // because another type could be using this custom validation.
            // Or you can return an error. Depends on your requirements and 
            // and usage.
        }
        using(var dbContext = new OnBoard101Entities())
        {
            if(dbContext.TrainerDetails.Any(td => td.Tag == tag && td.TrainerId != 
                                            currentTrainer.TrainerId))
            {
                return new ValidationResult("This URL Tag is not available. Please enter a different one.");
            }
        }

        return ValidationResult.Success;
    }
}