2012-08-13 9 views
6

Estamos tratando de crear alguna validación personalizada con anotaciones de datos MVC 4, la validación que estamos creando es una especie de mensaje más que una validación restrictiva. En primer lugar, hemos creado algunas clases de validación personalizadas heredadas de la clase ValidationAttribute y reemplazando el método IsValid() para probar los datos y devolver un ValidationResult si no es válido. La vista que muestra estos datos tiene vistas parciales que utilizan EditorTemplates para mostrar la maquinilla de afeitar generados datos utilizando nuestras anotaciones de datos personalizados y muchos construidos en la validación, todo esto está envuelto en una forma como estaMVC 4 Manual de anotación de datos personalizados Llamada de validación de jquery

@using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl })) 

Nuestros requisitos son para dejar el usuario después de vuelta los datos y guardar parcialmente las formas, pero los impulsan en cualquier campo no válidos por lo que están utilizando la clase CSS en el formulario de envío para permitir la devolución de datos al igual que

<input type="submit" value="Save" class="cancel"/> 

Todo esto está funcionando bien, pero que tenemos ahora requisitos para mostrar todos los mensajes de error en la página carga que no vi a ser un problema hasta que lo probé ...

me encontré con algunos ejemplos que utilizan jQuery en el evento ready $ (documento) que llama la forma de métodos válidos como se ve aquí

Manual form validation in MVC 3 and JQuery

pero esto no parece funcionar para nosotros el $ ('formulario'). Validate() no parece hacer nada, la única llamada que parece desencadenar la validación de formularios es $ ('form'). Valid() Pero esto solo parece mostrar la validación incorporada tal como los atributos [Requerido] y la única forma de mostrar los mensajes de validación personalizados es usar el botón de enviar para publicar de nuevo la forma.

Debe haber una manera de hacer que mis anotaciones de datos personalizados muestren los mensajes sin publicar la página la primera vez, ¿verdad? Cualquier ayuda sería muy apreciada.

Respuesta

6

Ok, he encontrado una manera de obtener el resultado que quería aunque era un poco más de lo que quería/imaginaba. Lo que me faltaba era no implantar IClientValidatable en mi clase de validación personalizada y tuve que agregar mi validación personalizada al método de validación jQuery Validator que probé pero no con el IClientValidatable implantado en la clase de validación personalizada, ejecutaré rápidamente a través de cómo conseguir este im trabajo suponiendo que tiene todas las cosas jQuery estableció/incluidos

en primer lugar crear el modelo simple que utiliza una validación de atributos personalizados

public class Person 
{ 
    [Required] 
    [Display(Name="Name")] 
    public string Name { get; set; } 
    public int Age { get; set; } 

    //Uses a custom data annotation that requires that at lease it self or the property name passed in the constructor are not empty 
    [OneOfTwoRequired("Mobile")] 
    public string Phone { get; set; } 
    [OneOfTwoRequired("Phone")] 
    public string Mobile { get; set; } 
} 

la clase de validación personalizada que utiliza la reflexión para obtener la propiedad del nombre de cadena pasado para probar con

Nota a partir del 15/08/2012: si está utilizando MVC 4, necesitará DE referenciado System.Web.Mvc 3.0 para el uso de IClientValidatable como ModelClientValidationRule no hace parece existir en MVC 4

public class OneOfTwoRequired : ValidationAttribute, IClientValidatable 
    { 
     private const string defaultErrorMessage = "{0} or {1} is required."; 

     private string otherProperty; 

     public OneOfTwoRequired(string otherProperty) 
      : base(defaultErrorMessage) 
     { 
      if (string.IsNullOrEmpty(otherProperty)) 
      { 
       throw new ArgumentNullException("otherProperty"); 
      } 

      this.otherProperty = otherProperty; 
     } 

     public override string FormatErrorMessage(string name) 
     { 
      return string.Format(ErrorMessageString, name, otherProperty); 
     } 

     protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
     { 
      PropertyInfo otherPropertyInfo = validationContext.ObjectInstance.GetType().GetProperty(otherProperty); 

      if (otherPropertyInfo == null) 
      { 
       return new ValidationResult(string.Format("Property '{0}' is undefined.", otherProperty)); 
      } 

      var otherPropertyValue = otherPropertyInfo.GetValue(validationContext.ObjectInstance, null); 

      if (otherPropertyValue == null && value == null) 
      { 
       return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName)); 
      } 

      return ValidationResult.Success; 
     } 
     public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
     { 
      yield return new ModelClientValidationRule 
      { 
       ErrorMessage = FormatErrorMessage(metadata.DisplayName), 
       //This is the name of the method aaded to the jQuery validator method (must be lower case) 
       ValidationType = "oneoftworequired" 
      }; 

     } 
    } 

Agregue esto a la Vista o vista parcial, debe asegurarse de que no esté en $ (documento).Método listo

jQuery.validator.addMethod("oneoftworequired", function (value, element, param) { 
     if ($('#Phone).val() == '' && $('#Mobile).val() == '') 
      return false; 
     else 
      return true; 
    }); 

    jQuery.validator.unobtrusive.adapters.addBool("oneoftworequired"); 

la materia validador jQuery sólo parece ser necesaria si se desea validar el formulario sin publicar espalda o al cargar la página inicial y al hacer eso que acaba de llamar $ ('forma'). válida()

Espero que esto ayude a alguien :)

0

Por qué es su código C# general, aplicable a cualquiera de los dos campos, mientras que el código de script está ligada específicamente a campos con identificadores de "#phone" y "#Mobile"? ¿No hay forma de generalizar el script también?

+0

err sí, podría utilizar scripts más genéricos, pero este era un caso en el que solo tendría 1 teléfono 1 elemento móvil por página, así que es genérico pero podría cambiar el ID de la clase if ($ ('. Option1 '). Val() ==' '&& $ ('. Option2 '). Val() ==' ') y eso sería más genérico que solo los tipos de teléfono. – Troublesum

Cuestiones relacionadas