¿Cómo construir un validador personalizado para la validación de Castle en el lado del cliente?

StackOverflow https://stackoverflow.com/questions/8853768

  •  28-10-2019
  •  | 
  •  

Pregunta

Estoy usando la validación del castillo y me gustaría saber por qué mi validador no funciona:

[Serializable]
    public class PositiveIntegerValidator : AbstractValidator
    {


    public override bool IsValid(object instance, object fieldValue)
    {
        if (fieldValue == null || !(fieldValue is int))
            return false;
        return ((int)fieldValue) > 0;
    }

    public override bool SupportsBrowserValidation
    {
        get { return true; }
    }

    public override void ApplyBrowserValidation(BrowserValidationConfiguration config, InputElementType inputType, IBrowserValidationGenerator generator, System.Collections.IDictionary attributes, string target)
    {
        base.ApplyBrowserValidation(config, inputType, generator, attributes, target);


        generator.SetValueRange(target, 0,int.MaxValue, ErrorMessage);
    }

    protected override string BuildErrorMessage()
    {
        return ErrorMessage;
    }
}
public class ValidatePositiveIntegerAttribute : AbstractValidationAttribute
{
    public ValidatePositiveIntegerAttribute(string msg) :base(msg){}
    public override IValidator Build()
    {
        PositiveIntegerValidator positiveIntegerValidator = new PositiveIntegerValidator();
        ConfigureValidatorMessage(positiveIntegerValidator);
        return positiveIntegerValidator;
    }
}

Y mi campo

  public class PackageViewModel
        {
//            ...
            [ValidateNonEmpty,ValidatePositiveInteger("The package count must be positive")]
            public int nbPackage { get; set; }
//...
}

Y mi punto de vista

 $FormHelper.TextField("package.nbPackage","%{size='3',value='1'}")

ValidAtenonEpty Validate tanto en el lado del cliente como en el servidor, pero el ValidatePositiveInteger no lo es.

He visto este hilo Min Longitud personalizada AbstractValidationAttribute e implementando Castle.components.validator.ivalidator , pero no puedo ver ninguna diferencia entre mi código y el suyo.

¿Fue útil?

Solución

Finalmente lo encontré después de navegar en el código fuente de validación de Castle:

La validación predeterminada es prototypewebvalidator, y este validador utiliza prototypeValidationGenerator para la validación del lado del cliente, y esta implementación no hace nada cuando llama "setValuerge":

  public void SetValueRange(string target, int minValue, int maxValue, string violationMessage)
      {
      }

Entonces parece lógico que la validación del lado del cliente no esté funcionando (el prototypeValidationGenerator no implementó esta función principalmente porque la API de validación subyacente, https://github.com/atetlaw/Really-easy-field-validation no lo impidió también).

Así que decidí extender esto porque es un marco y es el propósito de un marco: proporcionar un marco y dejarle trabajar en él.

Entonces creé el generador

public class PrototypeValidationGeneratorExtension : PrototypeWebValidator.PrototypeValidationGenerator
{
    private PrototypeWebValidator.PrototypeValidationConfiguration _config;
    public PrototypeValidationGeneratorExtension(PrototypeWebValidator.PrototypeValidationConfiguration config, InputElementType inputType, IDictionary attributes)
        :base(config,inputType,attributes)
    {
        _config = config;
    }
    public new void SetValueRange(string target, int minValue, int maxValue, string violationMessage)
    {
                    this._config.AddCustomRule("validate-range",violationMessage,string.Format("min : {0}, max : {1}", minValue, maxValue));
    }
}

El validador proporciona alguna funcionalidad para agregar validación personalizada el validador que necesita FormHelper:

 public class PrototypeWebValidatorExtension : PrototypeWebValidator
{
    public new IBrowserValidationGenerator CreateGenerator(BrowserValidationConfiguration config, InputElementType inputType, IDictionary attributes)
    {
        return new PrototypeValidationGeneratorExtension((PrototypeWebValidator.PrototypeValidationConfiguration)config, inputType, attributes);
    }
}

Y cableas el castillo con tu validador en tu controlador base como este:

        protected override void Initialize()
        {
            ((FormHelper)this.Helpers["Form"]).UseWebValidatorProvider(new PrototypeWebValidatorExtension());
//    ...
    }

Tengo un controlador base, pero esta solución no es la mejor, pero no pude descubrir cómo inyectarlo en la configuración del monorraíl de Castle.

Intentaré cometer esto con la base de la fuente de Castle Monorail ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top