2013-07-31 13 views
15

Mam widok modelu &, którego używam do edycji i wstawienia strony dla rekordu. Jednym z wymagań biznesowych jest to, że pewne pole jest wymagane przy edycji, ale nie w nowym. Początkowo zanim ta konkretna funkcja została dodana do zapisie, miałem model tak:Warunkowa walidacja na modelu w MVC

[Required(ErrorMessage = "*")] 
[Range(0.0, (double)decimal.MaxValue)] 
[DisplayName("Cost")] 
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)] 
public decimal ProposedCost { get; set; } 

chciałbym albo usunąć żądaną własność, czy jest to forma wkładka lub dodać go, jeśli formularz edycji. Jakie jest lepsze podejście? Cała moja inna walidacja jest wykonywana jak powyżej. Czy mogę zmienić stan modelu? Myśli?

EDIT

Coś powinienem wyjaśnić, że nadal są one dozwolone, aby dodać koszt na nowy, po prostu nie jest wymagana.

Odpowiedz

32

Jeśli korzystasz z MVC3/.NET4, możesz użyć IValidatableObject, który istnieje specjalnie do takich celów.

Cytowanie ScottGu,

... Interfejs IValidatableObject umożliwia wykonanie modelu poziomu walidacji i umożliwia dostarczenie wiadomości o błędach walidacji charakterystyczne dla stanu ogólnego modelu ....

modelować wyglądałby

public class MyViewModel : IValidatableObject 
{ 
    public long? Id { get; set; } 
    public decimal? ProposedCost { get; set; } 

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) 
    { 
     if (Id != null && ProposedCost == 0) { 
      yield return new ValidationResult("ProposedCost must be provided."); 
     } 
    } 
} 

a następnie w sterowniku,

[HttpPost] 
public ActionResult Submit(MyViewModel model) 
{ 
    if (!ModelState.IsValid) { 
     //failed - report an error, redirect to action etc 
    } 
    //succeeded - save to database etc 
} 

W przeciwnym razie, najbardziej czysty rozwiązaniem byłoby użyć widoku modele - UpdateViewModel gdzie wymagana jest własnością i CreateViewModel gdzie nie jest to wymagane.

+0

Próbowałem tego, jednak wciąż był w stanie zapisać rekord edycji bez proponowanego kosztu. Umieściłem punkt przerwania i uderzałem w Wynik Walidacji. Myśli? – Seth

+0

Czy na pewno sprawdzasz 'ModelState.IsValid'? Zaktualizowałem odpowiedź, aby pokazać przykład. Zwróć też uwagę, że 'ProposedCost' musi być zerowany, jeśli nie pozwala na ustawienie go. – andreister

+0

Tak, tęskniłem za tym, dobry połów. Pozostałe dodane właściwości automatycznie sprawdzają po stronie klienta. W każdym razie mogę to wykorzystać? Jest to oczywiście poza zakresem mojego pierwotnego pytania. – Seth

3

Można użyć atrybutu sprawdzania poprawności RequiredIf z projektu MVC Foolproof Validation. Używałem go w projektach, aby włączyć tylko te funkcje, których potrzebujesz.

Alternatywą byłoby użycie RemoteAttribute i wdrożenie logiki samodzielnie w metodzie.

+3

ja osobiście nie lubię 'RequiredIf' ponieważ nie typ bezpiecznie - musisz napisać' [RequiredIf ("SomeProperty", wartości, ...)] 'a oznacza, że ​​kompilator nie ostrzeże cię, gdy 'SomeProperty' zostanie przemianowany, ale stara nazwa utknęła w atrybucie – andreister

+0

@ireister, możesz użyć' [RequiredIf (nameof (SomeProperty), value, ...)] 'który daje ci kompilację Sprawdzanie czasu i radzi sobie ze zmianą nazwy 'SomeProperty' –

+0

Bardzo prawdziwa @JamesCulshaw - jedna z moich ulubionych funkcji C# 6, ponieważ pomaga w tym dokładnym scenariuszu. – christophano

0

Można spróbować na walidacji z:

ModelState.Remove("ProposedCost"); 

lub przedłużenia swój model tak:

public class NewModeViewModel : EditModeViewModel 
{ 
    public new decimal ProposedCost { get; set; } 
} 

i przejściu do widoku edycji.

4

Jest biblioteka MVC Niezawodny: http://foolproof.codeplex.com/

Na przykład trzeba by mieć coś takiego w swoim modelu

[RequiredIfTrue("Required", ErrorMessage = "*")] 
[Range(0.0, (double)decimal.MaxValue)] 
[DisplayName("Cost")] 
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)] 
public decimal ProposedCost { get; set; } 

public bool Required { get; set; } 

Będziesz wtedy trzeba ustawić właściwość Required na podstawie których forma model ma zamiar.

Potrzebne będzie również ukryte pole wejściowe w formularzu do reprezentowania właściwości Required, jeśli chcesz przeprowadzić walidację po stronie klienta.

nadzieję, że pomoże ...

Powiązane problemy