2011-09-07 13 views
6

Jak utworzyć warunkowo wymagane właściwości za pomocą frameworka MVC 3, który będzie działał z funkcją sprawdzania po stronie klienta, a także sprawdzania poprawności po stronie serwera, gdy JS jest wyłączony? Na przykład:MVC 3 Warunkowo wymagane właściwości

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;} 
} 

Przepisy w tym przykładzie to:

  1. Name i Age są wymagane, jeśli Location nie jest ustawiony.
  2. Location jest wymagany tylko wtedy, gdy Name i Age nie są ustawione.
  3. Nie ma znaczenia, czy Imię, Wiek i Lokalizacja są ustawione.

W widoku potrzebny jest wynik wysłany do Action, jeśli ustawiono Name/Age. I inny Action, jeśli Lokalizacja jest ustawiona. Próbowałem z 2 oddzielnymi formularzami z różnymi adresami URL; działa to wspaniale, z wyjątkiem problemów powodujących reguły sprawdzania poprawności. Preferrably chciałbym korzystanie z 2 oddzielne działanie Get URL, czyli

@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" /> 
} 

Na podstawie powyższej PersonModel, jeśli lokalizacja jest złożony, walidacja nie powiedzie się, ponieważ PersonModel spodziewa się imię i wiek będzie również ustawić. I vice versa z Name/Age.

Biorąc powyższy przykład z kodem, w jaki sposób tworzysz warunkowo wymagane właściwości za pomocą frameworka MVC 3, który będzie działał z funkcją sprawdzania po stronie klienta, a także sprawdzania poprawności po stronie serwera, gdy JS jest wyłączony?

Odpowiedz

1

Możesz dodać niestandardową weryfikację do swojego modelu podklasy ValidationAttribute lub implementując IValidatableObject.

Pozwala na względnie proste dodanie walidacji po stronie klienta poprzez implementację IClientValidatable i zarejestrowanie nowego adaptera i metody za pośrednictwem jQuery. Zobacz Perform client side validation for custom attribute.

IValidatableObject jest bardziej odpowiedni do jednorazowych wymagań dotyczących walidacji, w przypadku których ponowne użycie nie jest możliwe. Powoduje to również uproszczony kod. Niestety, nie ma prostego sposobu na wdrożenie walidacji po stronie klienta przy użyciu tej metody.

0

Stworzyłem własnego potomka RequiredAttribute. Przyjmuje nazwę właściwości boolowskiej, która powinna być warunkiem sprawdzania poprawności. Zauważ, że ten kod nie jest gotowy do produkcji, brak jest sprawdzania błędów i można zrobić pewne dopracowanie przy sprawdzaniu zerowej wartości.

[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)); 
    } 
} 

Można by utworzyć właściwość tylko do odczytu do reprezentowania kondycję jak poniżej. Zwróć też uwagę, że właściwość Wiek nie może być "pusta" w twoim kodzie. Jeśli chcesz go wesprzeć, powinieneś użyć typu n (do?

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;} 
}