2010-08-27 23 views
10

Ho creato una sezione di configurazione personalizzata in una libreria di classi C# ereditando da ConfigurationSection. Faccio riferimento alla libreria di classi nella mia applicazione web (anche C#, ASP.NET), riempio gli attributi appropriati e tutto funziona alla grande. Il problema inizia quando inizio ad aggiungere i validatori.Perché StringValidator fallisce sempre per la sezione di configurazione personalizzata?

Per esempio, questa struttura:

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

Come funziona benissimo, ma non appena mi aggiungi a:

[StringValidator(MinLength=1)] 

bombarda con il seguente errore:

Il valore per la proprietà 'appCode' non è valido. L'errore è: la stringa deve essere lunga almeno 1 caratteri.

Viene visualizzato questo errore anche se un valore valido appCode è nel mio file web.config. Se rimuovo il validatore funziona perfettamente. Qualcuno sa come aggirare questo?

+0

Ho letto che tutta la serie, purtroppo non spiega il motivo per cui sto ricevendo l'errore. –

+1

Hai provato a inizializzare la proprietà ApplicationCode con un valore predefinito (valido)? Sembra che la regola di validazione non riesca ad un certo punto prima che il valore venga letto dal file di configurazione. – Shackles

+0

Sì, e funziona perfettamente con i valori predefiniti. Tuttavia, non tutti i campi hanno valori di default validi/ragionevoli, specialmente quelli opzionali, quindi è fastidioso che non riesca a inizializzarsi da configurazione. –

risposta

3

sono stato in grado di risolvere questo problema utilizzando un esplicito ConfigurationProperty come la chiave della mia proprietà collezione piuttosto che una stringa, secondo la seguente implementazione:

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

(Questo codice è strettamente modellato dopo il codice riflesso dalla classe dell'elemento di configurazione . Ancora desidero non dover duplicare le convalide, ma almeno questo codice mi consente di specificare un valore predefinito vuoto pur richiedendo un valore da inserire.)

+0

Hai ragione, vorrei non doverlo fare neanche io. L'ho provato e funziona, quindi grazie. –

+0

Ho passato un'intera giornata a combattere quel problema. Eccellente - questo ha fatto il trucco per me. –

3

Sembra che la risposta sia perché non hanno un valore predefinito. Sembra strano, quindi se qualcuno ha una risposta migliore fammi sapere e accetterò il loro.

2

I ha avuto questo problema per un po ', poi ho capito che i validatori a non per rendere l'attributo o gli elementi richiesti, servono per convalidarli.

Per rendere necessaria una proprietà è necessario utilizzare IsRequired e ConfigrationPropertyOptions.IsRequired, ad es.

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

Oppure (se si utilizza l'API)

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

In questo modo, il quadro di configurazione si occuperà della proprietà di essere in sé necessaria, e il validatore maniglie convalidare ciò che è nel valore. I validatori non sono pensati per fare qualcosa richiesto.

Questo funziona anche sugli elementi per rendere necessari elementi figlio. Per esempio. se stai creando una ConfigSection personalizzata con elementi figlio e hai bisogno di un elemento figlio da richiedere. Tuttavia, se si crea un CustomValidator che eredita da ConfigurationValidatorBase, è necessario utilizzare ElementInformation.IsPresent, ad es.

  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."); 
     } 

Per farla breve, vi manca la parte opzioni del tuo attributo per renderlo obbligatorio e non deve usare StringValidator (minLength = 1) per renderlo necessario. Infatti StringValidator (MinLength = 1) è completamente ridondante.Se lo rendi necessario è impossibile che MinLength = 1 fallisca senza il Required Failing first perché se è presente, è garantito che sia lungo almeno 1 carattere.

Cambia il tuo validatore per

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

Poi fosso il validatore stringa.

1

La risoluzione della StringValidator può essere fatto da uno dei seguenti modi:

  • Rimozione minLength argomento
  • Impostazione minLength = 0
  • Rimozione del StringValidator attributo
  • Aggiunta DefaultValue per l'attributo ConfigurationProperty

La definizione ideale per la proprietà è come:

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