Ich habe ein ViewModel, das einige DataAnnotations-Validierungen und dann für komplexere Validierungen IValidatableObject implementiert und die Validate-Methode verwendet.
Das Verhalten, das ich erwartet habe, war dieses : zuerst alle DataAnnotations und dann, nur wenn keine Fehler aufgetreten sind, die Validate-Methode. Wie auch immer ich finde, dass das nicht immer wahr ist. Mein ViewModel (ein Demo) hat drei Dateien eins string
, eins decimal
und eins decimal?
. Alle drei Eigenschaften haben nur Required-Attribut. Für string
und decimal?
ist das Verhalten das erwartete, aber für decimal
, wenn leer, ist die erforderliche Validierung fehlgeschlagen (soweit so gut) und führt dann die Validate-Methode aus. Wenn ich die Eigenschaft inspiziere, ist ihr Wert Null.
Was ist hier los? Was vermisse ich?
Hinweis : Ich weiß, dass das Attribut Required prüfen soll, ob der Wert null ist. Ich würde also erwarten, dass ich das Required-Attribut nicht in NULL-Typen verwenden kann (weil es nie ausgelöst wird), oder dass das Attribut irgendwie die POST-Werte versteht und dass das Feld nicht gefüllt ist. Im ersten Fall sollte das Attribut nicht ausgelöst werden und die Validate-Methode sollte ausgelöst werden. Im zweiten Fall sollte das Attribut ausgelöst werden und die Validate-Methode sollte nicht ausgelöst werden. Aber mein Ergebnis sind: Die Attribute triggert und die Validate-Methode wird ausgelöst.
Hier ist der Code (nichts besonderes):
Controller:
%Vor%Modell:
%Vor%ViewModel:
%Vor%Anzeigen:
%Vor%Überlegungen nach dem Austausch von Kommentaren:
Das einvernehmliche und erwartete Verhalten unter den Entwicklern ist die IValidatableObject
Methode Validate()
wird nur aufgerufen, wenn keine Validierungsattribute ausgelöst werden. Kurz gesagt, der erwartete Algorithmus ist dies (aus dem vorherigen Link):
Allerdings verwendet den Code der Frage, Validate
wird auch nach [Required]
triggers aufgerufen. Dies scheint ein offensichtlicher MVC-Fehler zu sein. Was hier gemeldet wird .
Drei mögliche Problemumgehungen:
Es gibt einen Workaround hier obwohl mit einigen erklärte Probleme mit seiner Verwendung, abgesehen von der MVC erwarteten Verhalten zu brechen. Mit ein paar Änderungen, um zu vermeiden, dass mehr als ein Fehler für das gleiche Feld angezeigt wird, ist hier der Code:
%Vor% Vergiss IValidatableObject
und verwende nur Attribute. Es ist sauber, direkt, besser zu lokalisieren und am besten wiederverwendbar unter allen Modellen. Implementieren Sie einfach ValidationAttribute für jede Validierung, die Sie durchführen möchten. Sie können das gesamte Modell oder bestimmte Eigenschaften validieren, das liegt an Ihnen. Abgesehen von den standardmäßig verfügbaren Attributen (DataType, Regex, Required und all diese Dinge) gibt es mehrere Bibliotheken mit den am häufigsten verwendeten Validierungen. Einer der die "fehlenden" implementiert, ist FluentValidation .
IValidatableObject
interface, das Datenannotationen beseitigt. Dies scheint eine vernünftige Option zu sein, wenn es sich um ein ganz bestimmtes Modell handelt und es nicht viel Validierung erfordert. In den meisten Fällen wird der Entwickler all diese reguläre und allgemeine Validierung durchführen (d. H. Erforderlich usw.), was zu Code-Duplizierung auf Validierungen führt, die bereits standardmäßig implementiert sind, wenn Attribute verwendet werden. Es gibt auch keine Wiederverwendbarkeit. Vor Kommentaren antworten:
Zuerst habe ich ein neues Projekt von Grund auf mit dem von Ihnen bereitgestellten Code erstellt. Es hat NIEMALS sowohl Datenannotationen als auch Validate-Methode ausgelöst.
Wie auch immer, weißt du das,
Vom Design her fügt MVC3 ein [Required]
-Attribut zu nicht-nullbaren Werttypen hinzu, wie int
, DateTime
oder ja, decimal
. Selbst wenn Sie das erforderliche Attribut aus diesem decimal
entfernen, funktioniert es genauso wie es dort ist.
Dies ist umstritten wegen seiner Unrichtigkeit (oder nicht), aber so, wie es entworfen wurde.
In Ihrem Beispiel:
decimal
. Dieses Verhalten scheint damit innerhalb Ihrer Application_Start-Methode ausgeschaltet zu sein:
%Vor%Ich denke, der Name der Eigenschaft ist selbsterklärend.
Wie auch immer, ich verstehe nicht, warum der Benutzer etwas eingeben soll, das nicht benötigt wird, und diese Eigenschaft nicht nullbar machen darf. Wenn es null ist, dann ist es Ihre Aufgabe, es zu überprüfen, wenn Sie es vor der Validierung im Controller nicht für null halten wollen
> %Vor%Was denkst du, ist es falsch bei diesem Ansatz oder sollte nicht so sein?
Tags und Links asp.net-mvc asp.net-mvc-3 asp.net data-annotations ivalidatableobject