2010-08-27 13 views
10

He creado una sección de configuración personalizada en una biblioteca de clases C# al heredar de ConfigurationSection. Hago referencia a la biblioteca de la clase en mi aplicación web (también C#, ASP.NET), completé los atributos adecuados y todo funciona bien. El problema comienza cuando comienzo a agregar validadores.¿Por qué StringValidator siempre falla en la sección de configuración personalizada?

Por ejemplo, esta propiedad:

[ConfigurationProperty("appCode", IsRequired = true)] 
    public string ApplicationCode 
    { 
     get 
     { 
      return (string)base["appCode"]; 
     } 
     set 
     { 
      base["appCode"] = value; 
     } 
    } 

Como es que trabaja muy bien, pero tan pronto como añado esto:

[StringValidator(MinLength=1)] 

bombardea con el siguiente error:

El valor de la propiedad 'appCode' no es válido. El error es: la cadena debe tener al menos 1 caracteres de longitud.

Recibo este error aunque haya un valor appCode válido en mi archivo web.config. Si elimino el validador, funciona perfectamente. ¿Alguien sabe cómo evitar esto?

+0

He leído que la serie entera, por desgracia, no explica por qué estoy recibiendo el error. –

+1

¿Ha intentado inicializar la propiedad ApplicationCode con un valor predeterminado (válido)? Parece que la regla de validación falla en algún momento antes de que se lea el valor del archivo de configuración. – Shackles

+0

Sí, y funciona bien con los valores predeterminados. Sin embargo, no todos los campos tienen valores predeterminados válidos/razonables, especialmente los opcionales, por lo que es molesto que no parezca inicializarse desde la configuración. –

Respuesta

3

que era capaz de solucionar este problema mediante el uso de una explícita ConfigurationProperty como la clave de mi colección de propiedades en lugar de una cadena, de acuerdo con la siguiente implementación:

public class AssemblyElement : ConfigurationElement 
{ 
    private static readonly ConfigurationProperty _propAssembly; 
    private static readonly ConfigurationPropertyCollection _properties; 

    static AssemblyElement() 
    { 
     _propAssembly = new ConfigurationProperty("assembly", typeof(string), null, null, new StringValidator(1), ConfigurationPropertyOptions.IsKey | ConfigurationPropertyOptions.IsRequired); 
     _properties = new ConfigurationPropertyCollection(); 
     _properties.Add(_propAssembly); 
    } 

    internal AssemblyElement() { } 
    public AssemblyElement(string assemblyName) 
    { 
     this.Assembly = assemblyName; 
    } 

    [ConfigurationProperty("assembly", IsRequired = true, IsKey = true, DefaultValue = "")] 
    [StringValidator(MinLength = 1)] 
    public string Assembly 
    { 
     get { return (string)base[_propAssembly]; } 
     set { base[_propAssembly] = value; } 
    } 

    internal AssemblyName AssemblyName 
    { 
     get { return new AssemblyName(this.Assembly); } 
    } 

    protected override ConfigurationPropertyCollection Properties 
    { 
     get { return _properties; } 
    } 
} 

(Este código está estrechamente el modelo de la código reflejado de la clase de elemento de configuración AssemblyInfo. Todavía me gustaría no tener que duplicar mis validaciones, pero al menos este código me permite especificar un valor predeterminado en blanco mientras se sigue requiriendo un valor para ser ingresado.)

+0

Tienes razón, ojalá no tuviera que hacer eso tampoco. Lo intenté y funciona, así que gracias. –

+0

He pasado todo un día luchando contra ese problema. Excelente, eso fue lo que hizo el truco para mí. –

3

parece que la respuesta es, en efecto, ya que no tienen un valor por defecto. Parece extraño, así que si alguien tiene una mejor respuesta házmelo saber y aceptaré la suya.

2

I tenido este problema por un tiempo, luego me di cuenta de que los validadores de No por hacer atributos o elementos requeridos, son para validarlos.

Para hacer que una propiedad necesaria que necesita para utilizar el isRequired y ConfigrationPropertyOptions.IsRequired, por ejemplo,

[ConfigurationProperty("casLogoutUrl", DefaultValue = null, IsRequired = true, Options = ConfigurationPropertyOptions.IsRequired)] 
[StringValidator(MinLength=10)] 

O (si se utiliza el API)

ConfigurationProperty casLoginUrl = new ConfigurationProperty("casLoginUrl", typeof(string), null, null, new StringValidator(1), ConfigurationPropertyOptions.IsRequired); 

Al hacer esto, el marco de configuración se encargará de la propiedad que se requiere en sí, y el validador mangos validar lo que está en el valor. Los validadores no están hechos para hacer algo requerido.

Esto también funciona en los elementos para que los elementos secundarios necesarios. P.ej. si está haciendo una ConfigSection personalizada con elementos secundarios y necesita un elemento secundario para ser necesario. Sin embargo, si crea un CustomValidator que hereda de ConfigurationValidatorBase, debe hacer uso de ElementInformation.IsPresent, p.

  public override void Validate(object value) 
     { 
      CredentialConfigurationElement element = (CredentialConfigurationElement)value; 
      if (!element.ElementInformation.IsPresent) 
       return; //IsRequired is handle by the framework, don't throw error here only throw an error if the element is present and it fails validation. 
      if (string.IsNullOrEmpty(element.UserName) || string.IsNullOrEmpty(element.Password)) 
       throw new ConfigurationErrorsException("The restCredentials element is missing one or more required Attribute: userName or password."); 
     } 

Para resumir, se echa en falta la parte de su atributo de opciones para que sea obligatorio y no debe utilizar StringValidator (MINLENGTH = 1) para que sea necesario. De hecho, StringValidator (MinLength = 1) es completamente redundante.Si lo hace necesario, es imposible que MinLength = 1 falle sin la falla obligatoria primero, porque si está presente, se garantiza que tendrá al menos 1 carácter de longitud.

Cambiar la validador para

[ConfigurationProperty("appCode", IsRequired = true, Options=ConfigurationPropertyOptions.IsRequired)] 

Entonces zanja el validador cadena.

1

La resolución del StringValidator se puede hacer por cualquiera de los siguientes:

  • Extracción minLength argumento
  • Configuración minLength = 0
  • Extracción de la Attribute StringValidator
  • Adición DefaultValue en ConfigurationProperty Attribute

La definición Ideal para la propiedad es como:

[ConfigurationProperty("title", IsRequired = true, DefaultValue = "something")] 
[StringValidator(InvalidCharacters = "[email protected]#$%^&*()[]{}/;’\"|\\" 
    , MinLength = 1 
    , MaxLength = 256)] 
public string Title 
{ 
    get { return this["title"] as string; } 
    set { this["title"] = value; } 
} 
Cuestiones relacionadas