如何将参数传递到ValidationAttribute中?

5

我有一个自定义的ValidationAttribute,它检查是否已存在另一个用户。 为此,它需要访问我的数据访问层,这是通过Unity注入到我的控制器中的实例。

我应如何将此(或任何其他内容)作为参数传递给我的自定义验证程序?

这可能吗?即在创建Dal时,应该是一个参数。

public class EmailIsUnique : ValidationAttribute
    {
        private string _errorMessage = "An account with this {0} already exists";

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            DataAccessHelper Dal = new DataAccessHelper(SharedResolver.AppSettingsHelper().DbConnectionString); //todo, this is way too slow
            bool isValid = true;
            if(value == null) {
                isValid = false;
                _errorMessage = "{0} Cannot be empty";
            } else {
                string email = value.ToString();
                if (Dal.User.FindByEmail(email) != null)
                {
                    isValid = false;
                }
            }

            if (isValid)
                return ValidationResult.Success;
            else
                return new ValidationResult(String.Format(_errorMessage, validationContext.DisplayName));
        }
    }
3个回答

5

我不太确定您能否将运行时参数传递到属性中。

您可以使用DependencyResolver.Current.GetService<DataAccessHelper>()来解析dal(假设您已注册DataAccessHelper)

您可能更有可能将DataAccessHelper注册为IDataAccessHelper或其他内容?在这种情况下,您将调用GetService<IDataAccessHelper>

public class EmailIsUnique : ValidationAttribute
{
    private string _errorMessage = "An account with this {0} already exists";

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        IDataAccessHelper Dal = DependencyResolver.Current.GetService<IDataAccessHelper>(); // too slow
        bool isValid = true;
        if(value == null) {
            isValid = false;
            _errorMessage = "{0} Cannot be empty";
        } else {
            string email = value.ToString();
            if (Dal.User.FindByEmail(email) != null)
            {
                isValid = false;
            }
        }

        if (isValid)
            return ValidationResult.Success;
        else
            return new ValidationResult(String.Format(_errorMessage, validationContext.DisplayName));
    }
}

或者

public class EmailIsUnique : ValidationAttribute
{
    [Dependency]
    public IDataAccessHelper DataAccess {get;set;}

    private string _errorMessage = "An account with this {0} already exists";

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {

        bool isValid = true;
        if(value == null) 
        {
            isValid = false;
            _errorMessage = "{0} Cannot be empty";
        } 
       else 
       {
            string email = value.ToString();
            if (DataAccess.User.FindByEmail(email) != null)
            {
                isValid = false;
            }
        }

        if (isValid)
            return ValidationResult.Success;
        else
            return new ValidationResult(String.Format(_errorMessage, validationContext.DisplayName));
    }
}

抱歉,我想我的代码有点混乱。我需要在这里摆脱服务定位器模式,因为它在一个独立的项目中,只应该接收依赖项。看起来我可能需要将其从属性移动到一些自定义代码中。谢谢James,感激不尽! - williamsandonz
1
如果是这种情况,您可以考虑使用接口来抽象化您的数据访问层(DAL),并将该接口注册到您的IoC容器中。然后,在属性上方指定[Dependency],通过属性注入来使用IDataAccesHelper属性。 - Jamez
是的!我刚在外面散步时也想到了同样的策略(至少是第一部分)。关于第二部分,我不知道Unity有这个功能,太棒了,谢谢! - williamsandonz
我对构造函数不是100%确定,你可以试一下,但如果它不起作用,试试第二种方法。如果那也不行,第一种方法肯定会起作用。 - Jamez
抱歉,是属性的意思,有点喝醉了哈哈 :-) - williamsandonz

1
您可能正在寻找属性注入。请查看this帖子。 第一种解决方案是创建自定义过滤器提供程序,支持依赖项注入。
第二种解决方案是使用服务定位器模式,在属性构造函数中获取服务实例。

谢谢。我正在使用服务定位器模式,但不幸的是,我刚刚将我的模型移动到了一个数据访问项目中(为了关注点分离),而该项目不应该有自己的服务定位器。看起来你的链接可能会很有帮助,谢谢! - williamsandonz

0

是的,您可以将参数传递到模型类中,如下所示:

[EmailIsUnique()]
public string Email {get; set;}

这样将自动将电子邮件作为参数传递并检查其值。


抱歉,Vaibhav,我不是在寻找那个,我是想从模型外部动态注入变量。 - williamsandonz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接