Mit validál a validator?

"Hát a Text property-t, nem?" Na ennyire nem egyszerű a helyzet, de kezdjük inkább az elején. Ha írunk egy saját kontrollt, majd feldobunk belőle egy példányt az egyik WebFormunkra, majd mellérakunk például egy RequiredFieldValidatort, akkor futtatáskor először a következő hibaüzenetet fogjuk kapni:

The ControlToValidate property of 'rfvPhone' cannot be blank.

Nincs semmi meglepetés, mindenki tudja, hogy a ControlToValidate tulajdonságot be kell állítani, mégis mindenki elfelejti az első fordítás előtt ;-) Amikor azonban megpróbáljuk beállítani ennek a tulajdonságnak az értékét, csalódottan fogjuk tapasztalni, hogy a Studioban a Properties ablakban nem tudjuk kiválasztani a saját vezérlőnket. Ne adjuk fel, bátran írjuk be a nevét mezőbe! Következő futtatás, következő hibaüzenet:

Control 'ctrlPhone' referenced by the ControlToValidate property of 'rfvPhone' cannot be validated.

Na, itt már valami gond van, nem lehet validálni a kontrollunkat. Idézzük fel, mit tanultunk a validátorokról: ha sajátot akarunk írni, akkor a BaseValidatorból kell származtatni kell és felül kell definiálni az EvaluateIsValid metódust. Nézzük mit találunk ebben, ha a RequiredFieldValidator az alany:

    protected override bool EvaluateIsValid()
    {
        string controlValidationValue = base.GetControlValidationValue( base.ControlToValidate );
        return ( ( controlValidationValue == null ) || 
!controlValidationValue.Trim().Equals( this.InitialValue.Trim() ) ); }

Az a bizonyos kutya tehát a BaseValidator osztály GetControlValidationValue metódusában van elásva, hantoljuk ki:

    protected string GetControlValidationValue( string name )
    {
        Control component = this.NamingContainer.FindControl( name );
        if( component == null )
        {
            return null;
        }
        PropertyDescriptor validationProperty = GetValidationProperty( component );
        if( validationProperty == null )
        {
            return null;
        }
        object obj2 = validationProperty.GetValue( component );
        if( obj2 is ListItem )
        {
            return ( (ListItem) obj2 ).Value;
        }
        if( obj2 != null )
        {
            return obj2.ToString();
        }
        return string.Empty;
    }

Tehát valahogy megszerezzük a tulajdonságot és elkérjük az értékét. Ha az érték típusa ListItem, akkor annak a Value tulajdonsága a fontos, egyébként egyszerűen megToStringezzük. Ebből tehát az következik, hogy bármilyen típusú tulajdonságot lehet validálni, hiszen ToString metódusa mindennek van.

Hogyan lesz meg a validálandó tulajdonság? A legelső sorban megkeressük magát a kontrollt. Itt érdemes megfigyelni, hogy csak az aktuális naming containeren belül keresünk, ezért kell a validátort a kontroll "közelébe" tenni. A keresett tulajdonságot a BaseValidator GetValidationProperty metódusa adja vissza, mégpedig így:

    public static PropertyDescriptor GetValidationProperty( object component )
    {
        ValidationPropertyAttribute attribute = 
(ValidationPropertyAttribute) TypeDescriptor.GetAttributes( component )[
typeof( ValidationPropertyAttribute ) ];
if( ( attribute != null ) && ( attribute.Name != null ) ) { return TypeDescriptor.GetProperties( component, (Attribute[]) null )[ attribute.Name ]; } return null; }

Keressük tehát azt a tulajdonságot, amelyet az osztályhoz rendelt ValidationPropertyAttribute Name tulajdonsága meghatároz. Magyarul nem csak a Text property-t lehet validálni, hanem bármit, csak mondjuk meg szegény validátornak, mégpedig a kontrollunkhoz rendelt attribútummal:

    [ValidationProperty( "LocalNumber" )]
    public partial class PhoneControl : System.Web.UI.UserControl
    {...}

Ha ezt megtesszük, eltűnik a hibaüzenet, a kontrollunkhoz már nyugodt szívvel tehetünk validátorokat. Ennek az attribútumnak egyébként a következő a szintaxisa az MSDN-ben:

    [AttributeUsageAttribute( AttributeTargets.Class )] 
    public sealed class ValidationPropertyAttribute : Attribute

Mivel az attribútumot osztályhoz rendeljünk és nem lehet több példányban felhasználni, csak egy tulajdonságot validálhatunk. Ha mégis megpróbáljuk többszörösen használni, fordítási hibát kapunk:

error CS0579: Duplicate 'ValidationProperty' attribute

Ezek után joggal merül fel a kérdés, vajon a Properties ablak is ez alapján dolgozik? Reflectorral megnézve a BaseValidator ControlToValidate tulajdonságát azt vehetjük észre, hogy egy ValidatedControlConverternevű TypeConverter van hozzárendelve, aminek a FilterControl metódusát a következőképpen implementálták:

    protected override bool FilterControl( Control control )
    {
        ValidationPropertyAttribute attribute = 
(ValidationPropertyAttribute) TypeDescriptor.GetAttributes( control )[
typeof( ValidationPropertyAttribute ) ];
if( attribute != null ) { return ( attribute.Name != null ); } return false; }

Tehát azok a kontrollok fognak kiválaszthatóként megjelenni a Properties ablakban a ControlToValidate tulajdonságnál, amelyekhez van ilyen attribútum és annak a Name tulajdonsága is meg van adva. Reflectorral keresgélve a következő típusokat és validálandó tulajdonságaikat találtam:

  • HtmlInputFile: Value
  • HtmlInputPassword: Value
  • HtmlInputText: Value
  • HtmlSelect: Value
  • HtmlTextArea: Value
  • DropDownList: SelectedItem
  • FileUpload: FileName
  • ListBox: SelectedItem
  • RadioButtonList: SelectedItem
  • TextBox: Text

Na, ezért nem tudunk validátort tenni egy CheckBoxListre, amikor rá akarjuk kényszeríteni a felhasználót, hogy legalább egy elemet válasszon ki.

Ennyi tudással felvértezve visszemehetünk a Properties ablakba és megnézhetjük, hogy már ki lehet-e választani a saját kontrollunkat a validálandó kontrollok listájából, majd joggal kérdezhetjük, hogy miért nem? Aki tudja, kérem írja meg. Köszönöm!



Balássy György (MS RD, ASP.NET MVP, MCTS)

Balássy György (MS RD, ASP.NET MVP, MCTS) Villamosmérnök, a BME Automatizálási és Alkalmazott Informatikai Tanszékén webportálok fejlesztését oktatja. 2000 óta foglalkozik a Microsoft .NET platformjával, melynek meghonosításában jelentős szerepet vállalt előadóként, konzulensként és A .NET Framework és programozása című könyv társszerzőjeként. Az MSDN Kompetencia Központon belül a Portál Technológiák Csoport vezetője, szakterülete web alapú rendszerek fejlesztése és üzemeltetése. 2004-ben Magyarországon elsőként kapta meg a Most Valuable Professional címet, majd 2005 óta a Microsoft magyarországi regionális igazgatója. Publikációi a Technet Magazinban, az MSDN Kompetencia Központ honlapján és szakmai blogjában olvashatóak.

2007.07.21. 1:04:01 | Permalink | Hozzászólások: 0 | Tárgyszavak: ,


  • Tipikus ASP.NET hozzáférési szintek

    Dávid Zoltán Az ASP.NET-es erőforrások (például aspx oldalak) a kezdetek óta védhetőek web.config-ban elhelyezett deklaratív bejegyzésekkel. Az IIS7 megjelenése óta az ilyen jellegű deklaratív védelem minden webes erőforrásnak (például PNG állományoknak) is alapértelmezetten kijár. Tovább »
  • Internet Explorer 6 DropDownList vs AJAX

    Dávid Zoltán Szerencsétlen hatos explorerben kicsit furcsán viselkednek a legördülőlisták. Legutóbb azzal borzolta az idegeimet, hogy ha volt ModalPopupExtender az oldalon és felbukkantottam .Show()-val, akkor ELTŰNT AZ ÖSSZES DropdownList. Nem is jelent meg soha többet, csak ha újratöltődött az oldal. Tovább »


Írja meg Ön is véleményét!


Hozzászólásokat csak regisztrált, bejelentkezett felhasználóktól tudunk elfogadni!

Hozzászólások