2011-02-25 21 views
7

Dopo l'aggiornamento a JQuery 1.5 e successive 1.5.1, la convalida del confronto non riesce. Sto usando JQuery.Validate 1.7. My ViewModel ha le seguenti annotazioni di dati:JQuery 1.5 interruzioni Confronta convalida (JQuery Validate 1.8)

/// <summary> 
/// Gets or sets the full name. 
/// </summary> 
/// <value>The full name.</value> 
[Required] 
[Display(Name = "fullname", ResourceType = typeof(Milkshake.Commerce.Model.Resources.Text))] 
public string FullName { get; set; } 

/// <summary> 
/// Gets or sets the email. 
/// </summary> 
/// <value>The email.</value> 
[DataType(DataType.EmailAddress)] 
[Display(Name = "email", ResourceType = typeof(Milkshake.Commerce.Model.Resources.Text))] 
[Required(ErrorMessageResourceName = "EmailRequired", ErrorMessageResourceType = typeof(Milkshake.Commerce.Model.Resources.ValidationMessages))] 
[RegularExpression(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", ErrorMessageResourceType = typeof(Milkshake.Commerce.Model.Resources.ValidationMessages), ErrorMessageResourceName = "EmailInvalid")] 
public string Email { get; set; } 

/// <summary> 
/// Gets or sets the password. 
/// </summary> 
/// <value>The password.</value> 
[DataType(DataType.Password)] 
[Display(Name = "password", ResourceType = typeof(Milkshake.Commerce.Model.Resources.Text))] 
[Required(ErrorMessageResourceName = "PasswordRequired", ErrorMessageResourceType = typeof(Milkshake.Commerce.Model.Resources.ValidationMessages))] 
[ValidatePasswordLengthAttribute(ErrorMessageResourceName = "PasswordLength", ErrorMessageResourceType = typeof(Milkshake.Commerce.Model.Resources.ValidationMessages))] 
public string Password { get; set; } 

/// <summary> 
/// Gets or sets the confirm password. 
/// </summary> 
/// <value>The confirm password.</value> 
[DataType(DataType.Password)] 
[Display(Name = "confirmPassword", ResourceType = typeof(Milkshake.Commerce.Model.Resources.Text))] 
[Required(ErrorMessageResourceName = "PasswordRequired", ErrorMessageResourceType = typeof(Milkshake.Commerce.Model.Resources.ValidationMessages))] 
[Compare("Password", ErrorMessageResourceName = "PasswordsMustMatch", ErrorMessageResourceType = typeof(Milkshake.Commerce.Model.Resources.ValidationMessages))] 
public string ConfirmPassword { get; set; } 

Con qualsiasi valore inserito, i campi della password non sono mai identici.

AGGIORNAMENTO - ASP.NET AntiForgeryToken si mette nei guai.

Dopo scherzare nella creazione di punti di interruzione Firebug, ho notato che nella funzione di validazione equalTo, a partire dal 1065 la linea nel jquery.validate.js, l'elemento di destinazione che si trova, non è il campo Password - ma il __RequestVerificationToken che Scritture ASP.NET MVC quando si utilizza l'helper Html.AntiForgeryToken().

Ciò significa che non stiamo nemmeno confrontando gli elementi di input corretti. Per ovviare a questo problema, ho aggiunto un hack sporco al file jquery.validate.js:

// http://docs.jquery.com/Plugins/Validation/Methods/equalTo 
equalTo: function (value, element, param) { 
    // bind to the blur event of the target in order to revalidate whenever the target field is updated 
    // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead 
    var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() { 
     $(element).valid(); 
    }); 

    if ($(target).is("input[type=hidden]") && $(target).attr("name") == "__RequestVerificationToken") { 
     var otherElementId = $(element).attr("id"); 
     var underScoreIndex = otherElementId.indexOf("_"); 
     otherElementId = otherElementId.substring(0, underScoreIndex + 1); 
     otherElementId += $(element).attr("data-val-equalto-other").substring(2); 

     target = $("#" + otherElementId); 
    } 

    return value == target.val(); 
} 

Questo mod, assume valore di data-val-equalTo-altro dell'attributo, e si mescola con il proprio ID, per trovare l'elemento di input corretto. Non funzionerà in tutti i casi. Ma lavora per me, nel caso di cui sopra.

risposta

11

ho trovato che questo è dovuto ad un errore nel jquery.validate.unobtrusive.js

Il codice in discreto aggiunge un adattatore equalTo che cerca di trovare l'elemento corrispondente dal suo attributo name, utilizzando il seguente codice:

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

la variabile fullOtherName è spesso (e probabilmente sempre) namespace con un periodo, in modo che il sele jQuery Ctor restituisce troppi input e seleziona il primo. Il periodo ha bisogno di essere fuggito con .Rimontare, dandovi ("" '\\.'):

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

Un costrutto simile esiste qualche riga più bassa, e dovrà anche essere fissato (come pure come il Javascript minorato).

+0

Funziona! Mi chiedo se questo bug è stato archiviato da qualche parte nell'universo di Microsoft. Dovrei segnalarlo tramite Microsoft Connect, in modo che venga risolto nella prossima versione. – MartinHN

+0

È stato corretto nel codice. Grazie. http://connect.microsoft.com/VisualStudio/feedback/details/665793/jquery-unobtrusive-validate-equalto-fails-with-compare-attribute – jsgoupil

+1

Questo è stato molto utile! Tuttavia, nel mio caso ho dovuto cambiarlo in element = $ (options.form) .find (": input [nome = '" + fullOtherName.replace (".", "\\.") + "']") [0]; annota le virgolette singole attorno al valore iniettato. E non dimenticare di sistemarlo nella versione minificata! :) –

0

Da http://bassistance.de/jquery-plugins/jquery-plugin-validation/

Attenzione: L'ultima versione non è, eppure , compatibile con jQuery 1.5.x. L'utente può trovare una versione compatibile nello GitHub repository.

Tuttavia, nessuno dei rami funziona per me ...

+0

In realtà, non ha nemmeno funzionato con 1.5. Immagino che dovremo aspettare che risolvano i problemi :( – MartinHN

+0

Ho trovato alcune nuove informazioni, guarda sopra. – MartinHN

+0

Cheers, Martin! Il mio problema è che non uso il token antiforgery ;-) –

0

In risposta all'aggiornamento di MartinHN, ho riscontrato lo stesso problema e ho applicato la stessa correzione. Poiché sto usando i modelli di editor nidificati, ho avuto più underscrores nel mio altroElementId e quindi ho cambiato il suo codice per usare lastIndexOf piuttosto che indexOf. Per esempio.

var underScoreIndex = otherElementId.indexOf("_"); 

è stato cambiato a:

var underScoreIndex = otherElementId.lastIndexOf("_"); 
0

Sembra che se si guarda al nuovo codice MVC4. Puoi vedere la nuova versione di jquery.validate.unobtrusive.js: http://code.msdn.microsoft.com/ASPNET-MVC-4-Mobile-e99ed0ed/sourcecode?fileId=49443&pathId=640259357 Se si fa un diff. È esattamente la stessa della versione MVC3 tranne che con le modifiche minori sopra menzionate fatte in un modo diverso. Quindi dovrebbe essere tutto quello che devi fare è sostituire il tuo jquery.validate.unobtrusive.js con quello nell'esempio di codice e tutto funzionerà.

Solo per quello che sai. Sto usando Jquery 1.6.4 con Jquery mobile 1.0.1

2

Se è ancora rilevante, ho avuto lo stesso problema, aggiornato tutti gli script e ora funziona. Sto usando il seguente: Jquery 1.8 (versione ufficiale dal loro cdn), validazione di Jquery 1.9 e validazione jQuery discreta dal pacchetto più recente fornito da microsoft su nunget (che, stranamente, ottiene validazione jquery 1.8 e non 1.9). Dio benedica Microsoft e il disordine che riesce a creare con 3 file di script: \

1

È possibile utilizzare le ultime versioni di jquery e jquery.validate dalla Microsoft CDN. Non riesco a vedere una versione aggiornata di jquery.validate.unobtrusive.min.js.

La versione di jquery.validate.unobtrusive.min.js fornita con MVC4 funziona correttamente.

<!-- Scripts --> 
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> 
<script type="text/javascript" src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.10.0/jquery.validate.min.js"></script> 
<!-- ToDo: Will Microsoft fix this on the CDN? --> 
<script type="text/javascript" src="@Url.Content("~/Scripts/Frameworks/jquery.validate.unobtrusive.min.js")"></script>