2011-10-20 7 views
5

¿Cómo puedo reemplazar los valores de rango con los valores de Web.Config en MVC3?Anotaciones de datos: ¿cómo puedo reemplazar los valores de rango con los valores de Web.Config en 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"/> 
+1

posible duplicado de [Anotación de datos/Validación y valores dinámicos] (http://stackoverflow.com/questions/2122161/data-annotation-validation-and-dynamic-values) –

Respuesta

7

Usted tendrá que crear un atributo personalizado que hereda de RangeAttribute e implementar 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) 
      ); 
     } 
    } 

Ejemplo de uso:

[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; } 

El primer ejemplo devolverá el mensaje de error por defecto, y el segundo le devolverá su mensaje de error personalizado. Ambos usarán los valores de rango definidos en web.config.

+0

¡Perfecto! Funcionó. Muchas gracias! – rk1962

+0

¡Eres genial! – rk1962

+0

Es genial para ser apreciado. ; ^> Gracias, y la mejor de las suertes. – counsellorben

4

Usted no será capaz de hacer eso en la declaración de atributo en la propiedad, es necesario conocer en tiempo de compilación de los valores. La manera más fácil que pude ver de hacer esto sería derivar una clase de atributo de RangeAttribute y configurar los valores de las propiedades para que provengan de web.config en la clase derivada. Algo así como

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

    } 
} 

posible que desee subir con un nombre mejor, aunque :)

+0

Muchas gracias. Acabo de crear una clase con el código anterior y no funcionó. ¿Me estoy perdiendo de algo? – rk1962

+0

Veré si puedo armar un ejemplo, aunque el código de counsellorben parece que funcionaría - http://stackoverflow.com/users/624472/counsellorben –

+0

@Russ Cam, me alegro de que alguien haya notado mi contribución. Aunque todavía tienes las golosinas. ;) – counsellorben

1

Pensando en voz alta aquí, pero el atributo ConfigRange dicta que la configuración debe estar presente para que esto funcione. ¿No puedes escribir una clase estática que pueda leer tus valores de web.config, app.config o lo que creas conveniente, y luego usar esa clase estática en el atributo de rango existente?

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

Entonces Anotar su propiedad con:

[Range(ConfigReader.Range1, 25.0d)] 

Sé que las clases estáticas son malas y no podrían muy bien ser una buena razón para no hacerlo, pero pensé que voy a dar una oportunidad.

+1

Creo que probé esto antes y no funcionó. – rk1962

+0

No tuve ningún error de compilación con un modelo de vista, pero no tuve la oportunidad de probarlo pasando un modelo de vista a la vista. ¿Puedes recordar por qué esto no funcionó? –

+0

Lo intentaré de nuevo y le dejaré saber el mensaje de error. ¡Gracias! – rk1962

Cuestiones relacionadas