2011-09-07 13 views
6

¿Cómo se crean las propiedades condicionalmente requeridas con el marco MVC 3 que funcionará con la Validación del lado del cliente y la Validación del lado del servidor cuando JS está deshabilitado? Por ejemplo:MVC 3 Propiedades condicionalmente requeridas

public class PersonModel 
{ 
    [Required] // Requried if Location is not set 
    public string Name {get; set;} 
    [Range(1, 5)] // Requried if Location is not set 
    public int Age {get; set;} 

    [Required] // Only required if Name and Age are not set. 
    public string Location {get; set;} 
} 

Las reglas en este ejemplo son: Es necesario

  1. Name y Age si Location no está establecida.
  2. Location es obligatorio solo si Name y Age no están configurados.
  3. No importa si el nombre, la edad y la ubicación están configurados.

En la vista, necesito el resultado enviado a Action si se configuran Nombre/Edad. Y un Action diferente si la Ubicación está configurada. Lo intenté con 2 formularios separados con diferentes Get Url's; esto funciona muy bien, excepto que las reglas de validación están causando problemas. Preferiblemente, me gustaría que el uso de la dirección URL del 2 Get acción separada, es decir,

@model PersonModel 

@using(Html.BeginForm("Age", "Person", FormMethod.Post)) 
{ 
    @Html.TextBoxFor(x => x.Name) 
    @Html.ValidationMessageFor(x => x.Name) 
    @Html.TextBoxFor(x => x.Age) 
    @Html.ValidationMessageFor(x => x.Age) 
    <input type="submit" value="Submit by Age" /> 
} 

@using(Html.BeginForm("Location", "Person", FormMethod.Post)) 
{ 
    @Html.TextBoxFor(x => x.Location) 
    @Html.ValidationMessageFor(x => x.Location) 
    <input type="submit" value="Submit by Location" /> 
} 

Sobre la base de la PersonModel anterior, si se presenta la ubicación, la validación fallará ya que el PersonModel espera que el nombre y la edad para ser establecer también. Y viceversa con Nombre/Edad.

Dado el ejemplo simulado anterior, ¿cómo se crean las propiedades requeridas condicionalmente con el marco MVC 3 que funcionarán con la Validación del lado del cliente y la Validación del lado del servidor cuando JS está deshabilitado?

Respuesta

1

Puede agregar una validación personalizada a su modelo, ya sea subclasificando ValidationAttribute o implementando IValidatableObject.

El ValidationAttribute le permite agregar la validación del lado del cliente de forma relativamente simple implementando IClientValidatable y registrando un nuevo adaptador y método a través de jQuery. Ver Perform client side validation for custom attribute.

IValidatableObject es más adecuado para los requisitos de validación de una sola vez donde la reutilización no es una opción. También da como resultado un código ligeramente más simple. Desafortunadamente, no hay una manera fácil de implementar la validación del lado del cliente usando este método.

0

He creado mi propio descendiente RequiredAttribute. Acepta un nombre de propiedad booleano, lo que debería ser la condición de la validación. Tenga en cuenta que este código no está listo para la producción, carece de verificación de errores y uno podría refinarse en la verificación de nulos.

[Localizable(false),AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 
public class RequiredIfAttribute : RequiredAttribute 
{ 
    public string BoolProperty { get; private set; } 
    public RequiredIfAttribute(string boolProperty) 
    { 
     BoolProperty = boolProperty; 
    } 

    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     if (!Equals(value, null) || !string.IsNullOrEmpty(value as string)) 
      return ValidationResult.Success; 
     var boolProperty = validationContext.ObjectInstance.GetType().GetProperty(BoolProperty); 
     var boolValue = (bool)boolProperty.GetValue(validationContext.ObjectInstance, null); 
     if (!boolValue) 
      return ValidationResult.Success; 
     return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); 
    } 
} 

Puede crear una propiedad de solo lectura para representar su condición como se muestra a continuación. También tenga en cuenta que la propiedad Age no puede estar "vacía" en su código. Si desea admitirlo, debe usar un tipo nullable int (int?) Para esa propiedad.

public class PersonModel 
{ 
    // helper properties 
    public bool LocationNotSet { get { return string.IsNullOrEmpty(Location); } }  
    public bool NameAndAgeNotSet { get { return string.IsNullOrEmpty(Name) && Age <= 0; } } 

    [RequiredIf("LocationNotSet")] // Requried if Location is not set 
    public string Name {get; set;} 
    [Range(1, 5), RequiredIf("LocationNotSet")] // Requried if Location is not set 
    public int Age {get; set;} 

    [RequiredIf("NameAndAgeNotSet")] // Only required if Name and Age are not set. 
    public string Location {get; set;} 
} 
Cuestiones relacionadas