Invest in people before investing in tools

Il blog di Matteo Baglini
posts - 118, comments - 95, trackbacks - 697

[Spring.NET #26] Spring.Core, Validator Actions e Validation Errors

Altro nodo molto importante del Validation Framework sono le Validator Actions, le quali permettono di eseguire un operazione come consequenza del risultato della validazione. Lo scenario più frequente è quello di utilizzare una Error Message Actions per aggiugre un messaggio di errore alla collezione degli errori, gestita da Spring.NET. Nell'esempio mostrato nel primo post sul Validation Framework ho volutamente omesso questa parte per far capire meglio le due fasi distinte del processo di validazione, la prima dove vengono applicate le regole e la seconda dove vengono eseguite una serie di operazioni di conseguenza. Come intuibile la seconda fase è dipendente dalla prima quindi possiamo aggiungerla solo se necessaria o in un secondo momento come faremo noi in questo esempio. Le Validator Actions fornite built-in sono due, Error Message Actions, già descritto in precedenza ed il Generic Actions il quale permette di effettuare qualsiasi altro tipo di operazione, per tutte le esigenze che Spring.NET non riesce a coprire basterà creare una nostra classe implementando l'interfaccia IValidationAction. Nell'esempio di oggi aggiungeremo una Error Message Actions a tutte le regole di validazione. La sintassi è molto semplice basta utilizzare il tag ad-hoc message indicando gli attributi id, il quale corrisponderà all''id di un messaggio in una MessageSource (vedi post precedenti qui e qui) ed il tag providers il quale indica uno o più contenitori di errori, per indicarne più di uno e bastera utilizzare la virgola come separatore, in fine se dobbiamo passare dei parametri basterà utilizzare il tag param ed impostare il suo unico attributo value. Se vogliamo, anche per le Validator Actions possiamo utilizzare l'attributo when in modo da renderne condizionale l'esecuzione. Vediamo come risulterà il file di configurazione dopo aver aggiunto una MessageSource e tutte le Error Message Actions:

<object name="messageSource" type="Spring.Context.Support.ResourceSetMessageSource, Spring.Core">
  <property name="resourceManagers">
    <list>
      <ref object="messagesResourceManager" />
    </list>
  </property>
</object>
<object name="messagesResourceManager" type="Spring.Objects.Factory.Config.ResourceManagerFactoryObject, Spring.Core">
  <property name="baseName" value="SpringSeries.Core.ValidatorActions.Messages" />
  <property name="assemblyName" value="23.ValidatorActions" />
</object>
<v:group id="PersonValidator">
  <v:required id="PersonFirstNameValidator" test="FirstName" >
    <v:message id="error.person.firstname.required" providers="FirstNameMessage" />
  </v:required>
  <v:condition id="PersonDateOfBirthValidator" test="DateOfBirth != DateTime.MinValue" >
    <v:message id="error.person.dateofbirth.required" providers="DateOfBirthMessage" />
  </v:condition>
  <v:regex id="PersonFirstNameContentValidator" test="FirstName" >
    <v:property name="Expression" value="[A-Za-z]*" />
    <v:message id="error.person.firstname.content" providers="FirstNameMessage" />
  </v:regex>
  <v:ref name="AddressInfoValidator" />
</v:group>
<v:group id="AddressInfoValidator">
  <v:required id="CityValidator" test="AddressInfo.City" when="AddressInfo.Address!=String.Empty" >
    <v:message id="error.city.required" providers="CityMessage" />
  </v:required>
  <v:required id="CapValidator" test="AddressInfo.PostalCode" when="AddressInfo.Address!=String.Empty" >
    <v:message id="error.cap.required" providers="PostalCodeMessage" />
  </v:required>
</v:group>

proseguiamo aggingiamo un file di risorsa contenente le stringhe:

post_validator_actions

Spring.NET inserisce automaticamente i messaggi di errore dell'ultimo oggetto validato, raggruppandoli per providers, all'interno di un oggetto ValidationErrors, quindi all'interno della calsse Program aggiugiamo un metodo per stampare i messaggi a video:

   1:  private static void PrintErrors(IApplicationContext _ctx,ValidationErrors _errors) {
   2:      if (!_errors.IsEmpty) {
   3:   
   4:          foreach (string _provider in _errors.Providers) {
   5:              foreach (ErrorMessage _error in _errors.GetErrors(_provider)) {
   6:                  Console.WriteLine(_error.GetMessage((IMessageSource)_ctx.GetObject("messageSource")));
   7:              }
   8:          }
   9:   
  10:          Console.WriteLine();
  11:      }
  12:  }

questo metodo non fa altro che ciclare tutti i providers e richiedere i messaggi di errore per ogniuno di essi, in fine gli stampiamo a video utilizzando la MessageSource come "fonte dati". La stampa dei messaggi è così intrigata perchè sto utilizzando una Console Application, per la quale non esiste nessuna integrazione da parte di Spring.NET, nel caso di applicazioni WinForm o WebFrom il discorso cambia e possiamo agganciare l'error provider presente nella Form o nella Web Page ai providers indicati nel file di configurazione, quindi i messaggi di errore verranno direttamente renderizzati senza nessuno sforzo da parte nostra. Nei prossimi post vedremo come fare in modo da capire meglio l'argomento. Per finire non ci resta che modificare il metodo Main dei precedenti post sul Validation Framework aggiungendo, per ogni caso di validazione, una istanza di ValidationErrors e la chiamata al metodo PrintErrors:

   1:  static void Main(string[] args) {            
   2:      IApplicationContext _ctx = ContextRegistry.GetContext();
   3:   
   4:      IValidator _validator = (IValidator)_ctx.GetObject("PersonValidator");
   5:      ValidationErrors _errors1 = new ValidationErrors();
   6:      ValidationErrors _errors2 = new ValidationErrors();
   7:      ValidationErrors _errors3 = new ValidationErrors();
   8:      ValidationErrors _errors4 = new ValidationErrors();
   9:      ValidationErrors _errors5 = new ValidationErrors();
  10:      ValidationErrors _errors6 = new ValidationErrors();
  11:   
  12:      Person _p01 = new Person(1);
  13:      _p01.FirstName = "Matteo";
  14:      _p01.LastName = "Baglini";
  15:      _p01.DateOfBirth = new DateTime(1982, 11, 8);
  16:   
  17:      Person _p02 = new Person(2);
  18:      _p02.LastName = "Baglini";
  19:      _p02.DateOfBirth = new DateTime(1982, 11, 8);
  20:   
  21:      Person _p03 = new Person(3);
  22:      _p03.FirstName = "Matteo";
  23:      _p03.LastName = "Baglini";
  24:   
  25:      Person _p04 = new Person(4);
  26:      _p04.FirstName = "Matteo";
  27:      _p04.LastName = "Baglini";
  28:      _p04.DateOfBirth = new DateTime(1982, 11, 8);
  29:      _p04.AddressInfo.Address = "Via dei Sassi Sgonfi";
  30:   
  31:      Person _p05 = new Person(5);
  32:      _p05.FirstName = "Matteo";
  33:      _p05.LastName = "Baglini";
  34:      _p05.DateOfBirth = new DateTime(1982, 11, 8);
  35:      _p05.AddressInfo.Address = "Via dei Sassi Sgonfi";
  36:      _p05.AddressInfo.City = "Livorno";
  37:      _p05.AddressInfo.PostalCode = "57100";
  38:   
  39:      Person _p06 = new Person(6);
  40:      _p06.FirstName = "1234567890";
  41:      _p06.LastName = "Baglini";
  42:      _p06.DateOfBirth = new DateTime(1982, 11, 8);
  43:      _p06.AddressInfo.Address = "Via dei Sassi Sgonfi";
  44:      _p06.AddressInfo.City = "Livorno";
  45:      _p06.AddressInfo.PostalCode = "57100";
  46:   
  47:      Console.WriteLine(_p01.ToString());
  48:      Console.WriteLine("Is Valid? {0}", _validator.Validate(_p01, _errors1));
  49:      PrintErrors(_ctx,_errors1);
  50:      
  51:      Console.WriteLine();
  52:      Console.WriteLine(_p02.ToString());
  53:      Console.WriteLine("Is Valid? {0}", _validator.Validate(_p02, _errors2));
  54:      PrintErrors(_ctx, _errors2);
  55:   
  56:      Console.WriteLine();
  57:      Console.WriteLine(_p03.ToString());
  58:      Console.WriteLine("Is Valid? {0}", _validator.Validate(_p03, _errors3));
  59:      PrintErrors(_ctx, _errors3);
  60:   
  61:      Console.WriteLine();
  62:      Console.WriteLine(_p04.ToString());
  63:      Console.WriteLine("Is Valid? {0}", _validator.Validate(_p04, _errors4));
  64:      PrintErrors(_ctx, _errors4);
  65:   
  66:      Console.WriteLine();
  67:      Console.WriteLine(_p05.ToString());
  68:      Console.WriteLine("Is Valid? {0}", _validator.Validate(_p05, _errors5));
  69:      PrintErrors(_ctx, _errors5);
  70:   
  71:      Console.WriteLine();
  72:      Console.WriteLine(_p06.ToString());
  73:      Console.WriteLine("Is Valid? {0}", _validator.Validate(_p06, _errors6));
  74:      PrintErrors(_ctx, _errors6);
  75:      
  76:      Console.Read();
  77:  }
Technorati Tag:

Print | posted on domenica 23 dicembre 2007 19:25 | Filed Under [ .NET OpenSource Spring.NET ]

Powered by:
Powered By Subtext Powered By ASP.NET