Аннотации данных - Как я могу заменить значения диапазона значениями Web.Config в MVC3? - PullRequest
5 голосов
/ 21 октября 2011

Как заменить значения Range значениями Web.Config в MVC3?

[Range(5, 20, ErrorMessage = "Initial Deposit should be between $5.00 and $20.00")
public decimal InitialDeposit { get; set; }

web.config:

<add key="MinBalance" value="5.00"/>
<add key="MaxDeposit" value="20.00"/>

Ответы [ 3 ]

8 голосов
/ 21 октября 2011

Вам потребуется создать пользовательский атрибут, наследующий от RangeAttribute и реализующий IClientValidatable.

    public class ConfigRangeAttribute : RangeAttribute, IClientValidatable
    {
        public ConfigRangeAttribute(int Int) :
            base
            (Convert.ToInt32(WebConfigurationManager.AppSettings["IntMin"]),
             Convert.ToInt32(WebConfigurationManager.AppSettings["IntMax"])) { }

        public ConfigRangeAttribute(double Double) :
            base
            (Convert.ToDouble(WebConfigurationManager.AppSettings["DoubleMin"]),
             Convert.ToDouble(WebConfigurationManager.AppSettings["DoubleMax"])) 
        {
            _double = true;
        }

        private bool _double = false;

        public override string FormatErrorMessage(string name)
        {
            return String.Format(ErrorMessageString, name, this.Minimum, this.Maximum);
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule
            {
                ErrorMessage = FormatErrorMessage(this.ErrorMessage),
                ValidationType = "range",
            };
            rule.ValidationParameters.Add("min", this.Minimum);
            rule.ValidationParameters.Add("max", this.Maximum);
            yield return rule;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value == null)
                return null;

            if (String.IsNullOrEmpty(value.ToString()))
                return null;

            if (_double)
            {
                var val = Convert.ToDouble(value);
                if (val >= Convert.ToDouble(this.Minimum) && val <= Convert.ToDouble(this.Maximum))
                    return null;
            }
            else
            {
                var val = Convert.ToInt32(value);
                if (val >= Convert.ToInt32(this.Minimum) && val <= Convert.ToInt32(this.Maximum))
                    return null;
            }

            return new ValidationResult(
                FormatErrorMessage(this.ErrorMessage)
            );
        }
    }

Пример использования:

[ConfigRange(1)]
public int MyInt { get; set; }

[ConfigRange(1.1, ErrorMessage = "This one has gotta be between {1} and {2}!")]
public double MyDouble { get; set; }

В первом примере возвращается сообщение об ошибке по умолчанию, а во втором - пользовательское сообщение об ошибке.Оба будут использовать значения диапазона, определенные в web.config.

4 голосов
/ 21 октября 2011

Вы не сможете сделать это в объявлении атрибута свойства, так как значения должны быть известны во время компиляции. Самый простой способ сделать это - получить класс атрибута из RangeAttribute и установить значения свойств для web.config в производном классе. Что-то вроде

public class RangeFromConfigurationAttribute : RangeAttribute
{
    public RangeFromConfigurationAttribute()
        : base(int.Parse(WebConfigurationManager.AppSettings["MinBalance"]), int.Parse(WebConfigurationManager.AppSettings["MaxDeposit"]))
    {

    }
}

Может, хотелось бы придумать лучшее имя:)

1 голос
/ 21 октября 2011

Здесь мыслят вслух, но атрибут ConfigRange указывает, что конфиг должен присутствовать, чтобы это работало. Разве вы не можете написать статический класс, который будет считывать ваши значения из web.config, app.config или из того, что вы считаете нужным, а затем использовать этот статический класс в существующем атрибуте диапазона?

public static class RangeReader
{
    public static double Range1 
    {
        // Replace this with logic to read from config file
        get { return 20.0d; } 
    }        
}

Затем пометьте вашу собственность:

[Range(ConfigReader.Range1, 25.0d)]

Я знаю, что статические классы плохие, и вполне может быть веская причина, чтобы этого не делать, но я подумал, что попробую.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...