2010-08-27 40 views
10

Utworzono niestandardową sekcję konfiguracji w bibliotece klasy C# przez dziedziczenie z ConfigurationSection. Odwołuję się do biblioteki klas w mojej aplikacji internetowej (również C#, ASP.NET), wypełniam odpowiednie atrybuty i wszystko działa świetnie. Problem zaczyna się, gdy zacznę dodawać weryfikatory.Dlaczego StringValidator zawsze kończy się niepowodzeniem w sekcji konfiguracji niestandardowej?

Na przykład, ta właściwość:

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

Jak to działa dobrze, ale jak tylko dodam to:

[StringValidator(MinLength=1)] 

bombs z powodu następującego błędu:

Wartość właściwości "appCode" jest niepoprawna. Błąd: Ciąg musi mieć co najmniej 1 znak.

Otrzymuję ten błąd, mimo że ważna wartość appCode jest w moim pliku web.config. Jeśli usuniemy walidator, działa idealnie. Czy ktoś wie, jak sobie z tym poradzić?

+0

Czytałem, że cała seria, niestety to nie wyjaśnia, dlaczego otrzymuję błąd. –

+1

Czy próbowałeś zainicjować właściwość ApplicationCode z (poprawną) wartością domyślną? Wygląda na to, że reguła sprawdzania poprawności zawodzi w pewnym momencie, zanim wartość zostanie odczytana z pliku konfiguracyjnego. – Shackles

+0

Tak, i działa poprawnie z domyślnymi ustawieniami. Jednak nie wszystkie pola mają poprawne/sensowne wartości domyślne, szczególnie opcjonalne, więc irytujące jest to, że nie można go zainicjować z konfiguracji. –

Odpowiedz

3

udało mi się obejść ten problem za pomocą wyraźnego ConfigurationProperty jako klucz do mojego właściwości kolekcji zamiast łańcucha, zgodnie z poniższym realizacji:

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

(Kod ten jest ściśle wzorowany na kod odbity od klasy elementu konfiguracyjnego AssemblyInfo. Nadal chciałbym nie musieć duplikować moich sprawdzeń, ale przynajmniej ten kod pozwala mi określić pustą domyślną wartość, a jednocześnie wymagać podania wartości.)

+0

Masz rację, szkoda, że ​​nie musiałem tego robić. Próbowałem jednak i działa, więc dzięki. –

+0

Spędziłem cały dzień walcząc z tym problemem. Doskonale - to mi się udało. –

3

Wygląda na to, że odpowiedź jest istotna, ponieważ nie mają wartości domyślnej. Wydaje się dziwne, więc jeśli ktoś ma lepszą odpowiedź, daj mi znać, a ja zaakceptuję ich.

2

I miałem ten problem przez jakiś czas, a potem zdałem sobie sprawę, że walidatory a nie należy do tego, aby atrybut lub elementy były wymagane, ale służą do ich sprawdzania.

Aby utworzyć wymaganą właściwość, należy użyć obiektów IsRequired i ConfigrationPropertyOptions.IsRequired, np.

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

albo (w przypadku korzystania z interfejsu API)

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

Spowoduje to, ramy konfiguracji zajmie właściwość jest wymagana siebie, a walidator uchwyty walidacji co do wartości. Walidatory nie są przeznaczone do robienia czegoś wymaganego.

Dotyczy to również elementów wymagających elementów potomnych. Na przykład. jeśli tworzysz niestandardową konfigurację z elementami podrzędnymi i potrzebujesz wymaganego elementu podrzędnego. Jednak jeśli tworzysz CustomValidator, który dziedziczy z ConfigurationValidatorBase, musisz użyć elementu ElementInformation.IsPresent, np.

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

Krótko mówiąc, brakuje opcjach część swojego atrybutu, aby to wymagane i nie powinno się używać StringValidator MINLENGTH (= 1), aby to wymagane. W rzeczywistości StringValidator (MinLength = 1) jest całkowicie nadmiarowy.Jeśli to zrobisz, nie będzie możliwe, aby MinLength = 1 zakończyło się niepowodzeniem bez wymaganego niepowodzenia, ponieważ jeśli jest obecny, ma przynajmniej 1 znak.

Zmień walidator do

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

Następnie rowu walidator ciąg.

1

od rozwiązania StringValidator może być wykonane za pomocą jednego z następujących sposobów:

  • Usuwanie MINLENGTH argumentu
  • Ustawienie MINLENGTH = 0
  • Usuwanie StringValidator atrybut
  • Dodawanie DefaultValue na atrybut ConfigurationProperty

Idealna definicja nieruchomości jest tak:

[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; } 
} 
Powiązane problemy