2011-01-14 2 views
5

Ich lege eine Ansicht aus, die zwei Kennwortzeichenfolgen vergleicht. Die beiden Eigenschaften in einem meiner Modelle sind ziemlich einfach:Clientseitige Validierung für CompareAttribute DataAnnotation nicht ausgelöst

[Required] 
    [RegularExpression(@"(\S)+", ErrorMessage = "White space is not allowed")] 
    [StringLength(20, MinimumLength = 6)] 
    [DataType(DataType.Password)] 
    [Display(Name = "New Password")] 
    public string NewPassword { get; set; } 

    [Required] 
    [DataType(DataType.Password)] 
    [RegularExpression(@"(\S)+", ErrorMessage = "White space is not allowed")] 
    [StringLength(20, MinimumLength = 6)] 
    [Display(Name = "Confirm Password")] 
    [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] 
    public string ConfirmPassword { get; set; } 

Hier ist meine Ansicht Code:

<table class="fieldset center" width="400"> 
    <tbody> 
     <tr> 
      <th width="150"> 
       @Html.LabelFor(m => m.NewPassword) 
      </th> 
      <td> 
       @Html.PasswordFor(m => m.NewPassword, new { @class = "itext3" }) 
       <br /><br />@Html.ValidationMessageFor(m => m.NewPassword) 
      </td> 
     </tr>      
     <tr> 
      <th width="150"> 
       @Html.LabelFor(m => m.ConfirmPassword) 
      </th> 
      <td> 
       @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "itext3" }) 
       <br /><br />@Html.ValidationMessageFor(m => m.ConfirmPassword) 
      </td> 
     </tr> 
    </tbody> 
</table> 

Alle Attribute feuern ihre clientseitige Nachrichten Validierung, wenn getestet, mit Ausnahme der CompareAttribute auf ConfirmPassword, das nicht ausgelöst wird, bis ich den Server treffe. In meinem Controller ist jedoch ModelState.IsValid = false.

Ich verglich, was ich mache, mit der Standard-MVC-Anwendung, die korrekt funktioniert. Irgendwelche Vorschläge zur Fehlerbehebung und zur Behebung?

Ich benutze MVC 3 RTM.

Antwort

4

Werfen Sie einen Blick auf Ihre Skript-Tags in Ihrem _Layout.cshtml. Ich vermute, das Problem ist wahrscheinlich Ihre jQuery Referenzen. Haben Sie das MVC 3-Projekt Formular neu gestartet oder verwenden Sie ein Beispielprojekt oder etwas ähnliches?

Hier ist was passiert mit mir; Ich hatte ähnliche Probleme ...

  • ich einige Beispiel-Code wurde unter Verwendung, die ajax.microsoft.com im src-Attribute So
  • hingewiesen, zum Beispiel eines der Script-Tags sah wie folgt aus: <script src="http://ajax.microsoft.com/ajax/jquery.validate/1.7/jquery.validate.min.js"></script>
  • ich wollte auf einen besseren Griff bekommen, was js auf der Client-Seite ausgeführt wurde, so habe ich es dies: <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
  • das ist nur ein Beispiel, ich glaube, es gibt noch ein paar Script-Tags waren, die ich als gut
  • geändert

Also, nach dem Wechsel zu intern gedienten jQuery-Dateien hat es funktioniert. Ich ging zurück und schaute auf meine lokale .validate.js Datei ... und es war Version 1.6. Das ist, wie ich erkannte, dass das Problem wegen der Version von jQuery oder seiner Kompatibilität mit einer der anderen js Bibliotheken sowieso war.

Fazit ist, dass es aussieht wie 1.7 funktioniert nicht vollständig mit der validate.unobtrusive.js lib, die ich hatte ... es kann eine neuere Version, die mit 1,7 funktioniert ... wie ich schon sagte, ich Ich habe an einem Beispielprojekt herumgebastelt, also gibt es da einige Unbekannte. Ich nehme an, es könnte auch eine Inkompatibilität mit der MvcValidation.js-Lib zwischen ihm und einer der anderen js-Bibliotheken sein?

Auf jeden Fall würde ich sagen, der einfachste Weg, Ihr Problem zu nennen, ist, dass Sie wahrscheinlich eine schlechte Kombination von js libs referenzieren. Ich würde sagen, der beste Weg, um eine gute Kombination von js libs zu erhalten, ist ein neues Asp.Net MVC 3 Projekt in Visual Studio zu erstellen und zu sehen, welche Versionen es Ihnen standardmäßig/mit der Projektvorlage ... gibt dass du das Projekt nicht von Grund auf begonnen hast. Wenn Sie es von Grund auf neu gestartet haben, könnten Sie Ihre Layout-Datei geändert haben, um schlechte js-Referenzen zu haben, oder wenn nichts davon wahr ist, dann könnte es ein Problem mit den VisualStudio-Projektvorlagen sein? ... realistischerweise würde ich das sagen ist jedoch zweifelhaft. All das gesagt - ich würde sagen, der wahrscheinlichste Grund [auf den ich überhaupt wetten würde] ist, dass Sie gerade in Schwierigkeiten geraten sind, wie ich schnell einen Beispielcode verwenden wollte =)

+0

Das war es. Du hast tatsächlich zwei Probleme gelöst, die ich hatte. http://stackoverflow.com/questions/4752877/remote-validation-in-asp-net-mvc-3-how-to-use-additionalfields-in-action-method Wenn Sie dort drüben gehen und eine Antwort hinzufügen, die auf zeigt Diese Frage werde ich dir auch dort beantworten. DANKE! – beaudetious

1

ich dies mit ASP.NET MVC 3 RTM getestet haben und es funktionierte gut für mich:

Modell:

public class MyViewModel 
{ 
    [Required] 
    [RegularExpression(@"(\S)+", ErrorMessage = "White space is not allowed")] 
    [StringLength(20, MinimumLength = 6)] 
    [DataType(DataType.Password)] 
    [Display(Name = "New Password")] 
    public string NewPassword { get; set; } 

    [Required] 
    [DataType(DataType.Password)] 
    [RegularExpression(@"(\S)+", ErrorMessage = "White space is not allowed")] 
    [StringLength(20, MinimumLength = 6)] 
    [Display(Name = "Confirm Password")] 
    [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] 
    public string ConfirmPassword { get; set; } 
} 

Controller:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     return View(new MyViewModel()); 
    } 

    [HttpPost] 
    public ActionResult Index(MyViewModel model) 
    { 
     return View(model); 
    } 
} 

Ausblick:

@model SomeAppName.Models.MyViewModel 
@{ 
    ViewBag.Title = "Home Page"; 
} 
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> 
@using (Html.BeginForm()) 
{ 
    @Html.LabelFor(m => m.NewPassword) 
    @Html.PasswordFor(m => m.NewPassword) 
    @Html.ValidationMessageFor(m => m.NewPassword) 
    <br/> 

    @Html.LabelFor(m => m.ConfirmPassword) 
    @Html.PasswordFor(m => m.ConfirmPassword) 
    @Html.ValidationMessageFor(m => m.ConfirmPassword) 

    <br/> 
    <input type="submit" value="OK" /> 
} 

In dieser Konfiguration c liensidevalidierung funktioniert tadellos für alle Attribute einschließlich die [Compare].

+0

Das ist das gleiche, was ich auch bewiesen habe. Ich frage mich, was ich anders mache, das ist nicht offensichtlich? – beaudetious

+0

@beaudetious, es ist noch weniger offensichtlich für diejenigen von uns, die Ihren Quellcode nicht sehen können oder den Fehler, den Sie beschreiben, reproduzieren können. Was mir in den Sinn kommt, ist die Suche nach Javascript Fehlern mit FireBug. –

+0

Danke Danke. Wird besorgt. Wenn ich finde, dass es ein einfacher Fehler ist (99% Chance), werde ich Ihnen als Antwort antworten. – beaudetious

8

Es gibt einen Fehler in jquery .validate.unobtrusive.js (und jquery.validate.unobtrusive.min.js, die verkleinerte Version). Die clientseitige Validierung, die als Ergebnis des [Compare] -Attributs ausgegeben wird, funktioniert NUR, wenn das Vergleichsfeld das ERSTE Feld im Formular ist. Um diesen Fehler zu beheben, suchen Sie die folgende Zeile in jquery.validate.unobtrusive.js:

element = $(options.form).find(":input[name=" + fullOtherName + "]")[0]; 

, die in diesem gleichwertigen Ergebnissen:

element = $(options.form).find(":input[name=MyExample.Control]")[0]; 

leider das ist nicht die richtige Syntax für find() und Ursachen Es verweist auf das erste Eingabesteuerelement im Formular.

Änderung, die an der Leitung:

element = $(options.form).find(":input[name='" + fullOtherName + "']")[0]; 

, die in diesem gleichwertigen Ergebnissen:

element = $(options.form).find(":input[name='MyExample.Control]'")[0]; 

Welche ist die korrekte Syntax ist, und paßt richtig die Eingabesteuerung mit dem angegebenen Namen.

Suchen Sie den gleichen Code-Block in jquery.validate.unobtrusive.min.js, die wie folgt aussieht:

f=a(b.form).find(":input[name="+d+"]")[0]; 

und ändern Sie es zu:

f=a(b.form).find(":input[name='"+d+"']")[0]; 
+0

Perfekt. Dies sollte die Antwort sein! Ich habe Mark Shapiros Korrektur in jquery.validate.unobtrusive.min.js eingesetzt und verwende es zusammen mit jQuery 1.8.2 und jQuery Validation Plugin 1.9.0; wirkt als Charme :) – Kayes

1

ich war nie in der Lage zu machen der Standard Weg zu arbeiten. Es scheint, als ob in JQuery nur die Validierungsmethoden ausgelöst werden, die bei JQuery.validator registriert sind.

zunächst so etwas wie dieses war ich ... tun

jQuery.validator.unobtrusive.adapters.add("equaltopropertyvalidation", ["param"], function (rule) 
    { 
     alert("attaching custom validation adapter."); 
     rule.rules["equaltopropertyvalidation"] = rule.params.param; 
     rule.messages["equaltopropertyvalidation"] = rule.message; 

     return function (value, element, param) 
     { 
      alert("now validating!"); 
      return value == this.currentForm[param].value; 
     }; 
    }); 

Aber meine zweite alert (jetzt Validierung!) Würde nie, obwohl die erste würde schießen. Ich hatte this Artikel gesehen, aber ich zögerte, es so zu implementieren, weil es mich erfordert, etwas zu tun, aber ich war faul.

Nun, nachdem ich viel Zeit verbracht habe, um herauszufinden, was falsch ist, habe ich es in der Weise implementiert, wie dieser Artikel vorschlägt und es funktioniert. Jetzt ist es so und es funktioniert.

<script type="text/javascript"> 

    jQuery.validator.addMethod("equaltopropertyvalidation", function (value, element, param) 
    { 
     return value == this.currentForm[param].value; 
    }); 

    jQuery.validator.unobtrusive.adapters.add("equaltopropertyvalidation", ["param"], function (rule) 
    { 
     rule.rules["equaltopropertyvalidation"] = rule.params.param; 
     rule.messages["equaltopropertyvalidation"] = rule.message; 
    }); 

</script> 

Wenn Sie Detail dann hier ist es: in jquery.validate.js suchen und

 check: function (element) 

für die Suche Dies ist die Funktion, die durch, wenn das Feld gültig ist oder nicht zu überprüfen gebrannt Entlassung aller anwendbaren Regeln auf dem Feld.Jetzt erstellt er zuerst ein Array oder Regeln zum Feuern. Es tut das mit dem folgenden Code.

 var rules = $(element).rules(); 

Dann iteriert es die Regeln Sammlung über, schafft ein Regelelement für jedes Element in der Sammlung und dann versucht, ein entsprechendes Verfahren zu finden für diese Regel zu feuern. Sobald die Methode gefunden wurde, wird sie ausgelöst. Es tut das mit dem folgenden Code.

 var result = $.validator.methods[method].call(this, element.value.replace(/\r/g, ""), element, rule.parameters); 

Nun ist die wichtige Sache ist, dass, wenn Sie Ihre eigene Methode, um die $ .validator.methods Sammlung nicht hinzugefügt wird mit dem JQuery.validator.addMethod ES WIRD NICHT GEFUNDEN WERDEN, auch wenn es sitzt dort in den JQuery .validator.unobtrusive.adapters Sammlung.

Es könnte eine Möglichkeit geben, dies ohne die Verwendung der JQuery.validator.addMethod zu machen (und wenn ja, dann bitte jemand klarstellen), aber dies ist der Grund, warum der zweite Ansatz funktioniert und der erste nicht.

Ich wurde mit den folgenden Versionen von JQuery Dateien

  1. JQuery: 1.6/1.7.1
  2. Jquery.Validate: 1.9.0
  3. JQuery.Unobtrusive.Validate: genommen von Microsoft CDN auf 2/14/2012.