martedì 5 febbraio 2013

Mvc - Rendere una checkbox obbligatoria

Per far si che in una pagina realizzata con il framework MCV, una checkbox sia obbligatoria, occorre un pò di lavoro. Nemmeno con la versione 4.5 di.NET sono stati capaci di rilasciare qualcosa che lo faccia in maniera semplice.

Prima di cominciare bisogna analizzare alcuni concetti di base:


  1. Una checkbox permette solo 2 valori: acceso o spento.
  2. Se si utilizza MVC, è bene che si sfrutti la logica dei modelli e delle annotazioni per segnare che una proprietà è obbligatoria.
  3. La validazione deve avvenire 2 volte, ovvero una volta lato "client", attraverso del javascript ed una seconda volta lato server, casomai il javascript avesse fatto cilecca o sia stato manomesso.

Per rappresentare la nostra proprietà useremo un valore booleano. Non esistendo una annotazione di base che permetta di definire che una proprietà booleana debba per forza essere essere uguale a "true", dobbiamo costruirla noi:


    public class BooleanRequiredAttribute 
                    : RequiredAttribute, IClientValidatable
    {
        /// <summary>
        /// Initializes a new instance of the 
        /// <see cref="BooleanRequiredAttribute" /> class.
        /// </summary>
        public BooleanRequiredAttribute() { }


        /// <summary>
        /// Checks that the value of the required data field is equal to true.
        /// </summary>
        /// <param name="value">The data field value to validate.</param>
        /// <returns>
        /// true if validation is successful; otherwise, false.
        /// </returns>
        public override bool IsValid(object value)
        {
            return value != null && (bool)value == true;
        }


        /// <summary>
        /// When implemented in a class, returns client validation rules                 /// for that class.
        /// </summary>
        /// <param name="metadata">The model metadata.</param>
        /// <param name="context">The controller context.</param>
        /// <returns>
        /// The client validation rules for this validator.
        /// </returns>
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(
            ModelMetadata metadata, ControllerContext context)
        {
            return new ModelClientValidationRule[] {
                new ModelClientValidationRule() { ValidationType = "mandatory"
                   ErrorMessage =  ErrorMessage}};
        }
    }



La nostra classe deve


  1. implementare la classe "IClientValidatable" in quanto dovremmo scrivere anche la parte di validazione lato "client"
  2. ereditare "RequiredAttribute" di modo da dover semplicemente fare un "override" del metodo "IsValid", dove restituiremo "true", solo se il valore della proprietà testata sarà "true"
  3. inventare una chiave per la validazione lato "client". In questo caso abbiamo scelto "mandatory", ma potete scegliere il nome che preferite.

A questo punto decorate la proprietà del modello con il nuovo attributo


        [BooleanRequiredAttribute]
        [DataType(DataType.Text)]
        public bool Privacy { get; set; }

e aggiungete il seguente script alla pagina:



(function ($) {
            $.validator.unobtrusive.adapters.add("mandatory", 
              function (options)         {
                options.rules["required"] = true;
 
                if (options.message) {
                    options.messages["required"] = options.message;
                }
            });
        } (jQuery));


e il gioco è fatto. Lato client si occuperà la libreria "jquery.validate" della validazione, mentre lato server se ne occuperà il framework MVC, richiamando nel metodo del controller la funzione "ModelState.IsValid"

es


  [HttpPost]
  public Save(Models.MyModel model)
  {
     if (ModelState.IsValid)
     {
        /* validazione riuscita */
     }
  }


Spero che questo articolo vi sia stato di aiuto.



Nessun commento:

Posta un commento